# `xmlrpc.client` — Cliente XML-RPC

Código-fonte: Lib/xmlrpc/client.py

XML-RPC é um método de chamada remota de métodos que usa XML usando HTTP(S) como transporte. Com ele, um cliente pode chamar métodos com parâmetros em um servidor remoto (o servidor é nomeado por um URI) e receber de volta dados estruturados. Este módulo oferece suporte à escrita de código de clientes XML-RPC; ele lida com todos os detalhes da tradução entre Python objetos e XML.

Aviso

O módulo `xmlrpc.client` não é seguro contra dados construídos de forma maliciosa. Se você precisa processar dados não-confiáveis ou sem autenticação, veja Vulnerabilidades em XML.

Alterado na versão 3.5: Para URIs com HTTPS, `xmlrpc.client` agora faz todas as validações de certificado e nome do servidor necessárias por padrão.

Disponibilidade: não Emscripten, não WASI.

Este módulo não funciona ou não está disponível em plataformas WebAssembly `wasm32-emscripten` e `wasm32-wasi`. Veja Plataformas WebAssembly para mais informações.

class xmlrpc.client.ServerProxy(uri, transport=None, encoding=None, verbose=False, allow_none=False, use_datetime=False, use_builtin_types=False, *, headers=(), context=None)

  Uma instância de `ServerProxy` é um objeto que gerencia a comunicação com um servidor XML-RPC remoto. O primeiro argumento obrigatório é uma URI (Uniform Resource Indicator - Indicador de Recurso Uniforme) e normalmente vai ser a URL do servidor. O segundo parâmetro, opcional, é uma instância de um factory de transporte; por padrão é uma instância de `SafeTransport` para URLs https e uma instância de `Transport` caso contrário. O terceiro parâmetro, opcional, é o encoding, por padrão sendo UTF-8. O quarto argumento, opcional, é a flag de debug.

  Os seguite parâmetros coordenam o uso da intância de proxy retornada. Se alow_none for verdadeiro, a constante `None` do Python será traduzida para XML; o comportamento padrão é que `None` levante uma `TypeError`, Isso é uma extensão comum da especificação do XML-RPC, mas não é suportado por todos os clientes e servidores, veja http://ontosys.com/xml-rpc/extensions.php para uma descrição. A flag use_builtin_types pode ser usada para que valores de data e hora sejam representados como objetos `datetime.datetime` e dados binários representados com objetos `bytes`; essa flag é False por padrão. Objetos `datetime.datetime`, `bytes` e `bytearray` podem ser usados nas chamadas. O parâmetro headers é uma sequência opcional de headers a serem enviados em cada requisição, representados por uma sequência de tuplas de dois valores representando o nome do header e seu valor (como `[('Header-Name', 'value')]`). A flag use_datetime é obsoleta e é similar a use_builtin_types mas se aplica somente a valores de data e hora.

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

Alterado na versão 3.8: O parâmetro headers foi adicionado.

Tanto o transporte por HTTP quanto o transporte por HTTP suportam a extensão da sintaxe de URL para Autenticação Básica do HTTP: `http://user:pass@host:port/path`. A parte `user:pass` será codificada em Base64 como um header HTTP ‘Authorization’, e enviada para o servidor remoto como parte do processo de conexão quando for invocado um método XML-RPC. Você só precisar usar isso se o servidor remoto requer Autenticação Básica com usuário e senha. Se for usada uma URL HTTPS, context pode ser do tipo `ssl.SSLContext` e configurar o SSL da conexão HTTPS por baixo.

A instância retornada é um objeto proxy com métodos que podem ser usados para invocar a chamada RPC correspondendo no servidor remoto. Se o servidor remoto suportar a API de instrospecção, o proxy também pode ser usado para perguntar ao servidor remoto pelos métodos que ele suporta (descoberta de serviço) e recuperar outros meta-dados associados com o servidor.

Os tipos que são conformáveis (por exemplo, que podem ser convertidos para XML) incluem os seguintes (e exceto onde indicado, eles não são convertidos como o mesmo tipo Python):

