microdot — minimální HTTP framework

Microdot je malý HTTP framework pro MicroPython inspirovaný Flaskem. Běží nad asyncio, obsluhuje více souběžných klientů bez vláken a poskytuje známé API založené na dekorátorech rout. Minimální aplikace vypadá takto:

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

Instance HTTP aplikace. Jedna instance se obvykle vytvoří poblíž začátku skriptu a opatří se obslužnými rutinami rout; voláním run() nebo čekáním na start_server() se zahájí obsluha.

Registrace rout

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

Dekorátor, který registruje obslužnou rutinu pro url_pattern pod uvedenými HTTP metodami (výchozí ['GET']). Vrací dekorátor, který po aplikaci na funkci tuto funkci zaregistruje jako obslužnou rutinu a vrátí ji beze změny.

url_pattern

Vzor cesty. Podporuje statické segmenty (/users) a dynamické segmenty uzavřené v < / >. Dynamické segmenty přijímají volitelnou předponu typu oddělenou znakem :<int:id>, <path:rest>, <re:[0-9a-f]+:hex>. Výchozí typ je string.

methods

Seznam názvů HTTP metod. Pokud je vynechán, odpovídá pouze GET.

Obslužná rutina je volána nejprve s objektem požadavku a poté se všemi zachycenými dynamickými segmenty jako pojmenovanými argumenty. Návratová hodnota obslužné rutiny se stane HTTP odpovědí: Response, řetězec, n-tice (body, status_code[, headers]) nebo dict / list (odeslaný jako JSON).

get(url_pattern: str) Callable

Praktický alias pro route(url_pattern, methods=['GET']) – zaregistruje dekorovanou funkci jako obslužnou rutinu GET pro url_pattern. Vrací dekorátor.

post(url_pattern: str) Callable

Praktický alias pro route(url_pattern, methods=['POST']) – zaregistruje dekorovanou funkci jako obslužnou rutinu POST pro url_pattern. Vrací dekorátor.

put(url_pattern: str) Callable

Praktický alias pro route(url_pattern, methods=['PUT']) – zaregistruje dekorovanou funkci jako obslužnou rutinu PUT pro url_pattern. Vrací dekorátor.

patch(url_pattern: str) Callable

Praktický alias pro route(url_pattern, methods=['PATCH']) – zaregistruje dekorovanou funkci jako obslužnou rutinu PATCH pro url_pattern. Vrací dekorátor.

delete(url_pattern: str) Callable

Praktický alias pro route(url_pattern, methods=['DELETE']) – zaregistruje dekorovanou funkci jako obslužnou rutinu DELETE pro url_pattern. Vrací dekorátor.

Háčky životního cyklu

before_request(f: Callable) Callable

Dekorátor, který registruje f ke spuštění před každým požadavkem. f přebírá objekt požadavku; jeho návratová hodnota je obvykle ignorována. Chcete-li požadavek zkrátit, vraťte Response (nebo hodnotu, která se na ni převede) – zbytek pipeline se pak přeskočí a odešle se tato odpověď. Vrací f beze změny.

after_request(f: Callable) Callable

Dekorátor, který registruje f ke spuštění po každém úspěšném požadavku. f přebírá (request, response) a musí vrátit (případně upravený) objekt odpovědi. Vrací f beze změny.

after_error_request(f: Callable) Callable

Dekorátor, který registruje f ke spuštění poté, co Microdot vygeneruje chybovou odpověď (404, 500, vyvolaná výjimka atd.). f přebírá (request, response) a musí vrátit (případně upravený) objekt odpovědi. Vrací f beze změny.

errorhandler(status_code_or_exception_class) Callable

Dekorátor, který registruje vlastní obslužnou rutinu pro HTTP stavový kód nebo třídu výjimky Pythonu. U stavových kódů přebírá obslužná rutina pouze požadavek; u tříd výjimek (request, exception). Vrací dekorátor.

