microdot — framework HTTP minimalista

O Microdot é um pequeno framework HTTP para MicroPython inspirado no Flask. É executado sobre asyncio, gere múltiplos clientes concorrentes sem utilizar threads, e expõe uma API familiar baseada em decoradores de rotas. Uma aplicação mínima tem o seguinte aspeto:

from microdot import Microdot

app = Microdot()

@app.route('/')
async def index(request):
    return 'Hello, world!'

app.run(host='0.0.0.0', port=80)

class Microdot

class microdot.Microdot

Uma instância de aplicação HTTP. Constrói-se uma instância perto do início do script e decora-se com handlers de rotas; chamar run() ou aguardar start_server() inicia o serviço.

Registo de rotas

route(url_pattern: str, methods: list | None = None) Callable

Decorador que regista um handler para url_pattern sob os métodos HTTP indicados (predefinição ['GET']). Devolve o decorador que, quando aplicado a uma função, a regista como handler e devolve a função inalterada.

url_pattern

Um padrão de caminho. Suporta segmentos estáticos (/users) e segmentos dinâmicos delimitados por < / >. Os segmentos dinâmicos aceitam um prefixo de tipo opcional separado por :<int:id>, <path:rest>, <re:[0-9a-f]+:hex>. O tipo predefinido é string.

methods

Lista de nomes de métodos HTTP. Se omitida, apenas GET é correspondido.

O handler é chamado com o objeto de pedido em primeiro lugar, seguido de quaisquer segmentos dinâmicos capturados como argumentos de palavra-chave. O valor de retorno do handler torna-se a resposta HTTP: um Response, uma string, um tuplo (body, status_code[, headers]), ou um dict / lista (enviado como JSON).

get(url_pattern: str) Callable

Alias de conveniência para route(url_pattern, methods=['GET']) – regista a função decorada como handler GET para url_pattern. Devolve o decorador.

post(url_pattern: str) Callable

Alias de conveniência para route(url_pattern, methods=['POST']) – regista a função decorada como handler POST para url_pattern. Devolve o decorador.

put(url_pattern: str) Callable

Alias de conveniência para route(url_pattern, methods=['PUT']) – regista a função decorada como handler PUT para url_pattern. Devolve o decorador.

patch(url_pattern: str) Callable

Alias de conveniência para route(url_pattern, methods=['PATCH']) – regista a função decorada como handler PATCH para url_pattern. Devolve o decorador.

delete(url_pattern: str) Callable

Alias de conveniência para route(url_pattern, methods=['DELETE']) – regista a função decorada como handler DELETE para url_pattern. Devolve o decorador.

Hooks de ciclo de vida

before_request(f: Callable) Callable

Decorador que regista f para ser executada antes de cada pedido. f recebe o objeto de pedido; o seu valor de retorno é normalmente ignorado. Para curto-circuitar o pedido, retorne um Response (ou um valor que seja convertível para um) – o restante pipeline é então ignorado e essa resposta é enviada. Devolve f inalterada.

after_request(f: Callable) Callable

Decorador que regista f para ser executada após cada pedido bem-sucedido. f recebe (request, response) e deve devolver o objeto de resposta (possivelmente modificado). Devolve f inalterada.

after_error_request(f: Callable) Callable

Decorador que regista f para ser executada após o Microdot gerar uma resposta de erro (404, 500, exceção lançada, etc.). f recebe (request, response) e deve devolver o objeto de resposta (possivelmente modificado). Devolve f inalterada.

errorhandler(status_code_or_exception_class) Callable

Decorador que regista um handler personalizado para um código de estado HTTP ou uma classe de exceção Python. Para códigos de estado, o handler recebe apenas o pedido; para classes de exceção, (request, exception). Devolve o decorador.

Montagem e abortar

mount(subapp: Microdot, url_prefix: str = '', local: bool = False) None

Associa as rotas de outra instância Microdot sob url_prefix. Quando local é False (predefinição), os handlers before / after / error da sub-aplicação também são associados ao pai. Quando True, esses handlers são executados apenas para as rotas da sub-aplicação. Devolve None.