Tipo XML-RPC | Python type
--- | ---
`boolean` | `bool`
`int`, `i1`, `i2`, `i4`, `i8` ou `biginteger` | `int` no intervalo de -2147483648 a 2147483647. Os valores recebem a tag `<int>`.
`double` ou `float` | `float`. Os valores recebem a tag `<double>`.
`string` | `str`
`array` | `list` ou `tuple` contendo elementos conformáveis. As matrizes são retornadas como `lists`.
`struct` | `dict`. Chaves devem ser strings, valores podem ser qualquer tipo conformáveis. Objetos de classes definidas pelo usuário pode ser usadas; apenas o atributo `__dict__` delas é transmitido.
`dateTime.iso8601` | `DateTime` ou `datetime.datetime`. O tipo retornado depende de volumes de sinalizadores use_builtin_types e use_datetime.
`base64` | `Binary`, `bytes` ou `bytearray`. O tipo retornado depende do valor da flag use_builtin_types.
`nil` | A constante `None`. A passagem é permitida somente se allow_none for verdadeiro.
`bigdecimal` | `decimal.Decimal`. Somente tipo retornado.

Esta é a lista completa de tipos suportados por XML-RPC. Chamadas de método podem também levantar uma instância de `Fault`, usado para que o servidor XML-RPC indique erros, ou `ProtocolError` para indicar erros na camada HTTP/HTTPS. Tnato `Fault` quanto `ProtocolError` derivam da classe base `Error`. Observe que o módulo de cliente xmlrpc atualmente não converte instância de subclasses dos tipos built-in.

Ao passar strings, os caracteres especiais para XML, como `<`, `>` e `&`, serão automaticamente escapados. No entanto, é responsabilidade do chamador garantir que o string esteja livre de caracteres que não são permitidos em XML, como os caracteres de controle com valores ASCII entre 0 e 31 (exceto, é claro, tabulação, nova linha e retorno de carro); se isso não for feito, resultará em uma solicitação XML-RPC que não é um XML bem formado. Se você precisar passar bytes arbitrários via XML-RPC, use as classes `bytes` ou `bytearray` ou a classe wrapper `Binary` descrito abaixo.

`Server` foi mantido como um apelido para `ServerProxy` para compatibilidade retroativa. Código novo deve usar `ServerProxy`.

Alterado na versão 3.5: Argumento context adicionado.

Alterado na versão 3.6: Adicionado suporte para tags com prefixos (por exemplo `ex:nil`) Adicionado suporte para desconversão de tipos adicionados usados pela implementação do Apache XML-RPC para numéricos: `i1`, `i2`, `i8`, `biginteger`, `float` e `bigdecimal`. Veja https://ws.apache.org/xmlrpc/types.html para uma descrição.

Ver também

XML-RPC HOWTO

  Uma boa descrição das operações XML-RPC e software cliente em vários idiomas. Contém praticamente tudo o que um desenvolvedor de clientes XML-RPC precisa saber.

XML-RPC Introspection

  Describe a extensão do protocolo XML-RPC para instrospecção.

XML-RPC Specification

  A especificação oficial.

## Objetos ServerProxy

A `ServerProxy` instance has a method corresponding to each remote procedure call accepted by the XML-RPC server. Calling the method performs an RPC, dispatched by both name and argument signature (e.g. the same method name can be overloaded with multiple argument signatures). The RPC finishes by returning a value, which may be either returned data in a conformant type or a `Fault` or `ProtocolError` object indicating an error.

Servers that support the XML introspection API support some common methods grouped under the reserved `system` attribute:

ServerProxy.system.listMethods()

  This method returns a list of strings, one for each (non-system) method supported by the XML-RPC server.

ServerProxy.system.methodSignature(name)

  This method takes one parameter, the name of a method implemented by the XML-RPC server. It returns an array of possible signatures for this method. A signature is an array of types. The first of these types is the return type of the method, the rest are parameters.

  Because multiple signatures (ie. overloading) is permitted, this method returns a list of signatures rather than a singleton.

  Signatures themselves are restricted to the top level parameters expected by a method. For instance if a method expects one array of structs as a parameter, and it returns a string, its signature is simply “string, array”. If it expects three integers and returns a string, its signature is “string, int, int, int”.

  If no signature is defined for the method, a non-array value is returned. In Python this means that the type of the returned value will be something other than list.

ServerProxy.system.methodHelp(name)

  This method takes one parameter, the name of a method implemented by the XML-RPC server. It returns a documentation string describing the use of that method. If no such string is available, an empty string is returned. The documentation string may contain HTML markup.

Alterado na versão 3.5: Instances of `ServerProxy` support the context manager protocol for closing the underlying transport.

