microdot — framework HTTP minimalista#

Microdot es un framework HTTP pequeño, inspirado en Flask, para MicroPython. Se ejecuta sobre asyncio, gestiona múltiples clientes concurrentes sin hilos y expone una API familiar de decoradores de rutas. Una aplicación mínima tiene este aspecto:

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#

Una instancia de aplicación HTTP. Se construye una instancia cerca del comienzo del script y se decora con manejadores de rutas; al llamar a run() o esperar a start_server() comienza el servicio.

Registro de rutas

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

Decorador que registra un manejador para url_pattern bajo los métodos HTTP indicados (por defecto ['GET']). Devuelve el decorador que, al aplicarse a una función, la registra como manejador y devuelve la función sin cambios.

url_pattern

Un patrón de ruta. Admite segmentos estáticos (/users) y segmentos dinámicos delimitados por < / >. Los segmentos dinámicos aceptan un prefijo de tipo opcional separado por :<int:id>, <path:rest>, <re:[0-9a-f]+:hex>. El tipo por defecto es string.

methods

Lista de nombres de métodos HTTP. Si se omite, solo se compara GET.

El manejador se llama primero con el objeto de la solicitud y luego con los segmentos dinámicos capturados como argumentos de palabra clave. El valor de retorno del manejador se convierte en la respuesta HTTP: una Response, una cadena, una tupla (body, status_code[, headers]), o un dict / list (enviado como JSON).

get(url_pattern: str) Callable#

Alias de conveniencia para route(url_pattern, methods=['GET']) – registra la función decorada como un manejador GET para url_pattern. Devuelve el decorador.

post(url_pattern: str) Callable#

Alias de conveniencia para route(url_pattern, methods=['POST']) – registra la función decorada como un manejador POST para url_pattern. Devuelve el decorador.

put(url_pattern: str) Callable#

Alias de conveniencia para route(url_pattern, methods=['PUT']) – registra la función decorada como un manejador PUT para url_pattern. Devuelve el decorador.

patch(url_pattern: str) Callable#

Alias de conveniencia para route(url_pattern, methods=['PATCH']) – registra la función decorada como un manejador PATCH para url_pattern. Devuelve el decorador.

delete(url_pattern: str) Callable#

Alias de conveniencia para route(url_pattern, methods=['DELETE']) – registra la función decorada como un manejador DELETE para url_pattern. Devuelve el decorador.

Hooks del ciclo de vida

before_request(f: Callable) Callable#

Decorador que registra f para ejecutarse antes de cada solicitud. f toma el objeto de la solicitud; su valor de retorno normalmente se ignora. Para cortocircuitar la solicitud, devuelve una Response (o un valor que se convierta en una) – el resto del pipeline se omite entonces y se envía esa respuesta. Devuelve f sin cambios.

after_request(f: Callable) Callable#

Decorador que registra f para ejecutarse después de cada solicitud exitosa. f toma (request, response) y debe devolver el objeto de respuesta (posiblemente modificado). Devuelve f sin cambios.

after_error_request(f: Callable) Callable#

Decorador que registra f para ejecutarse después de que Microdot genere una respuesta de error (404, 500, excepción lanzada, etc.). f toma (request, response) y debe devolver el objeto de respuesta (posiblemente modificado). Devuelve f sin cambios.

errorhandler(status_code_or_exception_class) Callable#

Decorador que registra un manejador personalizado para un código de estado HTTP o una clase de excepción de Python. Para los códigos de estado, el manejador toma solo la solicitud; para las clases de excepción, (request, exception). Devuelve el decorador.

Montaje y aborto

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

Adjunta las rutas de otra instancia Microdot bajo url_prefix. Cuando local es False (por defecto), los manejadores before / after / error de la subaplicación también se adjuntan al padre. Cuando es True, esos manejadores se ejecutan solo para las rutas de la subaplicación. Devuelve None.

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

Lanza HTTPException para abortar la solicitud actual con el código de estado dado. Nunca retorna de forma normal – el framework captura la excepción y la convierte en la respuesta de error correspondiente. Cómodo dentro de los cuerpos de las rutas:

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()

Ejecución del servidor

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

Bloquea el hilo que llama, ejecuta asyncio.run() sobre start_server(). Devuelve None solo después de que se haya llamado a shutdown() y el bucle de escucha salga. La forma más sencilla de lanzar una aplicación independiente:

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 el servidor como una corrutina. Usa esto al integrarlo con un bucle de eventos asyncio existente junto con otras tareas. La corrutina no retorna hasta que se llama a shutdown():

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

Interfaz de red en la que escuchar. '0.0.0.0' (por defecto) significa todas las interfaces; '127.0.0.1' significa solo loopback.

port

Puerto TCP en el que escuchar. Por defecto 5000 – elige 80 para HTTP simple, 443 para HTTPS.

debug

Si es True, registra cada solicitud y vuelca los trazados de pila a stdout.

ssl

