xmlrpc.client no Python: chamadas RPC

Publicado em: 21/08/2026
Tempo de leitura: 4 minutos
Cabos conectados a servidor representando chamadas remotas com xmlrpc.client no Python

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=True para permitir a extensão que representa None.
  • use_builtin_types=True para retornar datas como datetime e dados binários como bytes.
  • headers para cabeçalhos HTTP adicionais.
  • context para um ssl.SSLContext em conexões HTTPS.
  • transport para 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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Desenvolvedor configurando servidor HTTPS e certificado TLS com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crie servidor HTTPS local no Python

    Aprenda HTTPSServer no Python para servir HTTPS localmente, configurar certificados, usar threads e entender limites de segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/10/2026
    Arquivos protegidos representando extração segura de TAR com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extraia TAR com segurança

    Aprenda tarfile extraction_filter no Python para extrair arquivos TAR com validação, segurança e controle de caminhos.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026
    Código Python exibindo avisos controlados com catch_warnings
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: capture warnings em testes Python

    Aprenda catch_warnings no Python para capturar, testar e controlar avisos com filtros específicos e segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python representando referências persistentes do pickle
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serialize referências externas

    Aprenda pickle persistent_id no Python para serializar referências externas com IDs estáveis, validação, segurança e compatibilidade.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binário representando buffers e memória no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: conte valores sem copiar buffers

    Aprenda memoryview.count no Python para contar bytes e valores em buffers sem cópias, com formatos, limites e boas práticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python com anotações de tipos
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib: evite imports circulares em anotações

    Aprenda annotationlib no Python para ler anotações adiadas, evitar imports circulares e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026