moonapi
Showcase

Watch a request become a response

Every moonapi application routes a request the same way: through the layer stack, into the router, through any security enforcers, to your handler, and back out through the response filters. Step through the pipeline, then try your own request against a small application.

Where each step lives

A request crosses several libraries on the way in, and the same ones on the way out. The iris boxes are this package's; the neutral ones are the libraries beside it and the server that feeds it. The drawing is Mermaid's, from the source kept under it — and the same path is written out in characters for a reader who cannot see the image.

A request arrives from the wire and passes, in order: the ASGI scope, the layer stack, App::middleware, the router, the route's hoops, its security requirement, dependencies and validation, and the handler; it leaves through the same layers in reverse. The outer steps belong to the server and the libraries beside this package, the middle ones to this package.
  bytes in: socket, TLS 1.3, HTTP/1.1 or HTTP/2        mooncat
      |
      v
  ASGI scope, receive, send                            moonasgi
      |
      v
  layers, outermost first:                             moonasgi
  gzip, CORS, trusted hosts, https redirect            moonzip
      |
      v
  App::middleware - the request, whole                 moonapi
      |
      v
  router: mount, docs, WebSocket, path match           moonapi
      |
      v
  hoops: middleware on a route node                    moonapi
      |
      v
  security requirement - the token is verified here    moonapi
                                                       mooncred
      |
      v
  dependencies, then validation -> 422                 moonapi
      |
      v
  handler: Context in, Response out                    moonapi
      |
      v
  bytes out: the same layers, in reverse               mooncat
this package a library beside it — the server, the ASGI seam, the wire formats, the token, the compressor

The pipeline, step by step

Press Run request to send a sample request through the stages. Each stage lights up as the request reaches it; the explanation on the right updates to match.

request lifecycle
1 · in
Layers
›
2 · match
Router
›
3 · guard
Security
›
4 · run
Handler
›
5 · out
Response
idle — press “Run request” to begin.
what happens here

The request lifecycle

A moonapi application is a single object that compiles to a server. The layers wrap the router; the router matches the path and method; security enforcers verify the caller; the handler builds the response; and the response passes back through the layers before it is sent.

sample request
GET /users/42

Try your own request

This tiny application has a handful of routes. Type a path and choose a method; the simulator applies the real 404/405 rules and shows what the application would answer.

GET / GET /users/42 POST /users GET /search?q=cat GET /items/233 GET /items (405) GET /missing (404)
matched route
—
response
App::handle
send a request to see the response
Why 405 and not 404? When the path matches a route under a different method, the application answers 405 Method Not Allowed and lists the allowed methods in the Allow header. Only when no route owns the path at all does it answer 404 Not Found.

What the stages do

Layers

Middleware wraps the router on the way in and the response on the way out — CORS, gzip, logging and custom filters all live here.

Router

Matches the path and method, binds {id} parameters, and decides 405 versus 404 when nothing fits.

Security

Before the handler runs, the schemes declared on the route are enforced; an unauthenticated caller never reaches your code.

Handler

Your function receives a typed context and returns a response — text, html, json, a redirect, or a stream.

Status & exception handlers

A raised exception or a particular status code can be caught and reshaped by handlers you register on the application.

Mounts

Mount a sub-application, such as static files or a whole router, under its own prefix without touching the main routes.