Un ssl.SSLContext para envolver las conexiones entrantes en TLS. None (por defecto) significa HTTP simple.

start_serving

Solo relevante en CPython; se ignora en MicroPython.

shutdown() None#

Solicita un apagado ordenado del servidor. Es seguro llamarlo desde un manejador de ruta – la solicitud actual se completa antes de que el bucle salga. Retorna de inmediato; el apagado real ocurre una vez que termina la solicitud en curso.

Atributos

url_map: list#

Lista de rutas registradas como tuplas (methods, URLPattern, handler, url_prefix, subapp).

before_request_handlers: list#

Lista de invocables registrados con before_request(), en orden de registro. Cada uno se ejecuta con el objeto de la solicitud antes del manejador de ruta. Mutar la lista directamente funciona pero rara vez es necesario – es preferible el decorador.

after_request_handlers: list#

Lista de invocables registrados con after_request(), en orden de registro. Cada uno se ejecuta con (request, response) después de una solicitud exitosa y debe devolver la respuesta (posiblemente modificada).

after_error_request_handlers: list#

Lista de invocables registrados con after_error_request(), en orden de registro. Cada uno se ejecuta con (request, response) después de que se genera una respuesta de error (por el framework o por un manejador de errores de la aplicación) y debe devolver la respuesta.

error_handlers: dict#

Mapeo de claves de error a invocables manejadores, poblado por errorhandler(). Las claves son códigos de estado HTTP (int) o clases de excepción de Python; los valores son los manejadores registrados. Los manejadores de códigos de estado toman (request); los manejadores de clases de excepción toman (request, exception).

debug: bool#

True mientras el servidor se ejecuta con debug=True.

class Request#

class microdot.Request#

Una solicitud HTTP entrante. Las instancias se pasan a los manejadores de ruta como primer argumento posicional. Las aplicaciones no construyen Request directamente.

Atributos de clase

max_content_length: int#

Rechaza con una respuesta 413 las solicitudes cuyo Content-Length supere esta cantidad de bytes. Por defecto 16 KB.

max_body_length: int#

El cuerpo más grande que se almacena en memoria y se expone a través de body. Los cuerpos más grandes (hasta max_content_length) permanecen en el socket y deben leerse a través de stream. Por defecto 16 KB.

max_readline: int#

Longitud máxima de una sola línea de solicitud / línea de cabecera en bytes. Por defecto 2 KB.

Atributos de instancia

app: Microdot#

La instancia Microdot que gestiona la solicitud.

client_addr: tuple#

La dirección del cliente como (host, port).

method: str#

Cadena del método HTTP ('GET', 'POST', …).

scheme: str#

'http' o 'https'.

url: str#

La ruta y cadena de consulta completas de la URL de la solicitud (todo lo que va después del host).

path: str#

Solo la porción de la ruta.

query_string: str | None#

La porción cruda de la cadena de consulta, o None.

args: MultiDict#

Cadena de consulta analizada como un MultiDict.

headers: NoCaseDict#

Cabeceras de la solicitud como un NoCaseDict (búsqueda sin distinción de mayúsculas/minúsculas).

cookies: dict#

Cabecera Cookie analizada como un dict.

content_length: int#

El valor entero de Content-Length, o 0 si está ausente.

content_type: str | None#

El valor de la cabecera Content-Type, o None.

g: object#

Un contenedor de formato libre por solicitud (un objeto vacío). Asigna atributos a él para pasar valores entre los hooks y los manejadores (request.g.user = ...).

route: Callable#

La función manejadora que coincidió con esta solicitud.

url_prefix: str#

Prefijo bajo el que se montó la ruta, o ''.

subapp: Microdot | None#

La instancia de la subaplicación montada, o None.

Acceso al cuerpo

body: bytes#

El cuerpo completo de la solicitud como bytes. Vacío cuando el cuerpo se está transmitiendo en streaming (ver stream).

stream: object#

Un objeto de stream asíncrono que expone read() sobre el cuerpo. Úsalo para cuerpos más grandes que max_body_length.

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

El cuerpo analizado como JSON (un dict, list, str, int, float o bool – lo que codifique la carga útil), o None si el Content-Type no es application/json.

form: MultiDict | None#

Campos de formulario codificados en URL como un MultiDict, o None. Para multipart/form-data, decora la ruta con microdot.multipart.with_form_data().

files: dict | None#

Archivos subidos como {name: FileUpload}, poblado por microdot.multipart.with_form_data(). Es None hasta que se ejecuta ese decorador.

after_request(f: Callable) Callable#

Registra un hook after-request local a la solicitud – se ejecuta después de los manejadores after-request a nivel de aplicación, solo en caso de éxito. f toma (request, response) y debe devolver el objeto de respuesta (posiblemente modificado). Devuelve f sin cambios.

class Response#

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

Una respuesta HTTP. La mayoría de los manejadores devuelven valores que Microdot convierte automáticamente en una Response; constrúyela directamente cuando necesites cabeceras personalizadas o un código de estado específico.

