microdot — minimaal HTTP-framework

Microdot is een klein, door Flask geïnspireerd HTTP-framework voor MicroPython. Het draait bovenop asyncio, verwerkt meerdere gelijktijdige clients zonder threads en biedt een vertrouwde route-decorator-API. Een minimale applicatie ziet er als volgt uit:

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

Een HTTP-applicatie-instantie. Eén instantie wordt bovenaan het script aangemaakt en voorzien van route-handlers; het aanroepen van run() of het awaiten van start_server() start de bediening.

Routeregistratie

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

Decorator die een handler registreert voor url_pattern onder de opgegeven HTTP-methoden (standaard ['GET']). Geeft de decorator terug die, wanneer toegepast op een functie, deze als handler registreert en de functie ongewijzigd teruggeeft.

url_pattern

Een padpatroon. Ondersteunt statische segmenten (/users) en dynamische segmenten omsloten door < / >. Dynamische segmenten accepteren een optioneel typevoorvoegsel gescheiden door :<int:id>, <path:rest>, <re:[0-9a-f]+:hex>. Het standaardtype is string.

methods

Lijst van HTTP-methodenamen. Indien weggelaten wordt alleen GET gematcht.

De handler wordt eerst aangeroepen met het request-object, gevolgd door eventuele vastgelegde dynamische segmenten als keyword-argumenten. De retourwaarde van de handler wordt de HTTP-respons: een Response, een string, een tuple (body, status_code[, headers]), of een dict / list (verzonden als JSON).

get(url_pattern: str) Callable

Handige alias voor route(url_pattern, methods=['GET']) – registreert de gedecoreerde functie als GET-handler voor url_pattern. Geeft de decorator terug.

post(url_pattern: str) Callable

Handige alias voor route(url_pattern, methods=['POST']) – registreert de gedecoreerde functie als POST-handler voor url_pattern. Geeft de decorator terug.

put(url_pattern: str) Callable

Handige alias voor route(url_pattern, methods=['PUT']) – registreert de gedecoreerde functie als PUT-handler voor url_pattern. Geeft de decorator terug.

patch(url_pattern: str) Callable

Handige alias voor route(url_pattern, methods=['PATCH']) – registreert de gedecoreerde functie als PATCH-handler voor url_pattern. Geeft de decorator terug.

delete(url_pattern: str) Callable

Handige alias voor route(url_pattern, methods=['DELETE']) – registreert de gedecoreerde functie als DELETE-handler voor url_pattern. Geeft de decorator terug.

Levenscyclus-hooks

before_request(f: Callable) Callable

Decorator die f registreert om vóór elk request te draaien. f neemt het request-object; de retourwaarde wordt normaal genegeerd. Om het request kort te sluiten, geef een Response terug (of een waarde die daarnaar converteert) – de rest van de pijplijn wordt dan overgeslagen en die respons wordt verzonden. Geeft f ongewijzigd terug.

after_request(f: Callable) Callable

Decorator die f registreert om na elk succesvol request te draaien. f neemt (request, response) en moet het (mogelijk gewijzigde) respons-object teruggeven. Geeft f ongewijzigd terug.

after_error_request(f: Callable) Callable

Decorator die f registreert om te draaien nadat Microdot een foutrespons heeft gegenereerd (404, 500, opgegooide uitzondering, enz.). f neemt (request, response) en moet het (mogelijk gewijzigde) respons-object teruggeven. Geeft f ongewijzigd terug.

errorhandler(status_code_or_exception_class) Callable

Decorator die een aangepaste handler registreert voor een HTTP-statuscode of een Python-uitzonderingsklasse. Voor statuscodes neemt de handler alleen het request; voor uitzonderingsklassen (request, exception). Geeft de decorator terug.

Mounten en afbreken

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

Voeg de routes van een andere Microdot-instantie toe onder url_prefix. Wanneer local False is (standaard), worden de before-/after-/error-handlers van de sub-app ook aan de ouder toegevoegd. Wanneer True, draaien die handlers alleen voor routes van de sub-app. Geeft None terug.

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

Gooi HTTPException op om het huidige request af te breken met de opgegeven statuscode. Keert nooit normaal terug – het framework vangt de uitzondering op en zet deze om in de bijbehorende foutrespons. Handig binnen route-bodies:

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

De server draaien

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

Blokkeer de aanroepende thread en draai asyncio.run() op start_server(). Geeft pas None terug nadat shutdown() is aangeroepen en de luisterlus is gestopt. De eenvoudigste manier om een standalone-app te starten:

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

Start de server als een coroutine. Gebruik dit bij integratie met een bestaande asyncio-event-loop naast andere taken. De coroutine keert pas terug wanneer shutdown() wordt aangeroepen:

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

Netwerkinterface om op te luisteren. '0.0.0.0' (standaard) betekent alle interfaces; '127.0.0.1' betekent alleen loopback.

port

TCP-poort om op te luisteren. Standaard 5000 – kies 80 voor gewoon HTTP, 443 voor HTTPS.

debug

Indien True, log elk request en dump tracebacks naar stdout.