Připojování a přerušování

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

Připojí routy jiné instance Microdot pod url_prefix. Když je local False (výchozí), připojí se k rodiči i rutiny sub-aplikace before / after / error. Když je True, tyto rutiny běží pouze pro routy sub-aplikace. Vrací None.

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

Vyvolá HTTPException pro přerušení aktuálního požadavku s daným stavovým kódem. Nikdy se nevrací normálně – framework výjimku zachytí a převede ji na odpovídající chybovou odpověď. Praktické uvnitř těla routy:

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

Spuštění serveru

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

Zablokuje volající vlákno a spustí asyncio.run() na start_server(). Vrací None až poté, co byla zavolána shutdown() a naslouchací smyčka skončila. Nejjednodušší způsob spuštění samostatné aplikace:

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

Spustí server jako korutinu. Použijte to při integraci se stávající smyčkou událostí asyncio vedle dalších úloh. Korutina se nevrátí, dokud není zavolána shutdown()

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

Síťové rozhraní, na kterém se naslouchá. '0.0.0.0' (výchozí) znamená všechna rozhraní; '127.0.0.1' znamená pouze loopback.

port

TCP port, na kterém se naslouchá. Výchozí 5000 – zvolte 80 pro běžné HTTP, 443 pro HTTPS.

debug

Pokud True, loguje každý požadavek a vypisuje zpětné trasování na stdout.

ssl

Objekt ssl.SSLContext pro zabalení příchozích spojení do TLS. None (výchozí) znamená běžné HTTP.

start_serving

Relevantní pouze na CPythonu; na MicroPythonu se ignoruje.

shutdown() None

Požádá o korektní vypnutí serveru. Lze bezpečně volat z obslužné rutiny routy – aktuální požadavek se dokončí předtím, než smyčka skončí. Vrací se okamžitě; samotné vypnutí proběhne, jakmile se dokončí právě zpracovávaný požadavek.

Atributy

url_map: list

Seznam registrovaných rout jako n-tic (methods, URLPattern, handler, url_prefix, subapp).

before_request_handlers: list

Seznam volatelných objektů registrovaných pomocí before_request() v pořadí registrace. Každý se spouští s objektem požadavku před obslužnou rutinou routy. Přímá změna seznamu funguje, ale je zřídka potřeba – upřednostněte dekorátor.

after_request_handlers: list

Seznam volatelných objektů registrovaných pomocí after_request() v pořadí registrace. Každý se spouští s (request, response) po úspěšném požadavku a musí vrátit (případně upravenou) odpověď.

after_error_request_handlers: list

Seznam volatelných objektů registrovaných pomocí after_error_request() v pořadí registrace. Každý se spouští s (request, response) poté, co je vygenerována chybová odpověď (frameworkem nebo aplikační obslužnou rutinou chyb), a musí vrátit odpověď.

error_handlers: dict

Mapování chybových klíčů na volatelné obslužné rutiny, naplněné pomocí errorhandler(). Klíče jsou buď HTTP stavové kódy (int), nebo třídy výjimek Pythonu; hodnotami jsou registrované obslužné rutiny. Obslužné rutiny stavových kódů přebírají (request); obslužné rutiny tříd výjimek přebírají (request, exception).

debug: bool

True, dokud server běží s debug=True.

class Request

class microdot.Request

Příchozí HTTP požadavek. Instance se předávají obslužným rutinám rout jako první poziční argument. Aplikace nevytvářejí Request přímo.

Atributy třídy

max_content_length: int

Odmítne požadavky, jejichž Content-Length překračuje tento počet bajtů, s odpovědí 413. Výchozí 16 KB.

max_body_length: int

Největší tělo, které se ukládá do paměti a zpřístupňuje přes body. Větší těla (až do max_content_length) zůstávají na socketu a musí se číst přes stream. Výchozí 16 KB.

max_readline: int

