xmlrpc.server: crie servidores XML-RPC

Publicado em: 21/08/2026
Tempo de leitura: 6 minutos
Rack de servidores representando um endpoint criado com xmlrpc.server no Python

O módulo xmlrpc.server oferece um framework básico para criar servidores XML-RPC em Python. Ele recebe chamadas HTTP POST com XML, converte parâmetros em objetos Python, executa uma função registrada e serializa o resultado. É útil em integrações legadas, testes locais e sistemas internos que já dependem do protocolo.

A documentação oficial alerta que o módulo não é seguro contra XML maliciosamente construído. Além disso, SimpleXMLRPCServer não fornece sozinho autenticação moderna, limitação de taxa, proteção contra abuso ou uma arquitetura pronta para internet pública. Trate-o como componente interno, atrás de controles adicionais.

Servidor mínimo

from xmlrpc.server import SimpleXMLRPCServer

with SimpleXMLRPCServer(
    ("127.0.0.1", 8000),
    allow_none=False,
    logRequests=False,
    use_builtin_types=True,
) as servidor:

    @servidor.register_function(name="somar")
    def somar(a: int, b: int) -> int:
        return a + b

    servidor.serve_forever()

O bind em 127.0.0.1 impede acesso direto de outras máquinas. Para produção interna, coloque um proxy reverso autenticado na frente e mantenha o processo em rede restrita.

Restringindo o caminho RPC

Por padrão, o handler aceita / e /RPC2. Uma subclasse pode limitar a apenas um caminho.

from xmlrpc.server import (
    SimpleXMLRPCRequestHandler,
    SimpleXMLRPCServer,
)

class Handler(SimpleXMLRPCRequestHandler):
    rpc_paths = ("/RPC2",)

servidor = SimpleXMLRPCServer(
    ("127.0.0.1", 8000),
    requestHandler=Handler,
)

A restrição reduz endpoints acidentais, mas não substitui autenticação. Um atacante que alcança o caminho ainda pode enviar chamadas.

Registro explícito de funções

Prefira register_function() com nomes claros. Isso cria uma allowlist de operações expostas.

def status() -> dict[str, object]:
    return {"ok": True, "versao": "1"}

servidor.register_function(status, "sistema.status")

Valide tipos, faixas, tamanho de strings e quantidade de itens dentro da função. Anotações de tipo não validam automaticamente os dados recebidos.

Não exponha funções perigosas

Evite registrar funções que executam comandos, abrem caminhos arbitrários, avaliam código, importam módulos ou recebem SQL cru. O XML-RPC é apenas transporte; os riscos da função continuam existindo.

from pathlib import Path

RAIZ = Path("/srv/relatorios").resolve()

def ler_relatorio(nome: str) -> str:
    if not nome.endswith(".txt") or "/" in nome or "\\" in nome:
        raise ValueError("nome inválido")
    caminho = (RAIZ / nome).resolve()
    if RAIZ not in caminho.parents:
        raise ValueError("caminho fora da raiz")
    return caminho.read_text(encoding="utf-8")

Mesmo em rede interna, considere todos os parâmetros não confiáveis.

register_instance e _dispatch

register_instance() pode expor métodos de um objeto. Uma abordagem mais segura é implementar _dispatch() e mapear manualmente nomes permitidos.

class Servico:
    def _dispatch(self, metodo, parametros):
        permitidos = {
            "sistema.status": self.status,
            "calcular.soma": self.soma,
        }
        funcao = permitidos.get(metodo)
        if funcao is None:
            raise ValueError("método não permitido")
        return funcao(*parametros)

    def status(self):
        return {"ok": True}

    def soma(self, a, b):
        return int(a) + int(b)

servidor.register_instance(Servico())

A allowlist impede que atributos internos sejam descobertos por nome.

Nunca habilite allow_dotted_names em rede aberta

