# `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.