Maximální délka jednoho řádku požadavku / řádku hlavičky v bajtech. Výchozí 2 KB.

Atributy instance

app: Microdot

Instance Microdot obsluhující požadavek.

client_addr: tuple

Adresa klienta jako (host, port).

method: str

Řetězec HTTP metody ('GET', 'POST', …).

scheme: str

'http' nebo 'https'.

url: str

Úplná cesta URL požadavku a dotazovací řetězec (vše za hostitelem).

path: str

Pouze část s cestou.

query_string: str | None

Surová část dotazovacího řetězce, nebo None.

args: MultiDict

Naparsovaný dotazovací řetězec jako MultiDict.

headers: NoCaseDict

Hlavičky požadavku jako NoCaseDict (vyhledávání bez ohledu na velikost písmen).

cookies: dict

Naparsovaná hlavička Cookie jako dict.

content_length: int

Celočíselná hodnota Content-Length, nebo 0, pokud chybí.

content_type: str | None

Hodnota hlavičky Content-Type, nebo None.

g: object

Volně formátovaný kontejner pro jednotlivý požadavek (prostý objekt). Přiřazujte mu atributy pro předávání hodnot mezi háčky a obslužnými rutinami (request.g.user = ...).

route: Callable

Funkce obslužné rutiny, která odpovídala tomuto požadavku.

url_prefix: str

Předpona, pod kterou byla routa připojena, nebo ''.

subapp: Microdot | None

Instance připojené sub-aplikace, nebo None.

Přístup k tělu

body: bytes

Úplné tělo požadavku jako bytes. Prázdné, když je tělo streamováno (viz stream).

stream: object

Asynchronní stream objekt zpřístupňující read() nad tělem. Použijte jej pro těla větší než max_body_length.

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

Tělo naparsované jako JSON (dict, list, str, int, float nebo bool – podle toho, co payload kóduje), nebo None, pokud Content-Type není application/json.

form: MultiDict | None

Pole formuláře kódovaná v URL jako MultiDict, nebo None. Pro multipart/form-data opatřete routu dekorátorem microdot.multipart.with_form_data().

files: dict | None

Nahrané soubory jako {name: FileUpload}, naplněné pomocí microdot.multipart.with_form_data(). None, dokud tento dekorátor neproběhne.

after_request(f: Callable) Callable

Zaregistruje after-request háček lokální pro daný požadavek – spustí se po obslužných rutinách after-request na úrovni aplikace, pouze při úspěchu. f přebírá (request, response) a musí vrátit (případně upravený) objekt odpovědi. Vrací f beze změny.

class Response

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

HTTP odpověď. Většina obslužných rutin vrací hodnoty, které Microdot automaticky převede na Response; vytvořte ji přímo, když potřebujete vlastní hlavičky nebo konkrétní stavový kód.

body

Tělo odpovědi. str se kóduje v UTF-8; dict / list se kóduje jako JSON a odpovídajícím způsobem se nastaví Content-Type; bytes se odešle tak, jak je; objekt podobný souboru nebo asynchronní generátor se streamuje.

status_code

Číselný HTTP stav. Výchozí 200.

headers

Dict hlaviček odpovědi (bez ohledu na velikost písmen).

reason

Vlastní textový popis. Výchozí "OK" pro 200 a "N/A" jinak.

Atributy třídy

default_content_type: str

Content-Type použitý, když není nastaven explicitně. Výchozí 'text/plain'.

default_send_file_max_age: int | None

Hodnota Cache-Control: max-age pro send_file(), když není zadán max_age. None (výchozí) znamená žádnou hlavičku Cache-Control.

send_file_buffer_size: int

Velikost úseku pro streamování send_file(). Výchozí 1024.

already_handled: None

Sentinel vracený z obslužných rutin, které již zapsaly odpověď přímo (používaný upgradem na WebSocket). Vždy None; podstatná je identita.

types_map: dict

