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.

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.