A própria documentação alerta que allow_dotted_names=True pode permitir acesso a variáveis globais e até execução arbitrária. Mantenha o padrão False. Se um sistema antigo exigir nomes hierárquicos, implemente-os por registro explícito ou _dispatch().

Introspecção

register_introspection_functions() expõe system.listMethods, system.methodHelp e system.methodSignature.

servidor.register_introspection_functions()

Isso ajuda em desenvolvimento, mas revela superfície de métodos. Em produção, habilite apenas se houver necessidade e autorização adequada. Documentação pública não deve incluir operações administrativas.

Multicall

register_multicall_functions() habilita system.multicall, permitindo várias operações em uma única requisição.

servidor.register_multicall_functions()

O recurso reduz viagens de rede, mas aumenta o trabalho de uma chamada. Aplique limite de quantidade, custo e tamanho. Não misture operações destrutivas sem definir atomicidade e comportamento de falha parcial.

Tipos e allow_none

XML-RPC suporta tipos limitados. allow_none=True habilita uma extensão para None, que nem todo cliente implementa. use_builtin_types=True facilita datas e bytes.

Defina o contrato por método: tipos aceitos, limites, timezone de datas, tamanho máximo de binários e significado de valores ausentes. Para arquivos grandes, prefira upload dedicado.

Falhas e mensagens

Exceções lançadas pelas funções são transformadas em faults XML-RPC. Não devolva stack traces, caminhos, queries ou segredos. Converta falhas conhecidas em códigos estáveis.

from xmlrpc.client import Fault

def buscar_usuario(usuario_id: int):
    if usuario_id <= 0:
        raise Fault(400, "identificador inválido")
    usuario = repositorio.buscar(usuario_id)
    if usuario is None:
        raise Fault(404, "usuário não encontrado")
    return usuario

A mensagem ainda deve ser escapada ao aparecer em HTML no cliente.

Autenticação

SimpleXMLRPCServer não traz uma solução completa de autenticação. A opção mais segura é colocar o processo atrás de Nginx, Apache, API gateway ou service mesh que valide mTLS, Basic Auth, token ou identidade de rede.

Uma subclasse de request handler pode verificar headers, mas cuidado para não registrar credenciais. Mantenha a lógica centralizada e teste respostas 401 e 403.

TLS

O servidor simples não configura HTTPS diretamente de forma ergonômica. Prefira terminar TLS em um proxy reverso atualizado, com certificado, versões modernas, limite de corpo, timeout e logs.

Se envolver o socket manualmente, você assume detalhes de handshake, shutdown e atualização. O guia de ssl no Python explica os riscos.

Limite de corpo e XML malicioso

O aviso da documentação deve ser levado a sério. XML pode ser construído para consumir memória ou CPU. Coloque limite de Content-Length no proxy, rejeite transferências sem política, configure timeout e limite conexões simultâneas.

Não exponha o servidor a clientes anônimos. Segmentação de rede e autenticação reduzem a probabilidade de receber payloads hostis, mas não substituem limites.

Concorrência

SimpleXMLRPCServer é baseado em socketserver.TCPServer e processa requisições de forma síncrona. Uma chamada lenta bloqueia as seguintes.

from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer

class ServidorComThreads(ThreadingMixIn, SimpleXMLRPCServer):
    daemon_threads = True

Threads aumentam concorrência, mas também risco de corrida, consumo e sobrecarga. Proteja estado compartilhado, limite conexões e evite tarefas longas. O guia de socketserver no Python detalha mixins e encerramento.

Timeouts e tarefas longas

Não execute relatórios extensos, processamento de vídeo ou operações indefinidas dentro da thread da requisição. Enfileire o trabalho, retorne um identificador e ofereça um método de consulta. Defina timeout no proxy e no cliente.

Encerramento seguro

Use o servidor como context manager e chame shutdown() a partir de outra thread quando serve_forever() estiver ativo. Depois, feche recursos de aplicação.