static abort(status_code: int, reason: str | None = None) None

Lança HTTPException para abortar o pedido atual com o código de estado indicado. Nunca retorna normalmente – o framework captura a exceção e converte-a na resposta de erro correspondente. Conveniente no interior de corpos de rota:

from microdot import abort

@app.get('/users/<int:id>')
def get_user(request, id):
    user = lookup(id)
    if user is None:
        abort(404)
    return user.to_dict()

Executar o servidor

run(host: str = '0.0.0.0', port: int = 5000, debug: bool = False, ssl=None) None

Bloqueia a thread de chamada, executa asyncio.run() sobre start_server(). Devolve None apenas após shutdown() ter sido chamado e o ciclo de escuta terminar. A forma mais simples de lançar uma aplicação autónoma:

app.run(host='0.0.0.0', port=80)
async start_server(host: str = '0.0.0.0', port: int = 5000, debug: bool = False, ssl=None, start_serving: bool = True) None

Inicia o servidor como uma corrotina. Use isto ao integrar com um ciclo de eventos asyncio existente juntamente com outras tarefas. A corrotina não retorna até shutdown() ser chamado:

async def main():
    await asyncio.gather(
        app.start_server(port=80),
        capture_loop(),
    )
host

Interface de rede a escutar. '0.0.0.0' (predefinição) significa todas as interfaces; '127.0.0.1' significa apenas loopback.

port

Porta TCP a escutar. Predefinição 5000 – use 80 para HTTP simples, 443 para HTTPS.

debug

Se True, regista cada pedido e imprime tracebacks para stdout.

ssl

Um ssl.SSLContext para envolver as ligações recebidas em TLS. None (predefinição) significa HTTP simples.

start_serving

Relevante apenas no CPython; ignorado no MicroPython.

shutdown() None

Solicita um encerramento gracioso do servidor. Seguro para chamar a partir de um handler de rota – o pedido atual é concluído antes do ciclo terminar. Retorna imediatamente; o encerramento efetivo ocorre assim que o pedido em curso terminar.

Atributos

url_map: list

Lista de rotas registadas como tuplos (methods, URLPattern, handler, url_prefix, subapp).

before_request_handlers: list

Lista de chamáveis registados com before_request(), por ordem de registo. Cada um é executado com o objeto de pedido antes do handler de rota. Alterar a lista diretamente é possível, mas raramente necessário – prefira o decorador.

after_request_handlers: list

Lista de chamáveis registados com after_request(), por ordem de registo. Cada um é executado com (request, response) após um pedido bem-sucedido e deve devolver a resposta (possivelmente modificada).

after_error_request_handlers: list

Lista de chamáveis registados com after_error_request(), por ordem de registo. Cada um é executado com (request, response) após ser gerada uma resposta de erro (pelo framework ou por um handler de erro da aplicação) e deve devolver a resposta.

error_handlers: dict

Mapeamento de chaves de erro para chamáveis de handler, preenchido por errorhandler(). As chaves são códigos de estado HTTP (int) ou classes de exceção Python; os valores são os handlers registados. Os handlers de código de estado recebem (request); os handlers de classe de exceção recebem (request, exception).

debug: bool

True enquanto o servidor está em execução com debug=True.

class Request

class microdot.Request

Um pedido HTTP recebido. As instâncias são passadas aos handlers de rota como primeiro argumento posicional. As aplicações não constroem Request diretamente.

Atributos de classe

max_content_length: int

Rejeita pedidos cujo Content-Length exceda este número de bytes com uma resposta 413. Predefinição 16 KB.

max_body_length: int

Maior corpo que é armazenado em memória e exposto via body. Corpos maiores (até max_content_length) permanecem no socket e devem ser lidos através de stream. Predefinição 16 KB.

max_readline: int

Comprimento máximo de uma linha de pedido / linha de cabeçalho em bytes. Predefinição 2 KB.

Atributos de instância

app: Microdot

A instância Microdot que trata o pedido.

client_addr: tuple

O endereço do cliente como (host, port).

method: str

