21.27. "xmlrpc.server" --- Servidores XML-RPC básicos
*****************************************************

**Código Fonte:** Lib/xmlrpc/server.py

======================================================================

O módulo "xmlrpc.server" fornece um framework básico de servidor para
servidores XML-RPC escritos em Python. Os servidores podem ser
independentes, usando "SimpleXMLRPCServer", ou incorporados em um
ambiente CGI, usando "CGIXMLRPCRequestHandler".

Aviso:

  O módulo "xmlrpc.server" não é seguro contra dados criados com
  códigos maliciosos. Se você precisar analisar dados não confiáveis
  ou não autenticados, consulte XML vulnerabilities.

class xmlrpc.server.SimpleXMLRPCServer(addr, requestHandler=SimpleXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True, use_builtin_types=False)

   Cria uma nova instância do servidor. Esta classe fornece métodos
   para registro de funções que podem ser chamadas pelo protocolo XML-
   RPC. O parâmetro *requestHandler* deve ser uma fábrica para
   instâncias do tratador de solicitações; o padrão é
   "SimpleXMLRPCRequestHandler". Os parâmetros *addr* e
   *requestHandler* são passados ​​para o construtor
   "socketserver.TCPServer". Se *logRequests* for true (o padrão), as
   solicitações serão registradas; definir esse parâmetro como false
   desativará o log. Os parâmetros *allow_none* e *encoding* são
   transmitidos para "xmlrpc.client" e controlam as respostas XML-RPC
   que serão retornadas do servidor. O parâmetro *bind_and_activate*
   controla se "server_bind()" e "server_activate()" são chamados
   imediatamente pelo construtor; o padrão é true. A configuração como
   false permite que o código manipule a variável de classe
   *allow_reuse_address* antes que o endereço seja vinculado. O
   parâmetro *use_builtin_types* é passado para a função "loads()" e
   controla quais tipos são processados ​​quando valores de data/hora
   ou dados binários são recebidos; o padrão é false.

   Alterado na versão 3.3: O sinalizador *use_builtin_types* foi
   adicionado.

class xmlrpc.server.CGIXMLRPCRequestHandler(allow_none=False, encoding=None, use_builtin_types=False)

   Cria uma nova instância para manipular solicitações XML-RPC em um
   ambiente CGI. Os parâmetros *allow_none* e *encoding* são
   transmitidos para "xmlrpc.client" e controlam as respostas XML-RPC
   que serão retornadas do servidor. O parâmetro *use_builtin_types* é
   passado para a função "loads()" e controla quais tipos são
   processados quando valores de data/hora ou dados binários são
   recebidos; o padrão é false.

   Alterado na versão 3.3: O sinalizador *use_builtin_types* foi
   adicionado.

class xmlrpc.server.SimpleXMLRPCRequestHandler

   Cria uma nova instância do manipulador de solicitações. Este
   manipulador de solicitação possui suporte a solicitações "POST" e
   modifica o log para que o parâmetro *logRequests* para o construtor
   de "SimpleXMLRPCServer" seja respeitado.


21.27.1. Objetos de SimpleXMLRPCServer
======================================

A classe "SimpleXMLRPCServer" é baseada em "socketserver.TCPServer" e
fornece um meio de criar servidores XML-RPC simples e independentes.

SimpleXMLRPCServer.register_function(function, name=None)

   Register a function that can respond to XML-RPC requests.  If
   *name* is given, it will be the method name associated with
   *function*, otherwise "function.__name__" will be used.  *name* can
   be either a normal or Unicode string, and may contain characters
   not legal in Python identifiers, including the period character.

SimpleXMLRPCServer.register_instance(instance, allow_dotted_names=False)

   Registra um objeto que é usado para expor nomes de métodos que não
   foram registrados usando "register_function()". Se *instance*
   contiver um método "_dispatch()", ele será chamado com o nome do
   método solicitado e os parâmetros da solicitação. Sua API é "def
   _dispatch(self, method, params)" (observe que *params* não
   representa uma lista de argumentos variáveis). Se ele chama uma
   função subjacente para executar sua tarefa, essa função é chamada
   como "func(*params)", expandindo a lista de parâmetros. O valor de
   retorno de "_dispatch()" é retornado ao cliente como resultado. Se
   *instance* não possui o método "_dispatch()", é procurado por um
   atributo correspondente ao nome do método solicitado.

   Se o argumento opcional *allow_dotted_names* for true e a instância
   não tiver o método "_dispatch()", se o nome do método solicitado
   contiver pontos, cada componente do nome do método será pesquisado
   individualmente, com o efeito de que um simples pesquisa
   hierárquica é realizada. O valor encontrado nessa pesquisa é
   chamado com os parâmetros da solicitação e o valor retornado é
   passado de volta ao cliente.

   Aviso:

     A ativação da opção *allow_dotted_names* permite que os invasores
     acessem as variáveis globais do seu módulo e podem permitir que
     os invasores executem códigos arbitrários em sua máquina. Use
     esta opção apenas em uma rede fechada e segura.