A working example follows. The server code:

    from xmlrpc.server import SimpleXMLRPCServer

    def is_even(n):
        return n % 2 == 0

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(is_even, "is_even")
    server.serve_forever()

The client code for the preceding server:

    import xmlrpc.client

    with xmlrpc.client.ServerProxy("http://localhost:8000/") as proxy:
        print("3 is even: %s" % str(proxy.is_even(3)))
        print("100 is even: %s" % str(proxy.is_even(100)))

## Objetos DateTime

class xmlrpc.client.DateTime

  This class may be initialized with seconds since the epoch, a time tuple, an ISO 8601 time/date string, or a `datetime.datetime` instance. It has the following methods, supported mainly for internal use by the marshalling/unmarshalling code:

  decode(string)

    Accept a string as the instance’s new time value.

  encode(out)

    Write the XML-RPC encoding of this `DateTime` item to the out stream object.

  It also supports certain of Python’s built-in operators through `rich comparison` and `__repr__()` methods.

A working example follows. The server code:

    import datetime
    from xmlrpc.server import SimpleXMLRPCServer
    import xmlrpc.client

    def today():
        today = datetime.datetime.today()
        return xmlrpc.client.DateTime(today)

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(today, "today")
    server.serve_forever()

The client code for the preceding server:

    import xmlrpc.client
    import datetime

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")

    today = proxy.today()
    # convert the ISO8601 string to a datetime object
    converted = datetime.datetime.strptime(today.value, "%Y%m%dT%H:%M:%S")
    print("Today: %s" % converted.strftime("%d.%m.%Y, %H:%M"))

## Objetos Binários

class xmlrpc.client.Binary

  This class may be initialized from bytes data (which may include NULs). The primary access to the content of a `Binary` object is provided by an attribute:

  data

    The binary data encapsulated by the `Binary` instance. The data is provided as a `bytes` object.

  `Binary` objects have the following methods, supported mainly for internal use by the marshalling/unmarshalling code:

  decode(bytes)

    Accept a base64 `bytes` object and decode it as the instance’s new data.

  encode(out)

    Write the XML-RPC base 64 encoding of this binary item to the out stream object.

    The encoded data will have newlines every 76 characters as per RFC 2045 section 6.8, which was the de facto standard base64 specification when the XML-RPC spec was written.

  It also supports certain of Python’s built-in operators through `__eq__()` and `__ne__()` methods.

Example usage of the binary objects. We’re going to transfer an image over XMLRPC:

    from xmlrpc.server import SimpleXMLRPCServer
    import xmlrpc.client

    def python_logo():
        with open("python_logo.jpg", "rb") as handle:
            return xmlrpc.client.Binary(handle.read())

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(python_logo, 'python_logo')

    server.serve_forever()

The client gets the image and saves it to a file:

    import xmlrpc.client

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
    with open("fetched_python_logo.jpg", "wb") as handle:
        handle.write(proxy.python_logo().data)

## Objetos Fault

class xmlrpc.client.Fault

  A `Fault` object encapsulates the content of an XML-RPC fault tag. Fault objects have the following attributes:

  faultCode

    An int indicating the fault type.

  faultString

    A string containing a diagnostic message associated with the fault.

In the following example we’re going to intentionally cause a `Fault` by returning a complex type object. The server code:

    from xmlrpc.server import SimpleXMLRPCServer

    # A marshalling error is going to occur because we're returning a
    # complex number
    def add(x, y):
        return x+y+0j

    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_function(add, 'add')

    server.serve_forever()

The client code for the preceding server:

    import xmlrpc.client

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
    try:
        proxy.add(2, 5)
    except xmlrpc.client.Fault as err:
        print("A fault occurred")
        print("Fault code: %d" % err.faultCode)
        print("Fault string: %s" % err.faultString)

## Objeto ProtocolError

class xmlrpc.client.ProtocolError

  A `ProtocolError` object describes a protocol error in the underlying transport layer (such as a 404 ‘not found’ error if the server named by the URI does not exist). It has the following attributes:

  url

    The URI or URL that triggered the error.

  errcode

    O código do erro.

  errmsg

    The error message or diagnostic string.

  headers

    A dict containing the headers of the HTTP/HTTPS request that triggered the error.