Mapa přípona-na-mime-typ používaná send_file() pro odvození typu obsahu. Mapuje css, gif, html, jpg, js, json, png, txt, svg.

Metody

Přidá hlavičku Set-Cookie. expires může být předem naformátovaný řetězec nebo objekt podobný datetime s timetuple(). Vrací None; hlavička se připojí přímo k této odpovědi.

Nastaví Set-Cookie, který danou cookie okamžitě zneplatní. kwargs přijímá stejné volby jako set_cookie() (path, domain, secure, http_only, partitioned); expires a max_age se ignorují. Vrací None; hlavička se připojí přímo k této odpovědi.

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

Vrátí přesměrovací odpověď:

@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

Streamuje soubor ze souborového systému jako tělo odpovědi. content_type se odvodí z přípony přes types_map, pokud není zadán. compressed=True nastaví Content-Encoding: gzip (soubor již musí být komprimovaný).

Varování

filename se otevírá přímo. Nikdy nepředávejte neošetřenou cestu zadanou uživatelem – umožnilo by to vyzrazení libovolného souboru.

Výjimky

exception microdot.HTTPException

Vyvolaná pomocí abort() pro zkrácení požadavku s konkrétním stavovým kódem. Microdot ji zachytí a převede na odpovídající chybovou odpověď.

status_code: int

Číselný HTTP stavový kód k vrácení – hodnota předaná abort().

reason: str

Textový popis k zahrnutí do chybové odpovědi. Pokud není zadán abort(), výchozí je "<status_code> error" (např. "404 error").

class URLPattern

class microdot.URLPattern(url_pattern: str)

Zkompilovaná podoba URL vzoru routy. Vytváří se automaticky pomocí Microdot.route(); aplikace ji zřídka instancují přímo.

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

Zaregistruje nový typ dynamického segmentu pro použití ve vzorech rout. Vrací None; typ se přidá do registru typů na úrovni třídy. Například pro přidání typu <uuid:...>

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

parser je volitelný volatelný objekt, který převede zachycený řetězec, než se dostane k obslužné rutině.

match(path: str) dict | None

Porovná path se vzorem a vrátí dict zachycených skupin, nebo None při neshodě.

Pomocné třídy

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

Podtřída dict, která ukládá více hodnot na klíč. Používá se pro dotazovací řetězce a těla formulářů kódovaná v URL, kde se stejný klíč může vyskytnout vícekrát (?tag=a&tag=b).

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

Vrátí první hodnotu pro key, volitelně převedenou pomocí type (volatelný objekt). Vrátí default, pokud klíč chybí nebo převod selže; jinak vrátí (případně převedenou) hodnotu.

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

Vrátí všechny hodnoty pro key jako seznam, volitelně s každou hodnotou převedenou pomocí type. Vrátí prázdný seznam, pokud key není přítomen.

class microdot.NoCaseDict

Podtřída dict s řetězcovými klíči bez ohledu na velikost písmen. Používá se pro Request.headers a Response.headers.

Funkce na úrovni modulu

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

Zkratka pro Microdot.abort(). Nikdy se nevrací normálně – vyvolává HTTPException. Importovatelná jako from microdot import abort.

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

Zkratka pro Response.redirect(). Importovatelná jako from microdot import redirect.

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

Zkratka pro Response.send_file().

microdot.urlencode(s: str) str

Procentně zakóduje komponentu URL. Nahradí znaky, které mají v URL vyhrazený význam (/, ?, &, =, #, mezera, …), jejich %xx hexadecimálními escape sekvencemi, takže výsledek lze bezpečně umístit do segmentu cesty nebo hodnoty dotazu. Vrací zakódovaný str.

microdot.urldecode(s: str) str

Procentně dekóduje komponentu URL – inverze urlencode(). Escape sekvence %xx se nahradí bajtem, který kódují, a + se převede na mezeru (historická konvence dotazovacích řetězců). Vrací dekódovaný str.

Podmoduly