API Middleware
Relevant source files
The following files were used as context for generating this wiki page:The API server, built with the Hono web framework, leverages a middleware-centric architecture to handle requests. Middleware functions are used to process incoming requests sequentially, managing cross-cutting concerns such as authentication, database context injection, API documentation, and routing for different RPC protocols. This approach allows for a clean separation of concerns and modular design.
The primary configuration and registration of these middlewares occur in the main application entry point, apps/api/src/index.ts. The server distinguishes between different types of requests (e.g., authentication, OpenAPI RPC, standard RPC) and applies specific middleware chains accordingly.
Middleware Registration and Execution Flow
All middlewares are registered on the main Hono application instance. The order of registration is critical as it defines the execution order for incoming requests. The server uses path-based routing to apply specific middleware to matching requests.
Sources: apps/api/src/index.ts:7-13
The following diagram illustrates the high-level request flow through the registered middlewares.
This diagram shows how requests are routed to different middleware handlers based on their path.
Sources: apps/api/src/index.ts:9-13
Registered Middleware Overview
| Path | Method(s) | Handler | Purpose | Source File |
|---|---|---|---|---|
/api/auth/* | POST, GET | handleBetterAuth | Handles all authentication-related endpoints. | apps/api/src/index.ts:9 |
* (all routes) | ANY | handleAuthContext | Populates authentication context (user, session) for all requests. | apps/api/src/index.ts:10 |
/api/spec.json | GET | handleOpenAPISpec | Generates and serves the OpenAPI specification. | apps/api/src/index.ts:11 |
/api/docs | GET | handleScalarDocs | Serves the interactive Scalar API documentation UI. | apps/api/src/index.ts:12 |
/api/* | ANY | handleOpenAPIRequests | Handles ORPC requests that follow the OpenAPI specification. | apps/api/src/index.ts:13 |
/rpc/* | ANY | handleRPCRequests | Handles standard ORPC requests. | apps/api/src/index.ts:14 |
Core Middleware Components
Authentication Middleware
Authentication is managed by the better-auth library. It is integrated via two main handlers: handleBetterAuth for the authentication endpoints and handleAuthContext as a global middleware.
handleAuthContext: This middleware is applied to all incoming requests (app.use("*", handleAuthContext)). Its role is to process authentication details (e.g., from a token) and inject user and session information into the request context. This context is then available to all subsequent middlewares and handlers.
Sources: apps/api/src/index.ts:10, apps/api/src/handlers/orpc.ts:31, apps/api/src/handlers/orpc.ts:46betterAuthConfiguration: The authentication system is configured inapps/api/src/lib/auth.ts. It uses thedrizzleAdapterto connect to a PostgreSQL database, mapping theuser,session,account, andverificationtables from the shared database schema.
Sources: apps/api/src/lib/auth.ts:5-19
The sequence diagram below shows how handleAuthContext provides user data to a downstream RPC handler.
ORPC and OpenAPI Middleware
The API uses orpc for type-safe remote procedure calls. Two distinct middleware handlers are used to process RPC requests based on the URL prefix.
handleOpenAPIRequests(/api/*): This handler processes ORPC requests that are exposed via an OpenAPI-compatible interface. It uses anOpenAPIHandlerinstance.handleRPCRequests(/rpc/*): This handler processes standard ORPC requests using anRPCHandlerinstance.
Both handlers follow a common pattern: they attempt to match and handle the incoming request. If the request path matches their prefix (e.g., /api or /rpc), they process it and return a response. If it doesn't match, they call next() to pass control to the next middleware in the chain.
Sources: apps/api/src/handlers/orpc.ts:27-37, apps/api/src/handlers/orpc.ts:42-52
// apps/api/src/handlers/orpc.ts:42-52
export async function handleRPCRequests(c: Context, next: Next) {
const { matched, response } = await rpcHandler.handle(c.req.raw, {
prefix: "/rpc",
context: {
user: c.get("user"),
session: c.get("session"),
},
});
if (matched) {
return c.newResponse(response.body, response);
}
await next();
}
Database Provider Middleware
The dbProviderMiddleware is an ORPC-specific middleware responsible for injecting a database connection or a mock database implementation into the ORPC context.
Sources: apps/api/src/middlewares/db.ts:18-32
Key features:
- Context Injection: It ensures that a
dbobject of typeDBis available in the context for all downstream ORPC procedures. - Deduplication: It checks if
context.dbalready exists before creating a new instance. This is a best practice to prevent re-initializing the database connection on every procedure call within a single request. - Mock Implementation: Currently, it uses a
createFakeDB()function to provide an in-memory mock database for development and testing purposes.
// apps/api/src/middlewares/db.ts:18-32
export const dbProviderMiddleware = os
.$context<{ db?: DB }>()
.middleware(async ({ context, next }) => {
/**
* Why we should ?? here?
* Because it can avoid `createFakeDB` being called when unnecessary.
* {@link https://orpc.unnoq.com/docs/best-practices/dedupe-middleware}
*/
const db: DB = context.db ?? createFakeDB();
return next({
context: {
db,
},
});
});
DB Interface
The DB interface defines the contract for the data access layer. The mock implementation provides methods for basic CRUD operations on a planets collection.
This diagram shows the structure of the DB interface and its nested planets methods.
Sources: apps/api/src/middlewares/db.ts:9-16
API Documentation Middleware
The API serves its own documentation using two dedicated middleware handlers registered on GET routes.
handleOpenAPISpec: This handler, registered at/api/spec.json, dynamically generates an OpenAPI 3.0 specification from theorpccontract. It includes information about API endpoints, schemas, and security definitions (Bearer Auth).
Sources: apps/api/src/handlers/openapi.ts:9-29, apps/api/src/index.ts:11handleScalarDocs: This handler, registered at/api/docs, provides a rich, interactive API browser using Scalar. It is configured to point to the/api/spec.jsonendpoint to fetch the API definition.
Sources: apps/api/src/handlers/openapi.ts:31-40, apps/api/src/index.ts:12