ssl

Een ssl.SSLContext om inkomende verbindingen in TLS te verpakken. None (standaard) betekent gewoon HTTP.

start_serving

Alleen relevant op CPython; genegeerd op MicroPython.

shutdown() None

Vraag een nette afsluiting van de server aan. Veilig om aan te roepen vanuit een route-handler – het huidige request voltooit voordat de lus stopt. Keert onmiddellijk terug; de daadwerkelijke afsluiting gebeurt zodra het lopende request klaar is.

Attributen

url_map: list

Lijst van geregistreerde routes als (methods, URLPattern, handler, url_prefix, subapp)-tuples.

before_request_handlers: list

Lijst van callables geregistreerd met before_request(), in registratievolgorde. Elke draait met het request-object vóór de route-handler. De lijst direct muteren werkt, maar is zelden nodig – gebruik bij voorkeur de decorator.

after_request_handlers: list

Lijst van callables geregistreerd met after_request(), in registratievolgorde. Elke draait met (request, response) na een succesvol request en moet de (mogelijk gewijzigde) respons teruggeven.

after_error_request_handlers: list

Lijst van callables geregistreerd met after_error_request(), in registratievolgorde. Elke draait met (request, response) nadat een foutrespons is gegenereerd (door het framework of door een foutafhandelaar van de applicatie) en moet de respons teruggeven.

error_handlers: dict

Mapping van foutsleutels naar handler-callables, gevuld door errorhandler(). Sleutels zijn ofwel HTTP-statuscodes (int) of Python-uitzonderingsklassen; waarden zijn de geregistreerde handlers. Statuscode-handlers nemen (request); uitzonderingsklasse-handlers nemen (request, exception).

debug: bool

True zolang de server draait met debug=True.

class Request

class microdot.Request

Een inkomend HTTP-request. Instanties worden als eerste positionele argument aan route-handlers doorgegeven. Applicaties construeren Request niet rechtstreeks.

Klasse-attributen

max_content_length: int

Weiger requests waarvan de Content-Length dit aantal bytes overschrijdt met een 413-respons. Standaard 16 KB.

max_body_length: int

Grootste body die in het geheugen wordt gebufferd en beschikbaar wordt gesteld via body. Grotere bodies (tot max_content_length) blijven op de socket en moeten via stream worden gelezen. Standaard 16 KB.

max_readline: int

Maximale lengte van een enkele requestregel / headerregel in bytes. Standaard 2 KB.

Instantie-attributen

app: Microdot

De Microdot-instantie die het request afhandelt.

client_addr: tuple

Het adres van de client als (host, port).

method: str

HTTP-methode-string ('GET', 'POST', …).

scheme: str

'http' of 'https'.

url: str

Het volledige request-URL-pad en de querystring (alles na de host).

path: str

Alleen het padgedeelte.

query_string: str | None

Het ruwe querystring-gedeelte, of None.

args: MultiDict

Geparseerde querystring als een MultiDict.

headers: NoCaseDict

Request-headers als een NoCaseDict (hoofdletterongevoelige opzoeking).

cookies: dict

Geparseerde Cookie-header als een dict.

content_length: int

De integer-waarde van Content-Length, of 0 indien afwezig.

content_type: str | None

De waarde van de Content-Type-header, of None.

g: object

Een vrij in te vullen container per request (een kaal object). Ken er attributen aan toe om waarden tussen hooks en handlers door te geven (request.g.user = ...).

route: Callable

De handler-functie die op dit request matchte.

url_prefix: str

Voorvoegsel waaronder de route is gemount, of ''.

subapp: Microdot | None

De gemounte sub-app-instantie, of None.

Body-toegang

body: bytes

De volledige request-body als bytes. Leeg wanneer de body wordt gestreamd (zie stream).

stream: object

Een async stream-object dat read() over de body biedt. Gebruik dit voor bodies groter dan max_body_length.

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

De body geparseerd als JSON (een dict, list, str, int, float, of bool – wat de payload ook codeert), of None als de Content-Type niet application/json is.

form: MultiDict | None

URL-gecodeerde formuliervelden als een MultiDict, of None. Voor multipart/form-data decoreer je de route met microdot.multipart.with_form_data().

files: dict | None

Geüploade bestanden als {name: FileUpload}, gevuld door microdot.multipart.with_form_data(). None totdat die decorator draait.

after_request(f: Callable) Callable

Registreer een request-lokale after-request-hook – draait na de after-request-handlers op applicatieniveau, alleen bij succes. f neemt (request, response) en moet het (mogelijk gewijzigde) respons-object teruggeven. Geeft f ongewijzigd terug.

class Response

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

Een HTTP-respons. De meeste handlers geven waarden terug die Microdot automatisch omzet naar een Response; construeer er zelf een wanneer je aangepaste headers of een specifieke statuscode nodig hebt.

body

Respons-body. str wordt UTF-8-gecodeerd; dict / list wordt JSON-gecodeerd en de Content-Type wordt dienovereenkomstig ingesteld; bytes wordt as-is verzonden; een file-achtig object of async generator streamt.

