O módulo xmlrpc.client permite chamar procedimentos remotos expostos por um servidor XML-RPC. O protocolo representa métodos, parâmetros e resultados em XML e usa HTTP ou HTTPS como transporte. Ele ainda aparece em sistemas legados, equipamentos, plataformas de publicação e integrações corporativas que precisam ser mantidas sem adicionar dependências externas.
XML-RPC é simples, mas não moderno nem adequado para qualquer cenário. A documentação do Python alerta que o módulo não é seguro contra dados XML maliciosamente construídos. Use-o apenas com endpoints autenticados e confiáveis, aplique TLS, timeouts, limites de resposta e uma política explícita de métodos permitidos.
Primeira chamada com ServerProxy
from xmlrpc.client import ServerProxy
with ServerProxy(
"https://rpc.example.com/RPC2",
use_builtin_types=True,
) as proxy:
resultado = proxy.calculadora.somar(7, 5)
print(resultado)
ServerProxy cria um objeto dinâmico. O acesso a proxy.calculadora.somar não chama nada imediatamente; a chamada ocorre quando os argumentos são fornecidos. O nome completo do método é enviado ao servidor.
Use o proxy como context manager para fechar o transporte. Não construa o nome do método diretamente com texto fornecido por usuários, pois isso pode permitir invocar operações não previstas.
Parâmetros importantes
Além da URI, ServerProxy aceita opções como:
allow_none=Truepara permitir a extensão que representaNone.use_builtin_types=Truepara retornar datas comodatetimee dados binários comobytes.headerspara cabeçalhos HTTP adicionais.contextpara umssl.SSLContextem conexões HTTPS.transportpara personalizar conexão, timeout, proxy ou observabilidade.
Nem todo servidor aceita None. Ative a opção somente quando o contrato declarar suporte.
Tipos suportados
XML-RPC possui um conjunto de tipos menor do que Python. Valores comuns incluem booleanos, inteiros em faixa limitada, floats, strings, arrays, estruturas semelhantes a dicionários, datas e binários.
payload = {
"id": 42,
"ativo": True,
"tags": ["python", "rpc"],
"preco": 19.90,
}
with ServerProxy(URL, use_builtin_types=True) as proxy:
resposta = proxy.catalogo.criar(payload)
As chaves de structs devem ser strings. Objetos complexos, sets, generators e muitas classes não podem ser serializados diretamente. Converta dados para um contrato simples antes da chamada.
Limites de inteiros
O formato XML-RPC tradicional trabalha com inteiros de 32 bits. Alguns servidores aceitam extensões como i8 ou biginteger, mas a interoperabilidade varia. IDs muito grandes devem ser negociados no contrato, muitas vezes como string.
def id_rpc(valor: int) -> str:
if valor < 0:
raise ValueError("ID inválido")
return str(valor)
Não presuma que dois produtos XML-RPC implementam as mesmas extensões.
Datas e use_builtin_types
Com use_builtin_types=True, datas recebidas podem virar datetime.datetime. Sem essa opção, podem chegar como objetos DateTime do módulo.
from datetime import datetime, timezone
from xmlrpc.client import ServerProxy
agora = datetime.now(timezone.utc).replace(tzinfo=None)
with ServerProxy(URL, use_builtin_types=True) as proxy:
proxy.eventos.registrar("backup", agora)
XML-RPC não transporta timezone de forma rica. Defina no contrato se datas são UTC e evite enviar horários locais ambíguos.
Dados binários
Bytes são codificados em Base64. Com use_builtin_types=True, o retorno pode ser bytes. Caso contrário, use Binary.data.
from xmlrpc.client import Binary, ServerProxy
conteudo = b"dados binarios"
with ServerProxy(URL, use_builtin_types=True) as proxy:
resposta = proxy.arquivos.enviar(Binary(conteudo))
Base64 aumenta o tamanho da transferência. Não use XML-RPC para arquivos grandes sem limites e confirmação de que o servidor suporta o volume. Prefira armazenamento de objetos ou upload HTTP dedicado.
Fault: erro da aplicação remota
Quando o servidor executa a chamada, mas devolve uma falha XML-RPC, o cliente lança Fault. Ela contém faultCode e faultString.
from xmlrpc.client import Fault, ServerProxy
try:
with ServerProxy(URL) as proxy:
proxy.usuarios.buscar(999)
except Fault as erro:
print("Código remoto:", erro.faultCode)
print("Mensagem:", erro.faultString)
Não mostre faultString diretamente em HTML e não trate a mensagem como estrutura confiável. O servidor pode incluir detalhes internos ou texto controlado externamente.
ProtocolError: falha no HTTP
ProtocolError descreve problemas na camada HTTP ou HTTPS, como 401, 403, 404 ou 500 antes de uma resposta XML-RPC válida. A exceção expõe URL, código, mensagem e headers.
from xmlrpc.client import ProtocolError
try:
proxy.sistema.status()
except ProtocolError as erro:
print(erro.errcode, erro.errmsg)
Uma falha de aplicação remota e uma falha de transporte exigem ações diferentes. Não repita automaticamente credenciais inválidas ou endpoints inexistentes. Para conceitos semelhantes no cliente HTTP padrão, consulte urllib.error no Python.
Outras falhas de transporte
DNS, timeout, conexão recusada e TLS podem aparecer como OSError, TimeoutError, ssl.SSLError ou exceções do transporte. Mantenha o bloco try pequeno e preserve a causa original.
try:
resultado = proxy.sistema.status()
except Fault:
raise
except ProtocolError:
raise
except OSError as erro:
raise RuntimeError("Serviço RPC indisponível") from erro
HTTPS e validação de certificado
Para URIs HTTPS, versões atuais do Python validam certificado e hostname por padrão. Você pode fornecer um contexto para usar uma CA corporativa ou definir versões mínimas.
import ssl
from xmlrpc.client import ServerProxy
contexto = ssl.create_default_context(cafile="ca-corporativa.pem")
contexto.minimum_version = ssl.TLSVersion.TLSv1_2
proxy = ServerProxy(
"https://rpc.example.com/RPC2",
context=contexto,
use_builtin_types=True,
)
Nunca use contexto não verificado como solução permanente. O guia de ssl no Python
Autenticação
O módulo aceita credenciais Basic embutidas na URL, mas essa forma pode vazar em logs, histórico, mensagens e monitoramento. Prefira um transporte ou header controlado e sempre use HTTPS.
cabecalhos = (("Authorization", "Bearer TOKEN_TEMPORARIO"),)
proxy = ServerProxy(URL, headers=cabecalhos)
Não fixe tokens no código-fonte. Carregue segredos de ambiente ou gerenciador dedicado, faça rotação e nunca registre o header.
Timeout com transporte personalizado
ServerProxy não possui um parâmetro de timeout direto. Uma opção é personalizar o transporte.
import http.client
import xmlrpc.client
class TransporteComTimeout(xmlrpc.client.SafeTransport):
def __init__(self, timeout: float = 10.0, context=None):
super().__init__(context=context)
self.timeout = timeout
def make_connection(self, host):
return http.client.HTTPSConnection(
host,
timeout=self.timeout,
context=self.context,
)
Teste o transporte na versão de Python usada em produção, pois atributos internos podem variar. Para controle HTTP de baixo nível, veja http.client no Python.
Introspecção
Alguns servidores expõem system.listMethods(), system.methodHelp() e system.methodSignature().
with ServerProxy(URL) as proxy:
metodos = proxy.system.listMethods()
for nome in metodos:
print(nome)
Introspecção é útil em desenvolvimento, mas pode revelar superfície sensível. Não dependa dela para autorização. O cliente deve manter uma allowlist própria de métodos permitidos.
MultiCall
MultiCall agrupa várias chamadas em uma requisição system.multicall, quando o servidor oferece suporte.
from xmlrpc.client import MultiCall, ServerProxy
with ServerProxy(URL) as proxy:
lote = MultiCall(proxy)
lote.catalogo.buscar(1)
lote.catalogo.buscar(2)
resultados = list(lote())
O lote reduz viagens de rede, mas pode aumentar custo e tamanho da resposta. Limite quantidade, avalie falhas parciais e não agrupe operações destrutivas sem semântica clara.
Segurança do XML
A documentação alerta contra dados XML maliciosos. Mesmo com servidor conhecido, um endpoint comprometido pode enviar respostas que consomem recursos. Use limites no proxy reverso, timeouts, tamanho máximo, autenticação e segmentação de rede.
Não exponha um cliente XML-RPC diretamente a uma URL arbitrária fornecida por usuário. Isso combina riscos de SSRF, XML malicioso e vazamento de credenciais.
Logs e observabilidade
Registre nome lógico do método, duração, resultado resumido, código de falha e identificador de correlação. Não registre parâmetros completos, respostas binárias, senhas, tokens ou dados pessoais.
Como os métodos são dinâmicos, envolva o proxy em funções explícitas de domínio. Isso facilita métricas, validação e testes.
Testes recomendados
Teste tipos compatíveis, None habilitado e desabilitado, números fora da faixa, datas, binários, Fault, ProtocolError, timeout, certificado inválido, resposta grande, método inexistente, multicall parcial e redaction de logs.
Execute testes contra um servidor local controlado. O próximo guia sobre xmlrpc.server mostra como montar esse ambiente.
Quando não usar XML-RPC
Para uma API nova, JSON sobre HTTP, gRPC ou outro protocolo moderno costuma oferecer melhor ecossistema, autenticação, streaming, schemas e observabilidade. XML-RPC faz sentido principalmente quando você precisa interoperar com um sistema existente.
Conclusão
xmlrpc.client simplifica integrações com serviços XML-RPC por meio de ServerProxy. Para usá-lo com segurança, limite métodos e tipos, valide TLS, proteja credenciais, configure timeout, trate Fault separadamente de ProtocolError e nunca confie em respostas XML arbitrárias.
Consulte a documentação oficial de xmlrpc.client e a especificação XML-RPC. Em sistemas novos, avalie alternativas; em sistemas legados, encapsule o protocolo atrás de uma camada de domínio bem testada.