String do método HTTP ('GET', 'POST', …).

scheme: str

'http' ou 'https'.

url: str

O URL completo do pedido, incluindo caminho e query string (tudo após o host).

path: str

Apenas a parte do caminho.

query_string: str | None

A parte da query string em bruto, ou None.

args: MultiDict

Query string analisada como MultiDict.

headers: NoCaseDict

Cabeçalhos do pedido como NoCaseDict (pesquisa insensível a maiúsculas/minúsculas).

cookies: dict

Cabeçalho Cookie analisado como dict.

content_length: int

O valor inteiro de Content-Length, ou 0 se ausente.

content_type: str | None

O valor do cabeçalho Content-Type, ou None.

g: object

Um contentor de livre forma por pedido (um objeto simples). Atribua-lhe atributos para passar valores entre hooks e handlers (request.g.user = ...).

route: Callable

A função de handler que correspondeu a este pedido.

url_prefix: str

Prefixo sob o qual a rota foi montada, ou ''.

subapp: Microdot | None

A instância da sub-aplicação montada, ou None.

Acesso ao corpo

body: bytes

O corpo completo do pedido como bytes. Vazio quando o corpo está a ser transmitido em stream (ver stream).

stream: object

Um objeto de stream assíncrono que expõe read() sobre o corpo. Use isto para corpos maiores que max_body_length.

json: dict | list | str | int | float | bool | None

O corpo analisado como JSON (um dict, list, str, int, float, ou bool – o que o payload codificar), ou None se o Content-Type não for application/json.

form: MultiDict | None

Campos de formulário com codificação URL como MultiDict, ou None. Para multipart/form-data, decore a rota com microdot.multipart.with_form_data().

files: dict | None

Ficheiros carregados como {name: FileUpload}, preenchido por microdot.multipart.with_form_data(). None até o decorador ser executado.

after_request(f: Callable) Callable

Regista um hook after-request local ao pedido – executado após os handlers after-request ao nível da aplicação, apenas em caso de sucesso. f recebe (request, response) e deve devolver o objeto de resposta (possivelmente modificado). Devolve f inalterada.

class Response

class microdot.Response(body=b'', status_code: int = 200, headers: dict | None = None, reason: str | None = None)

Uma resposta HTTP. A maioria dos handlers devolve valores que o Microdot converte automaticamente para Response; construa um diretamente quando precisar de cabeçalhos personalizados ou de um código de estado específico.

body

Corpo da resposta. str é codificado em UTF-8; dict / list é codificado como JSON e o Content-Type é definido em conformidade; bytes é enviado tal como está; um objeto do tipo ficheiro ou um gerador assíncrono transmite em stream.

status_code

Estado HTTP numérico. Predefinição 200.

headers

Dict de cabeçalhos de resposta (insensível a maiúsculas/minúsculas).

reason

Frase de razão personalizada. Predefinição "OK" para 200 e "N/A" caso contrário.

Atributos de classe

default_content_type: str

Content-Type utilizado quando nenhum é definido explicitamente. Predefinição 'text/plain'.

default_send_file_max_age: int | None

Valor de Cache-Control: max-age para send_file() quando max_age não é fornecido. None (predefinição) significa sem cabeçalho Cache-Control.

send_file_buffer_size: int

Tamanho do bloco para streaming em send_file(). Predefinição 1024.

already_handled: None

Sentinela devolvido por handlers que já escreveram a resposta diretamente (utilizado por upgrades WebSocket). Sempre None; é a identidade que importa.

types_map: dict

Mapa de extensão para tipo MIME utilizado por send_file() para inferência de tipo de conteúdo. Mapeia css, gif, html, jpg, js, json, png, txt, svg.

Métodos

Adiciona um cabeçalho Set-Cookie. expires pode ser uma string pré-formatada ou um objeto semelhante a datetime com timetuple(). Devolve None; o cabeçalho é acrescentado a esta resposta no local.

Define um Set-Cookie que expira o cookie indicado imediatamente. kwargs aceita as mesmas opções que set_cookie() (path, domain, secure, http_only, partitioned); expires e max_age são ignorados. Devolve None; o cabeçalho é acrescentado a esta resposta no local.