SimpleXMLRPCServer.register_introspection_functions()

   Registradores de funções de introspecção XML-RPC
   "system.listMethods", "system.methodHelp" e
   "system.methodSignature".

SimpleXMLRPCServer.register_multicall_functions()

   Registra a função de multichamada XML-RPC system.multicall.

SimpleXMLRPCRequestHandler.rpc_paths

   Um valor de atributo que deve ser uma tupla listando partes do
   caminho válidas da URL para receber solicitações XML-RPC.
   Solicitações postadas em outros caminhos resultarão em um erro HTTP
   404 "página inexistente". Se esta tupla estiver vazia, todos os
   caminhos serão considerados válidos. O valor padrão é "('/',
   '/RPC2')".


21.27.1.1. Exemplo de SimpleXMLRPCServer
----------------------------------------

Código do servidor:

   from xmlrpc.server import SimpleXMLRPCServer
   from xmlrpc.server import SimpleXMLRPCRequestHandler

   # Restrict to a particular path.
   class RequestHandler(SimpleXMLRPCRequestHandler):
       rpc_paths = ('/RPC2',)

   # Create server
   with SimpleXMLRPCServer(("localhost", 8000),
                           requestHandler=RequestHandler) as server:
       server.register_introspection_functions()

       # Register pow() function; this will use the value of
       # pow.__name__ as the name, which is just 'pow'.
       server.register_function(pow)

       # Register a function under a different name
       def adder_function(x,y):
           return x + y
       server.register_function(adder_function, 'add')

       # Register an instance; all the methods of the instance are
       # published as XML-RPC methods (in this case, just 'mul').
       class MyFuncs:
           def mul(self, x, y):
               return x * y

       server.register_instance(MyFuncs())

       # Run the server's main loop
       server.serve_forever()

O código do cliente a seguir chamará os métodos disponibilizados pelo
servidor anterior:

   import xmlrpc.client

   s = xmlrpc.client.ServerProxy('http://localhost:8000')
   print(s.pow(2,3))  # Returns 2**3 = 8
   print(s.add(2,3))  # Returns 5
   print(s.mul(5,2))  # Returns 5*2 = 10

   # Print list of available methods
   print(s.system.listMethods())

O exemplo a seguir incluído no módulo "Lib/xmlrpc/server.py" mostra um
servidor que permite nomes com pontos e registra uma função de várias
chamadas.

Aviso:

  A ativação da opção *allow_dotted_names* permite que os invasores
  acessem as variáveis globais do seu módulo e podem permitir que os
  invasores executem códigos arbitrários em sua máquina. Use este
  exemplo apenas em uma rede fechada e segura.

   import datetime

   class ExampleService:
       def getData(self):
           return '42'

       class currentTime:
           @staticmethod
           def getCurrentTime():
               return datetime.datetime.now()

   with SimpleXMLRPCServer(("localhost", 8000)) as server:
       server.register_function(pow)
       server.register_function(lambda x,y: x+y, 'add')
       server.register_instance(ExampleService(), allow_dotted_names=True)
       server.register_multicall_functions()
       print('Serving XML-RPC on localhost port 8000')
       try:
           server.serve_forever()
       except KeyboardInterrupt:
           print("\nKeyboard interrupt received, exiting.")
           sys.exit(0)

Esta demonstração ExampleService pode ser chamada na linha de comando:

   python -m xmlrpc.server

O cliente que interage com o servidor acima está incluído em
*Lib/xmlrpc/client.py*:

   server = ServerProxy("http://localhost:8000")

   try:
       print(server.currentTime.getCurrentTime())
   except Error as v:
       print("ERROR", v)

   multi = MultiCall(server)
   multi.getData()
   multi.pow(2,9)
   multi.add(1,2)
   try:
       for response in multi():
           print(response)
   except Error as v:
       print("ERROR", v)

Este cliente que interage com o servidor XMLRPC de demonstração pode
ser chamado como:

   python -m xmlrpc.client


21.27.2. CGIXMLRPCRequestHandler
================================

The "CGIXMLRPCRequestHandler" class can be used to  handle XML-RPC
requests sent to Python CGI scripts.

CGIXMLRPCRequestHandler.register_function(function, name=None)

   Register a function that can respond to XML-RPC requests. If
   *name* is given, it will be the method name associated with
   function, otherwise *function.__name__* will be used. *name* can be
   either a normal or Unicode string, and may contain  characters not
   legal in Python identifiers, including the period character.

