Architecture and design¶
MicroPie is intentionally small. Its goal is to provide just enough functionality to build asynchronous web applications without locking you into a rigid structure. This section discusses some of the key design choices and how they influence the API.
ASGI application¶
MicroPie is built on top of the ASGI specification, which defines
how Python applications communicate with asynchronous servers. Your
application subclass inherits from App and
implements the ASGI call interface via the __call__ method. The
framework inspects the scope['type'] field to dispatch to HTTP,
WebSocket or lifespan handling code.
Routing by naming¶
Unlike frameworks that require you to declare routes in advance,
MicroPie derives routing information from the names of your methods.
The first segment of the path becomes the handler name. This allows
you to add new endpoints simply by defining a new method on your
application subclass. The remaining path segments, query string
parameters and form data are mapped to arguments via function
signature inspection. This approach reduces boilerplate but may
surprise users expecting explicit routing. You can always regain
control by writing a custom middleware to map paths to handlers or by
checking self.request.method and self.request.path_params inside
your handlers.
Context‑local request¶
MicroPie stores the current request in a contextvars
ContextVar. This allows you to access self.request within your
handler as well as from deeper helper functions without passing the
request around explicitly. The context variable is reset at the end
of each request to avoid leaking state.
Session management¶
Sessions are stored in a pluggable back‑end and identified by a
random session_id cookie. The default in‑memory back‑end keeps
session data in dictionaries keyed by session ID and updates a last
access timestamp to implement expiration. You can customise the
back‑end by providing your own implementation of
SessionBackend. MicroPie saves sessions after a
handler returns, only if self.request.session is non‑empty, to
avoid creating unnecessary cookies.
Middleware pipeline¶
The middleware hooks allow you to intercept requests before and after handlers. Middleware can modify the request object, provide early responses (useful for authentication), and alter the final response. For WebSockets, separate middleware hooks run before the connection handler starts and after it finishes.
Streaming and SSE support¶
Handlers may return an iterator or asynchronous generator to stream
data to the client. MicroPie detects such responses and iterates
over them, sending each chunk to the client. When using server‑sent
events (SSE) there is an additional challenge: if the client
disconnects, the iterator must be cancelled. MicroPie wraps SSE
responses in a small loop that listens for disconnect events and
cancels the generator accordingly. Remember to include a
Content‑Type: text/event-stream header when sending SSE.
Lifespan hooks¶
ASGI defines a lifespan protocol for startup and shutdown events. MicroPie
exposes startup_handlers and shutdown_handlers lists on the
App instance. Handlers are executed sequentially and
should be asynchronous callables. Use them to open database connections,
prime caches or register background tasks. Lifespan functions run before
any request or WebSocket traffic is accepted, ensuring your dependencies
are ready.
Templating and JSON helpers¶
If jinja2 is installed, MicroPie enables the
_render_template() helper to render templates from a
templates directory, returning HTML responses with the correct
Content-Type. For JSON, the framework prefers orjson when
available and gracefully falls back to json. This keeps the core
lean while letting you opt into performance boosts.
Error handling¶
MicroPie automatically handles common error cases. Requests for
unknown routes result in a 404 Not Found. If a required
parameter is missing, MicroPie responds with 400 Bad Request.
Unhandled exceptions inside handlers produce a 500 Internal Server
Error and are printed to standard error. You can override these
behaviours via middleware.
Extensibility¶
The minimalist core is designed to be extended. You can mount your application behind other ASGI middleware, integrate additional protocols like Socket.IO, or implement your own session storage. The framework imposes few constraints so that you remain in control of your stack.
WebSocket pipeline¶
WebSocket connections follow a parallel flow to HTTP requests. The
ws_ method naming convention resolves handlers, middleware gates the
connection before accept() is called, and the
WebSocket helper manages receive/send coroutines. Session
data is shared with HTTP handlers so users can authenticate once and reuse
the same session across protocols.