try:
    servidor.serve_forever()
except KeyboardInterrupt:
    pass
finally:
    servidor.server_close()

Em ambientes gerenciados, trate SIGTERM e pare de aceitar novas chamadas antes de encerrar.

Logs

logRequests=True registra requisições de forma simples. Em produção, prefira logging estruturado com método lógico, duração, resultado e identificador de correlação. Não registre corpo XML completo, tokens ou dados pessoais.

Documentação automática

DocXMLRPCServer gera uma página HTML de documentação para GET. É conveniente em laboratórios, mas pode revelar métodos e textos internos. Não exponha essa página sem autenticação e revisão.

Cliente correspondente

Para consumir o serviço, use xmlrpc.client no Python. O cliente deve usar HTTPS, timeout, allowlist de métodos e tratamento separado de Fault e ProtocolError.

Testes recomendados

Teste método válido e inexistente, parâmetros fora de faixa, corpo grande, XML malformado, autenticação ausente, caminho incorreto, chamadas simultâneas, multicall excessivo, shutdown e ausência de segredos nos faults e logs.

Faça testes locais e nunca use um servidor público de terceiros para validar código destrutivo.

Quando escolher outra tecnologia

Para uma API nova, frameworks HTTP com JSON, schemas e middleware de segurança costumam ser mais adequados. XML-RPC é indicado principalmente para compatibilidade com sistemas existentes ou ferramentas internas simples em rede controlada.

Conclusão

xmlrpc.server permite construir rapidamente um endpoint RPC, mas a rapidez não elimina responsabilidades de segurança. Registre funções explicitamente, mantenha allow_dotted_names desativado, limite caminhos e payloads, autentique no proxy, proteja TLS, controle concorrência e trate XML como não confiável.

Consulte a documentação oficial de xmlrpc.server e as orientações de segurança para XML no Python. Para internet pública ou projetos novos, considere uma plataforma de API com controles mais completos.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Cabos conectados a servidor representando chamadas remotas com xmlrpc.client no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    xmlrpc.client no Python: chamadas RPC

    Aprenda xmlrpc.client no Python para chamar serviços XML-RPC, tratar Fault e ProtocolError, usar TLS, tipos compatíveis e limites seguros.

    Ler mais

    Tempo de leitura: 4 minutos
    21/08/2026
    Código de erro sobre dados binários representando falhas tratadas com urllib.error no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    urllib.error no Python: trate falhas HTTP

    Aprenda urllib.error no Python para tratar URLError, HTTPError, downloads incompletos, retries seletivos e diagnósticos de rede mais claros.

    Ler mais

    Tempo de leitura: 6 minutos
    21/08/2026
    Teclas com a palavra HTML representando entidades HTML no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    html.entities: converta entidades HTML

    Aprenda html.entities no Python para consultar entidades HTML, converter nomes e code points e evitar confundir decoding com sanitização.

    Ler mais

    Tempo de leitura: 7 minutos
    21/08/2026
    Pasta com arquivos representando tipos MIME identificados com mimetypes no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    mimetypes: detecte tipos MIME de arquivos

    Aprenda mimetypes no Python para identificar tipos de arquivos, validar uploads e gerar headers HTTP com mais segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    20/08/2026
    Código HTML em uma tela representando análise com html.parser no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    html.parser no Python: analise HTML

    Aprenda html.parser no Python para extrair texto, links e metadados, processar HTML em blocos e evitar confundir parsing com sanitização.

    Ler mais

    Tempo de leitura: 6 minutos
    20/08/2026
    Pessoa usando laptop em uma sessão web representando cookies com http.cookiejar no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    http.cookiejar no Python: gerencie cookies

    Aprenda http.cookiejar no Python para manter sessões, aplicar políticas, persistir cookies com segurança e integrar com urllib.request.

    Ler mais

    Tempo de leitura: 6 minutos
    20/08/2026