body

Cuerpo de la respuesta. str se codifica en UTF-8; dict / list se codifica como JSON y el Content-Type se establece en consecuencia; bytes se envía tal cual; un objeto tipo archivo o un generador asíncrono se transmiten en streaming.

status_code

Estado HTTP numérico. Por defecto 200.

headers

Dict de cabeceras de respuesta (sin distinción de mayúsculas/minúsculas).

reason

Frase de motivo personalizada. Por defecto es "OK" para 200 y "N/A" en caso contrario.

Atributos de clase

default_content_type: str#

Content-Type usado cuando no se establece ninguno explícitamente. Por defecto 'text/plain'.

default_send_file_max_age: int | None#

Valor de Cache-Control: max-age para send_file() cuando no se proporciona max_age. None (por defecto) significa sin cabecera Cache-Control.

send_file_buffer_size: int#

Tamaño de fragmento para el streaming de send_file(). Por defecto 1024.

already_handled: None#

Centinela devuelto por los manejadores que ya han escrito la respuesta directamente (usado por las actualizaciones a WebSocket). Siempre None; lo que importa es la identidad.

types_map: dict#

Mapa de extensión a tipo MIME usado por send_file() para inferir el tipo de contenido. Mapea css, gif, html, jpg, js, json, png, txt, svg.

Métodos

Añade una cabecera Set-Cookie. expires puede ser una cadena ya formateada o un objeto similar a datetime con timetuple(). Devuelve None; la cabecera se añade a esta respuesta en el sitio.

Establece un Set-Cookie que expira inmediatamente la cookie dada. kwargs acepta las mismas opciones que set_cookie() (path, domain, secure, http_only, partitioned); expires y max_age se ignoran. Devuelve None; la cabecera se añade a esta respuesta en el sitio.

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

Devuelve una respuesta de redirección:

@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 en streaming un archivo del sistema de archivos como cuerpo de la respuesta. content_type se infiere de la extensión a través de types_map si no se proporciona. compressed=True establece Content-Encoding: gzip (el archivo ya debe estar comprimido).

Advertencia

filename se abre directamente. Nunca pases una ruta proporcionada por el usuario sin sanear – hacerlo permite la divulgación arbitraria de archivos.

Excepciones#

exception microdot.HTTPException#

Lanzada por abort() para cortocircuitar una solicitud con un código de estado específico. Microdot la captura y la convierte en la respuesta de error correspondiente.

status_code: int#

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

reason: str#

Frase de motivo a incluir en la respuesta de error. Si no se proporciona a abort(), por defecto es "<status_code> error" (p. ej. "404 error").

class URLPattern#

class microdot.URLPattern(url_pattern: str)#

La forma compilada del patrón de URL de una ruta. Construida automáticamente por Microdot.route(); las aplicaciones rara vez instancian una directamente.

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

Registra un nuevo tipo de segmento dinámico para usar en los patrones de ruta. Devuelve None; el tipo se añade al registro de tipos a nivel de clase. Por ejemplo, para añadir un tipo <uuid:...>:

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

parser es un invocable opcional que convierte la cadena capturada antes de que llegue al manejador.

match(path: str) dict | None#

Compara path con el patrón y devuelve un dict de los grupos capturados, o None si no hay coincidencia.

Clases auxiliares#

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

Una subclase de dict que almacena múltiples valores por clave. Se usa para las cadenas de consulta y los cuerpos de formulario codificados en URL donde la misma clave puede aparecer más de una vez (?tag=a&tag=b).

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

Devuelve el primer valor para key, opcionalmente convertido con type (un invocable). Devuelve default si la clave falta o la conversión falla; en caso contrario devuelve el valor (opcionalmente convertido).

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

Devuelve todos los valores para key como una lista, opcionalmente con cada valor convertido por type. Devuelve una lista vacía si key no está presente.

class microdot.NoCaseDict#

Una subclase de dict con claves de cadena sin distinción de mayúsculas/minúsculas. Se usa para Request.headers y Response.headers.

Funciones a nivel de módulo#

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

Atajo para Microdot.abort(). Nunca retorna de forma normal – lanza HTTPException. Importable como from microdot import abort.

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

Atajo para Response.redirect(). Importable como from microdot import redirect.

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

Atajo para Response.send_file().

microdot.urlencode(s: str) str#

Codifica en porcentaje un componente de URL. Reemplaza los caracteres que tienen un significado reservado en una URL (/, ?, &, =, #, espacio, …) con sus escapes hexadecimales %xx para que el resultado pueda situarse de forma segura dentro de un segmento de ruta o un valor de consulta. Devuelve el str codificado.

microdot.urldecode(s: str) str#

Decodifica en porcentaje un componente de URL – el inverso de urlencode(). Los escapes %xx se reemplazan por el byte que codifican, y + se convierte en un espacio (la convención histórica de las cadenas de consulta). Devuelve el str decodificado.

Submódulos#