Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive Cloudflare platform skill covering Workers, D1, R2, KV, AI, Durable Objects, and security.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/pages/api.md
1# Functions API23## File-Based Routing45```6/functions/index.ts → example.com/7/functions/api/users.ts → example.com/api/users8/functions/api/users/[id].ts → example.com/api/users/:id9/functions/api/users/[[path]].ts → example.com/api/users/* (catchall)10/functions/_middleware.ts → Runs before all routes11```1213**Rules**: `[param]` = single segment, `[[param]]` = multi-segment catchall, more specific wins.1415## Request Handlers1617```typescript18import type { PagesFunction } from '@cloudflare/workers-types';1920interface Env {21DB: D1Database;22KV: KVNamespace;23}2425// All methods26export const onRequest: PagesFunction<Env> = async (context) => {27return new Response('All methods');28};2930// Method-specific31export const onRequestGet: PagesFunction<Env> = async (context) => {32const { request, env, params, data } = context;3334const user = await env.DB.prepare(35'SELECT * FROM users WHERE id = ?'36).bind(params.id).first();3738return Response.json(user);39};4041export const onRequestPost: PagesFunction<Env> = async (context) => {42const body = await context.request.json();43return Response.json({ success: true });44};4546// Also: onRequestPut, onRequestPatch, onRequestDelete, onRequestHead, onRequestOptions47```4849## Context Object5051```typescript52interface EventContext<Env, Params, Data> {53request: Request; // HTTP request54env: Env; // Bindings (KV, D1, R2, etc.)55params: Params; // Route parameters56data: Data; // Middleware-shared data57waitUntil: (promise: Promise<any>) => void; // Background tasks58next: () => Promise<Response>; // Next handler59passThroughOnException: () => void; // Error fallback (not in advanced mode)60}61```6263## Dynamic Routes6465```typescript66// Single segment: functions/users/[id].ts67export const onRequestGet: PagesFunction = async ({ params }) => {68// /users/123 → params.id = "123"69return Response.json({ userId: params.id });70};7172// Multi-segment: functions/files/[[path]].ts73export const onRequestGet: PagesFunction = async ({ params }) => {74// /files/docs/api/v1.md → params.path = ["docs", "api", "v1.md"]75const filePath = (params.path as string[]).join('/');76return new Response(filePath);77};78```7980## Middleware8182```typescript83// functions/_middleware.ts84// Single85export const onRequest: PagesFunction = async (context) => {86const response = await context.next();87response.headers.set('X-Custom-Header', 'value');88return response;89};9091// Chained (runs in order)92const errorHandler: PagesFunction = async (context) => {93try {94return await context.next();95} catch (err) {96return new Response(err.message, { status: 500 });97}98};99100const auth: PagesFunction = async (context) => {101const token = context.request.headers.get('Authorization');102if (!token) return new Response('Unauthorized', { status: 401 });103context.data.userId = await verifyToken(token);104return context.next();105};106107export const onRequest = [errorHandler, auth];108```109110**Scope**: `functions/_middleware.ts` → all; `functions/api/_middleware.ts` → `/api/*` only111112## Bindings Usage113114```typescript115export const onRequestGet: PagesFunction<Env> = async ({ env }) => {116// KV117const cached = await env.KV.get('key', 'json');118await env.KV.put('key', JSON.stringify({data: 'value'}), {expirationTtl: 3600});119120// D1121const result = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first();122123// R2, Queue, AI - see respective reference docs124125return Response.json({success: true});126};127```128129## Advanced Mode130131Full Workers API, bypasses file-based routing:132133```javascript134// functions/_worker.js135export default {136async fetch(request, env, ctx) {137const url = new URL(request.url);138139// Custom routing140if (url.pathname.startsWith('/api/')) {141return new Response('API response');142}143144// REQUIRED: Serve static assets145return env.ASSETS.fetch(request);146}147};148```149150**When to use**: WebSockets, complex routing, scheduled handlers, email handlers.151152## Smart Placement153154Automatically optimizes function execution location based on traffic patterns.155156**Configuration** (in wrangler.jsonc):157```jsonc158{159"placement": {160"mode": "smart" // Enables optimization (default: off)161}162}163```164165**How it works**: Analyzes traffic patterns over time and places functions closer to users or data sources (e.g., D1 databases). Requires no code changes.166167**Trade-offs**: Initial requests may see slightly higher latency during learning period (hours-days). Performance improves as system optimizes.168169**When to use**: Global apps with centralized databases or geographically concentrated traffic sources.170171## getRequestContext (Framework SSR)172173Access bindings in framework code:174175```typescript176// SvelteKit177import type { RequestEvent } from '@sveltejs/kit';178export async function load({ platform }: RequestEvent) {179const data = await platform.env.DB.prepare('SELECT * FROM users').all();180return { users: data.results };181}182183// Astro184const { DB } = Astro.locals.runtime.env;185const data = await DB.prepare('SELECT * FROM users').all();186187// Solid Start (server function)188import { getRequestEvent } from 'solid-js/web';189const event = getRequestEvent();190const data = await event.locals.runtime.env.DB.prepare('SELECT * FROM users').all();191```192193**✅ Supported adapters** (2026):194- **SvelteKit**: `@sveltejs/adapter-cloudflare`195- **Astro**: Built-in Cloudflare adapter196- **Nuxt**: Set `nitro.preset: 'cloudflare-pages'` in `nuxt.config.ts`197- **Qwik**: Built-in Cloudflare adapter198- **Solid Start**: `@solidjs/start-cloudflare-pages`199200**❌ Deprecated/Unsupported**:201- **Next.js**: Official adapter (`@cloudflare/next-on-pages`) deprecated. Use Vercel or self-host on Workers.202- **Remix**: Official adapter (`@remix-run/cloudflare-pages`) deprecated. Migrate to supported frameworks.203204See [gotchas.md](./gotchas.md#framework-specific) for migration guidance.205