status_code

Numerieke HTTP-status. Standaard 200.

headers

Dict van respons-headers (hoofdletterongevoelig).

reason

Aangepaste reden-tekst. Standaard "OK" voor 200 en anders "N/A".

Klasse-attributen

default_content_type: str

Content-Type die wordt gebruikt wanneer er geen expliciet is ingesteld. Standaard 'text/plain'.

default_send_file_max_age: int | None

Cache-Control: max-age-waarde voor send_file() wanneer max_age niet is opgegeven. None (standaard) betekent geen Cache-Control-header.

send_file_buffer_size: int

Chunkgrootte voor het streamen van send_file(). Standaard 1024.

already_handled: None

Sentinel die wordt teruggegeven door handlers die de respons al rechtstreeks hebben geschreven (gebruikt door WebSocket-upgrades). Altijd None; het gaat om de identiteit.

types_map: dict

Mapping van extensie naar mime-type die door send_file() wordt gebruikt voor het afleiden van het content-type. Wijst css, gif, html, jpg, js, json, png, txt, svg toe.

Methoden

Voeg een Set-Cookie-header toe. expires mag een voorgeformatteerde string zijn of een datetime-achtig object met timetuple(). Geeft None terug; de header wordt ter plekke aan deze respons toegevoegd.

Stel een Set-Cookie in die de opgegeven cookie onmiddellijk laat verlopen. kwargs accepteert dezelfde opties als set_cookie() (path, domain, secure, http_only, partitioned); expires en max_age worden genegeerd. Geeft None terug; de header wordt ter plekke aan deze respons toegevoegd.

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

Geef een redirect-respons terug:

@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

Stream een bestand van het bestandssysteem als respons-body. content_type wordt afgeleid uit de extensie via types_map indien niet opgegeven. compressed=True stelt Content-Encoding: gzip in (het bestand moet al gecomprimeerd zijn).

Waarschuwing

filename wordt rechtstreeks geopend. Geef nooit een niet-opgeschoond door de gebruiker aangeleverd pad door – dat maakt willekeurige bestandsblootstelling mogelijk.

Uitzonderingen

exception microdot.HTTPException

Opgegooid door abort() om een request kort te sluiten met een specifieke statuscode. Microdot vangt dit op en zet het om in de bijbehorende foutrespons.

status_code: int

Numerieke HTTP-statuscode om terug te geven – de waarde die aan abort() is doorgegeven.

reason: str

Reden-tekst om op te nemen in de foutrespons. Indien niet opgegeven aan abort(), standaard "<status_code> error" (bijv. "404 error").

class URLPattern

class microdot.URLPattern(url_pattern: str)

De gecompileerde vorm van het URL-patroon van een route. Wordt automatisch geconstrueerd door Microdot.route(); applicaties instantiëren er zelden rechtstreeks een.

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

Registreer een nieuw dynamisch-segmenttype voor gebruik in routepatronen. Geeft None terug; het type wordt toegevoegd aan het typeregister op klasseniveau. Bijvoorbeeld om een <uuid:...>-type toe te voegen:

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

parser is een optionele callable die de vastgelegde string converteert voordat deze de handler bereikt.

match(path: str) dict | None

Match path tegen het patroon en geef een dict van vastgelegde groepen terug, of None bij geen match.

Hulpklassen

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

Een dict-subklasse die meerdere waarden per sleutel opslaat. Gebruikt voor querystrings en URL-gecodeerde formulier-bodies waar dezelfde sleutel meer dan eens kan voorkomen (?tag=a&tag=b).

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

Geef de eerste waarde voor key terug, optioneel geconverteerd met type (een callable). Geeft default terug als de sleutel ontbreekt of de conversie mislukt; geeft anders de (eventueel geconverteerde) waarde terug.

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

Geef alle waarden voor key terug als een lijst, optioneel met elke waarde geconverteerd door type. Geeft een lege lijst terug als key niet aanwezig is.

class microdot.NoCaseDict

Een dict-subklasse met hoofdletterongevoelige string-sleutels. Gebruikt voor Request.headers en Response.headers.

Functies op moduleniveau

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

Snelkoppeling voor Microdot.abort(). Keert nooit normaal terug – gooit HTTPException op. Importeerbaar als from microdot import abort.

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

Snelkoppeling voor Response.redirect(). Importeerbaar als from microdot import redirect.

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

Snelkoppeling voor Response.send_file().

microdot.urlencode(s: str) str

Percent-codeer een URL-component. Vervangt tekens met een gereserveerde betekenis in een URL (/, ?, &, =, #, spatie, …) door hun %xx hex-escapes zodat het resultaat veilig binnen een padsegment of querywaarde kan staan. Geeft de gecodeerde str terug.

microdot.urldecode(s: str) str

Percent-decodeer een URL-component – het omgekeerde van urlencode(). %xx-escapes worden vervangen door de byte die ze coderen, en + wordt omgezet naar een spatie (de historische querystring-conventie). Geeft de gedecodeerde str terug.

Submodules