justapi — /docs

Middleware lets you run code before and after every request. JustAPI has two middleware layers:

  • Native Rust middleware (CORS, JWT, security headers) — configured with dedicated methods, runs on every request including the native fast path.
  • Python middleware — your own async def mw(request, call_next) callables, registered with @app.middleware("http") or per-route middlewares=.

Basic HTTP Middleware

Use the @app.middleware("http") decorator. Middleware is async and must await call_next(request):

import time
from justapi import JustAPIApp

app = JustAPIApp()


@app.middleware("http")
async def timing_middleware(request, call_next):
    start = time.time()
    response = await call_next(request)
    elapsed = time.time() - start
    response.headers.append(
        (b"X-Process-Time", str(round(elapsed, 4)).encode())
    )
    return response

call_next dispatches the request down the chain; the return value is the handler's response object.

Performance: Python middleware runs on the Python side of the boundary and is bypassed (must be) by the native fast path. Prefer native middleware (add_cors, enable_secure_headers, set_jwt_auth) when possible. Keep Python middleware to logic that must run in Python.

CORS Middleware

JustAPI has a built-in, Rust-native CORS configuration method:

app.add_cors(
    allow_origins=["https://example.com", "https://api.example.com"],
    allow_methods=["GET", "POST", "PUT", "DELETE"],
    allow_headers=["*"],
    allow_credentials=True,
)
Parameter Type Default Description
allow_origins list[str] ["*"] Allowed origins
allow_methods list[str] All methods Allowed HTTP methods
allow_headers list[str] ["*"] Allowed headers
allow_credentials bool False Allow cookies/auth headers

Secure Headers Middleware

Add safe HTTP security headers (Rust-native):

app.enable_secure_headers(with_hsts=True)

This adds: - X-Content-Type-Options: nosniff - X-Frame-Options: DENY - Strict-Transport-Security (when with_hsts=True) - Content-Security-Policy - X-XSS-Protection: 0

Multiple Middleware

Middlewares are executed in registration order (first added is outermost):

@app.middleware("http")
async def middleware_one(request, call_next):
    print("Before 1")
    response = await call_next(request)
    print("After 1")
    return response


@app.middleware("http")
async def middleware_two(request, call_next):
    print("Before 2")
    response = await call_next(request)
    print("After 2")
    return response

Output for a single request:

Before 1
Before 2
[handler executes]
After 2
After 1

Route-Level Middleware

Attach middleware to individual routes:

async def auth_middleware(request, call_next):
    if not (request.get("headers") or {}).get("x-token"):
        return {"status": 401, "body": {"detail": "unauthorized"}}
    return await call_next(request)

@app.get("/protected", middlewares=[auth_middleware])
async def protected(request):
    return {"message": "top secret"}

Real-World Patterns

Request Logging Middleware

import logging

logger = logging.getLogger("justapi")


@app.middleware("http")
async def log_requests(request, call_next):
    method = request.get("method")
    path = request.get("path")
    logger.info("→ %s %s", method, path)
    response = await call_next(request)
    status = getattr(response, "status_code", None) or 200
    logger.info("← %s %s%s", method, path, status)
    return response

Authorization via Dependency

from justapi import Depends, HTTPException, Header


def require_admin(authorization: str = Header(...)):
    if authorization != "Bearer admin-token":
        raise HTTPException(403, "Admin access required")


@app.get("/admin/users", dependencies=[Depends(require_admin)])
def list_all_users(request):
    return {"users": []}

Native Fast-Path Note

The Rust native fast path (native=True) is a validate-and-echo shortcut that does not execute Python middleware or dependencies. Routes using native=True must not declare Python middleware/dependencies — the framework rejects that combination at registration time. Native middleware (add_cors, enable_secure_headers, set_jwt_auth) runs for all routes.

How It Works Internally

  1. Native middleware (CORS, security headers, JWT, rate limit) runs in the Rust middleware chain with zero GIL overhead.
  2. Python middleware runs as an async wrapper around your handler on the Python side.
  3. call_next dispatches down the middleware chain to the handler.
  4. The handler's result flows back through each middleware's post-processing.

Next Steps

JustAPI v2.0.9 — Open Source MIT License · Built with WebTUI · GitHub

NORMAL master justapi/docs
utf-8 Top 1:1