In the following example we’re going to intentionally cause a `ProtocolError` by providing an invalid URI:

    import xmlrpc.client

    # create a ServerProxy with a URI that doesn't respond to XMLRPC requests
    proxy = xmlrpc.client.ServerProxy("http://google.com/")

    try:
        proxy.some_method()
    except xmlrpc.client.ProtocolError as err:
        print("A protocol error occurred")
        print("URL: %s" % err.url)
        print("HTTP/HTTPS headers: %s" % err.headers)
        print("Error code: %d" % err.errcode)
        print("Error message: %s" % err.errmsg)

## Objetos MultiCall

The `MultiCall` object provides a way to encapsulate multiple calls to a remote server into a single request [1].

class xmlrpc.client.MultiCall(server)

  Create an object used to boxcar method calls. server is the eventual target of the call. Calls can be made to the result object, but they will immediately return `None`, and only store the call name and parameters in the `MultiCall` object. Calling the object itself causes all stored calls to be transmitted as a single `system.multicall` request. The result of this call is a generator; iterating over this generator yields the individual results.

A usage example of this class follows. The server code:

    from xmlrpc.server import SimpleXMLRPCServer

    def add(x, y):
        return x + y

    def subtract(x, y):
        return x - y

    def multiply(x, y):
        return x * y

    def divide(x, y):
        return x // y

    # A simple server with simple arithmetic functions
    server = SimpleXMLRPCServer(("localhost", 8000))
    print("Listening on port 8000...")
    server.register_multicall_functions()
    server.register_function(add, 'add')
    server.register_function(subtract, 'subtract')
    server.register_function(multiply, 'multiply')
    server.register_function(divide, 'divide')
    server.serve_forever()

The client code for the preceding server:

    import xmlrpc.client

    proxy = xmlrpc.client.ServerProxy("http://localhost:8000/")
    multicall = xmlrpc.client.MultiCall(proxy)
    multicall.add(7, 3)
    multicall.subtract(7, 3)
    multicall.multiply(7, 3)
    multicall.divide(7, 3)
    result = multicall()

    print("7+3=%d, 7-3=%d, 7*3=%d, 7//3=%d" % tuple(result))

## Convenience Functions

xmlrpc.client.dumps(params, methodname=None, methodresponse=None, encoding=None, allow_none=False)

  Convert params into an XML-RPC request. or into a response if methodresponse is true. params can be either a tuple of arguments or an instance of the `Fault` exception class. If methodresponse is true, only a single value can be returned, meaning that params must be of length 1. encoding, if supplied, is the encoding to use in the generated XML; the default is UTF-8. Python’s `None` value cannot be used in standard XML-RPC; to allow using it via an extension, provide a true value for allow_none.

xmlrpc.client.loads(data, use_datetime=False, use_builtin_types=False)

  Convert an XML-RPC request or response into Python objects, a `(params, methodname)`. params is a tuple of argument; methodname is a string, or `None` if no method name is present in the packet. If the XML-RPC packet represents a fault condition, this function will raise a `Fault` exception. The use_builtin_types flag can be used to cause date/time values to be presented as `datetime.datetime` objects and binary data to be presented as `bytes` objects; this flag is false by default.

  The obsolete use_datetime flag is similar to use_builtin_types but it applies only to date/time values.

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

## Exemplo de uso do cliente

    # simple test program (from the XML-RPC specification)
    from xmlrpc.client import ServerProxy, Error

    # server = ServerProxy("http://localhost:8000") # local server
    with ServerProxy("http://betty.userland.com") as proxy:

        print(proxy)

        try:
            print(proxy.examples.getStateName(41))
        except Error as v:
            print("ERROR", v)

To access an XML-RPC server through a HTTP proxy, you need to define a custom transport. The following example shows how:

    import http.client
    import xmlrpc.client

    class ProxiedTransport(xmlrpc.client.Transport):

        def set_proxy(self, host, port=None, headers=None):
            self.proxy = host, port
            self.proxy_headers = headers

        def make_connection(self, host):
            connection = http.client.HTTPConnection(*self.proxy)
            connection.set_tunnel(host, headers=self.proxy_headers)
            self._connection = host, connection
            return connection

    transport = ProxiedTransport()
    transport.set_proxy('proxy-server', 8080)
    server = xmlrpc.client.ServerProxy('http://betty.userland.com', transport=transport)
    print(server.examples.getStateName(41))

## Example of Client and Server Usage

See Exemplo de SimpleXMLRPCServer.

Notas de rodapé

[1]

This approach has been first presented in a discussion on xmlrpc.com.