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 deSafeTransport
para URLs https e uma instância deTransport
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 é queNone
levante umaTypeError
, 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 objetosdatetime.datetime
e dados binários representados com objetosbytes
; essa flag é False por padrão. Objetosdatetime.datetime
,bytes
ebytearray
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 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A constante |
|
|
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.
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:Binary
objects have the following methods, supported mainly for internal use by the marshalling/unmarshalling code:-
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 theMultiCall
object. Calling the object itself causes all stored calls to be transmitted as a singlesystem.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’sNone
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, orNone
if no method name is present in the packet. If the XML-RPC packet represents a fault condition, this function will raise aFault
exception. The use_builtin_types flag can be used to cause date/time values to be presented asdatetime.datetime
objects and binary data to be presented asbytes
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.