RatMinimal web framework

Middleware

A middleware is a service with two extras: a route pattern (match: '/...') and lifecycle hooks (before, after, on_start[], on_shutdown[]). When a request matches, the hooks run around the page handler. This is useful for logging, auth gates, hit counters, or anything that should fire on every request without per-page wiring. The counter below is live.

Live: a page-view counter

main.rat: fires after every request

The page_views service matches every URL ('/**') and bumps total in its after hook. The number below reads the live state; every page you visit on this site, including this refresh, adds one.

# main.rat
> service [page_views]
match: '/**'
total: 0

after[req]
    total << total + 1

# any page
> page
<p> This site has been viewed [page_views.total] times.
Result

Total page views so far: 3478

Refresh this page or visit any other doc to bump the counter.

Short-circuit with before

Auth gate on /admin

A before hook runs before the page handler. Assign to redirect or abort to bail out: the page handler never runs and the user sees the alternative response. Pair with match to scope the gate to a subtree.

> service [admin_gate]
match: '/admin/**'

before[req]
    (is not session.user_id)
        redirect << '/login'

# or for an API endpoint:
> service [api_auth]
match: '/api/**'

before[req]
    (is not session.user_id)
        abort << {status: 401, body: 'unauthorized'}

Lifecycle: on_start / on_shutdown

Boot-time and drain-time work

on_start[] runs once when the server boots; on_shutdown[] runs once at SIGINT/SIGTERM (the framework calls http.Server.Shutdown after the hook returns). Use them for warming caches, opening pools, registering metrics, or draining connections. They take no parameters and run only for their side effects.

> service [warmup]
ready: false

on_start[]
    log('booting')
    ready << true

on_shutdown[]
    log('draining connections')

Per-request hooks

on_request_start / on_request_end fire on every URL

When you don't need URL matching but want a hook on every request (request tracing, structured access logs, request-scoped resources), declare on_request_start[] and on_request_end[]. They fire on every URL regardless of match:.

> service [tracer]

on_request_start[]
    log('begin')

on_request_end[]
    log('end')

Match patterns

Glob over the route

match is a glob over the request path. '/**' matches every route; '/api/**' matches every API call; '/admin' matches only the literal path; '/users/*/posts' uses single-segment wildcards. Multiple middlewares can match the same request; they fire in alphabetic-name order for before, and reverse for after.

> service [api_log]
match: '/api/**'
hits: 0

after[req]
    hits << hits + 1
    log(req.method, req.url)

> service [request_log]
match: '/**'

after[req]
    log('served:', req.url)

See also Services · Public endpoints · Channels