classmethod redirect(location: str, status_code: int = 302) Response

Devolve uma resposta de redirecionamento:

@app.get('/old')
def old(request):
    return Response.redirect('/new')
classmethod send_file(filename: str, status_code: int = 200, content_type: str | None = None, stream=None, max_age: int | None = None, compressed: bool | str = False, file_extension: str = '') Response

Transmite em stream um ficheiro do sistema de ficheiros como corpo da resposta. content_type é inferido a partir da extensão via types_map se não for fornecido. compressed=True define Content-Encoding: gzip (o ficheiro já deve estar comprimido).

Aviso

filename é aberto diretamente. Nunca passe um caminho fornecido pelo utilizador sem sanitização – fazer isso permite a divulgação arbitrária de ficheiros.

Exceções

exception microdot.HTTPException

Lançada por abort() para curto-circuitar um pedido com um código de estado específico. O Microdot captura esta exceção e converte-a na resposta de erro correspondente.

status_code: int

Código de estado HTTP numérico a devolver – o valor passado a abort().

reason: str

Frase de razão a incluir na resposta de erro. Se não for fornecida a abort(), tem como predefinição "<status_code> error" (por exemplo, "404 error").

class URLPattern

class microdot.URLPattern(url_pattern: str)

A forma compilada do padrão de URL de uma rota. Construído automaticamente por Microdot.route(); as aplicações raramente instanciam um diretamente.

classmethod register_type(type_name: str, pattern: str = '[^/]+', parser: Callable | None = None) None

Regista um novo tipo de segmento dinâmico para utilização em padrões de rota. Devolve None; o tipo é adicionado ao registo de tipos ao nível da classe. Por exemplo, para adicionar um tipo <uuid:...>

URLPattern.register_type('uuid', '[0-9a-f-]{36}')

parser é um chamável opcional que converte a string capturada antes de esta chegar ao handler.

match(path: str) dict | None

Faz a correspondência de path com o padrão e devolve um dict de grupos capturados, ou None se não houver correspondência.

Classes auxiliares

class microdot.MultiDict(initial_dict: dict | None = None)

Uma subclasse de dict que armazena múltiplos valores por chave. Utilizada para query strings e corpos de formulário com codificação URL onde a mesma chave pode aparecer mais do que uma vez (?tag=a&tag=b).

get(key, default=None, type: Callable | None = None)

Devolve o primeiro valor para key, opcionalmente convertido com type (um chamável). Devolve default se a chave estiver ausente ou a conversão falhar; caso contrário, devolve o valor (opcionalmente convertido).

getlist(key, type: Callable | None = None) list

Devolve todos os valores para key como uma lista, opcionalmente com cada valor convertido por type. Devolve uma lista vazia se key não estiver presente.

class microdot.NoCaseDict

Uma subclasse de dict com chaves de string insensíveis a maiúsculas/minúsculas. Utilizada para Request.headers e Response.headers.

Funções ao nível do módulo

microdot.abort(status_code: int, reason: str | None = None) None

Atalho para Microdot.abort(). Nunca retorna normalmente – lança HTTPException. Importável como from microdot import abort.

microdot.redirect(location: str, status_code: int = 302) Response

Atalho para Response.redirect(). Importável como from microdot import redirect.

microdot.send_file(filename: str, **kwargs) Response

Atalho para Response.send_file().

microdot.urlencode(s: str) str

Codifica em percentagem um componente de URL. Substitui caracteres com significado reservado num URL (/, ?, &, =, #, espaço, …) pelos seus escapes hexadecimais %xx, para que o resultado possa ser colocado com segurança dentro de um segmento de caminho ou valor de query. Devolve a str codificada.

microdot.urldecode(s: str) str

Descodifica em percentagem um componente de URL – o inverso de urlencode(). Os escapes %xx são substituídos pelo byte que codificam, e + é convertido em espaço (a convenção histórica das query strings). Devolve a str descodificada.

Submódulos