Pages Functions — Routing & Middleware
In this tutorial, you'll learn about Pages Functions. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
This tutorial explains advanced routing techniques and middleware patterns for Cloudflare Pages Functions, including parameterized routes, catch-all handlers, and request transformation chains. Middleware reduces code duplication by placing shared logic like authentication and logging into reusable handlers. The DodaTech API Gateway uses middleware to validate API keys and log every request before it reaches the route handler.
Route Patterns
Pages Functions support parameterized and catch-all routes using file and directory naming conventions.
flowchart LR
A[Incoming request] --> B[Match route]
B --> C{Pattern matched?}
C -->|Parameter route| D[Extract params]
C -->|Catch-all| E[Capture full path]
C -->|Static| F[Exact match]
D --> G[Execute handler]
E --> G
F --> G
style B fill:#f90,color:#fff
style G fill:#f90,color:#fff
Parameterized Routes
Create a file named [param].js inside a directory to capture dynamic segments. The parameter value is available in the request context.
// functions/user/[id].js
export function onRequest(context) {
const userId = context.params.id;
if (!userId) {
return new Response('User ID required', { status: 400 });
}
return new Response('User profile for ID: ' + userId, {
headers: { 'Content-Type': 'text/plain' }
});
}
// Visiting /user/42
// Expected output: User profile for ID: 42
Catch-All Routes
Use [...path].js to capture all remaining URL segments. This is useful for building proxy endpoints or custom routers.
// functions/proxy/[...path].js
export async function onRequest(context) {
const { path } = context.params;
const targetUrl = 'https://api.example.com/' + path.join('/');
const response = await fetch(targetUrl, {
headers: { 'Authorization': 'Bearer ' + context.env.API_KEY }
});
return new Response(response.body, {
status: response.status,
headers: { 'Content-Type': 'application/json' }
});
}
// Visiting /proxy/users/123 proxies to https://api.example.com/users/123
Middleware Pattern
Use _middleware.js files to apply logic before route handlers. Middleware runs for all routes in the same directory and subdirectories.
// functions/_middleware.js
export async function onRequest(context) {
const startTime = Date.now();
const url = new URL(context.request.url);
context.response = await context.next();
const duration = Date.now() - startTime;
console.log(context.request.method, url.pathname, context.response.status, duration + 'ms');
return context.response;
}
// Every request through this directory logs:
// GET /api/data 200 12ms
Authentication Middleware
A common use case is protecting multiple routes with token-based authentication.
// functions/api/_middleware.js
export async function onRequest(context) {
const authHeader = context.request.headers.get('Authorization');
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return new Response('Unauthorized', { status: 401 });
}
const token = authHeader.slice(7);
if (token !== context.env.SECRET_TOKEN) {
return new Response('Forbidden', { status: 403 });
}
context.data.user = { role: 'admin' };
return context.next();
}
// Requests without valid Bearer token receive 401 or 403
FAQ
Practice Questions
- How do you define a parameterized route in Pages Functions?
- What file naming convention creates a catch-all route handler?
- What method do you call in middleware to pass control to the next handler?
Summary
Pages Functions support parameterized routes, catch-all patterns, and middleware chains. Middleware files run before route handlers and can handle authentication, logging, and request transformation. Route patterns are defined through the file system structure.
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro — security-first tools for the modern web.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro