"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 Vulnerabilidades em XML.

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á os registros. 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 registro para que o parâmetro *logRequests* para o
   construtor de "SimpleXMLRPCServer" seja respeitado.


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=None, name=None)

   Registra uma função que possa responder às solicitações XML-RPC. Se
   *name* for fornecido, será o nome do método associado a *function*,
   caso contrário, "function.__name__" será usado. *name* é uma string
   e pode conter caracteres ilegais para identificadores Python,
   incluindo o caractere de ponto.

   Este método também pode ser usado como um decorador. Quando usado
   como decorador, *name* só pode ser fornecido como argumento nomeado
   para registrar *function* em *name*. Se nenhum *name* for
   fornecido, "function.__name__" será usado.

   Alterado na versão 3.7: "register_function()" pode ser usado como
   um decorador.

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()", e 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()

   Registra as 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')".


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())

"register_function()" também pode ser usado como um decorador. O
exemplo anterior do servidor pode registrar funções com um decorador:

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

   class RequestHandler(SimpleXMLRPCRequestHandler):
       rpc_paths = ('/RPC2',)

   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, using
       # register_function as a decorator. *name* can only be given
       # as a keyword argument.
       @server.register_function(name='add')
       def adder_function(x, y):
           return x + y

       # Register a function under function.__name__.
       @server.register_function
       def mul(x, y):
           return x * y

       server.serve_forever()

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


CGIXMLRPCRequestHandler
=======================

A classe "CGIXMLRPCRequestHandler" pode ser usada para manipular
solicitações XML-RPC enviadas para scripts CGI Python.

CGIXMLRPCRequestHandler.register_function(function=None, name=None)

   Registra uma função que possa responder às solicitações XML-RPC. Se
   *name* for fornecido, será o nome do método associado a *function*,
   caso contrário, "function.__name__" será usado. *name* é uma string
   e pode conter caracteres ilegais para identificadores Python,
   incluindo o caractere de ponto.

   Este método também pode ser usado como um decorador. Quando usado
   como decorador, *name* só pode ser fornecido como argumento nomeado
   para registrar *function* em *name*. Se nenhum *name* for
   fornecido, "function.__name__" será usado.

   Alterado na versão 3.7: "register_function()" pode ser usado como
   um decorador.

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()


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 registro para que
   o parâmetro *logRequests* no parâmetro "DocXMLRPCServer" seja
   respeitado.


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á na documentação como um parágrafo, abaixo do
   nome do servidor.


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á na documentação como um parágrafo, abaixo do
   nome do servidor.