CGIXMLRPCRequestHandler.register_instance(instance)

   Registra um objeto que é usado para expor nomes de métodos que não
   foram registrados usando "register_function()". Se a instância
   contiver um método "_dispatch()", ela será chamada com o nome do
   método solicitado e os parâmetros da solicitação; o valor retornado
   é retornado ao cliente como resultado. Se a instância não tiver um
   método "_dispatch()", será procurado um atributo correspondente ao
   nome do método solicitado; se o nome do método solicitado contiver
   pontos, cada componente do nome do método será pesquisado
   individualmente, com o efeito de que uma pesquisa hierárquica
   simples é executada. O valor encontrado nessa pesquisa é chamado
   com os parâmetros da solicitação e o valor retornado é passado de
   volta ao cliente.

CGIXMLRPCRequestHandler.register_introspection_functions()

   Registra as funções de introspecção XML-RPC "system.listMethods",
   "system.methodHelp" e "system.methodSignature".

CGIXMLRPCRequestHandler.register_multicall_functions()

   Registra a função de multichamada XML-RPC "system.multicall".

CGIXMLRPCRequestHandler.handle_request(request_text=None)

   Manipula uma solicitação XML-RPC. Se *request_text* for fornecido,
   devem ser os dados POST fornecidos pelo servidor HTTP, caso
   contrário, o conteúdo do stdin será usado.

Exemplo:

   class MyFuncs:
       def mul(self, x, y):
           return x * y


   handler = CGIXMLRPCRequestHandler()
   handler.register_function(pow)
   handler.register_function(lambda x,y: x+y, 'add')
   handler.register_introspection_functions()
   handler.register_instance(MyFuncs())
   handler.handle_request()


21.27.3. Documentando servidor XMLRPC
=====================================

Essas classes estendem as classes acima para servir a documentação
HTML em resposta a solicitações HTTP GET. Os servidores podem ser
independentes, usando "DocXMLRPCServer" ou incorporados em um ambiente
CGI, usando "DocCGIXMLRPCRequestHandler".

class xmlrpc.server.DocXMLRPCServer(addr, requestHandler=DocXMLRPCRequestHandler, logRequests=True, allow_none=False, encoding=None, bind_and_activate=True, use_builtin_types=True)

   Cria uma nova instância do servidor. Todos os parâmetros têm o
   mesmo significado que para "SimpleXMLRPCServer"; *requestHandler*
   assume como padrão "DocXMLRPCRequestHandler".

   Alterado na versão 3.3: O sinalizador *use_builtin_types* foi
   adicionado.

class xmlrpc.server.DocCGIXMLRPCRequestHandler

   Cria uma nova instância para manipular solicitações XML-RPC em um
   ambiente CGI.

class xmlrpc.server.DocXMLRPCRequestHandler

   Cria uma nova instância do manipulador de solicitações. Este
   manipulador de solicitações possui suporte a solicitações POST de
   XML-RPC, documenta solicitações GET e modifica o log para que o
   parâmetro *logRequests* no parâmetro "DocXMLRPCServer" seja
   respeitado.


21.27.4. Objetos de DocXMLRPCServer
===================================

A classe "DocXMLRPCServer" é derivada de "SimpleXMLRPCServer" e
fornece um meio de criar servidores XML-RPC autodocumentados e
independentes. Solicitações HTTP POST são tratadas como chamadas de
método XML-RPC. As solicitações HTTP GET são tratadas gerando
documentação HTML no estilo pydoc. Isso permite que um servidor
forneça sua própria documentação baseada na Web.

DocXMLRPCServer.set_server_title(server_title)

   Define o título usado na documentação HTML gerada. Este título será
   usado dentro do elemento "title" do HTML.

DocXMLRPCServer.set_server_name(server_name)

   Define o nome usado na documentação HTML gerada. Este nome
   aparecerá na parte superior da documentação gerada dentro de um
   elemento "h1".

DocXMLRPCServer.set_server_documentation(server_documentation)

   Define a descrição usada na documentação HTML gerada. Esta
   descrição aparecerá como um parágrafo, abaixo do nome do servidor,
   na documentação.


21.27.5. DocCGIXMLRPCRequestHandler
===================================

A classe "DocCGIXMLRPCRequestHandler" é derivada de
"CGIXMLRPCRequestHandler" e fornece um meio de criar scripts CGI XML-
RPC autodocumentados. Solicitações HTTP POST são tratadas como
chamadas de método XML-RPC. As solicitações HTTP GET são tratadas
gerando documentação HTML no estilo pydoc. Isso permite que um
servidor forneça sua própria documentação baseada na web.

DocCGIXMLRPCRequestHandler.set_server_title(server_title)

   Define o título usado na documentação HTML gerada. Este título será
   usado dentro do elemento "title" do HTML.

DocCGIXMLRPCRequestHandler.set_server_name(server_name)

   Define o nome usado na documentação HTML gerada. Este nome
   aparecerá na parte superior da documentação gerada dentro de um
   elemento "h1".

DocCGIXMLRPCRequestHandler.set_server_documentation(server_documentation)

   Define a descrição usada na documentação HTML gerada. Esta
   descrição aparecerá como um parágrafo, abaixo do nome do servidor,
   na documentação.
