Skip to content

Pages Functions — Routing & Middleware

DodaTech Updated 2026-06-23 3 min read

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

What is the execution order of middleware?

Middleware runs from the outermost directory to the innermost. Parent _middleware.js executes before child middleware. The route handler runs last.

Can I skip middleware for specific routes?

Yes. You can inspect the request URL inside middleware and call context.next() without additional logic to skip processing for certain paths.

Do middleware blocks affect performance?

Each middleware adds minimal overhead measured in microseconds. Cloudflare Functions use the V8 runtime which handles small middleware chains efficiently.

Practice Questions

  1. How do you define a parameterized route in Pages Functions?
  2. What file naming convention creates a catch-all route handler?
  3. 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