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/workers/api.md
1# Workers Runtime APIs23## Fetch Handler45```typescript6export default {7async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {8const url = new URL(request.url);9if (request.method === 'POST' && url.pathname === '/api') {10const body = await request.json();11return new Response(JSON.stringify({ id: 1 }), {12headers: { 'Content-Type': 'application/json' }13});14}15return fetch(request); // Subrequest to origin16},17};18```1920## Execution Context2122```typescript23ctx.waitUntil(logAnalytics(request)); // Background work, don't block response24ctx.passThroughOnException(); // Failover to origin on error25```2627**Never** `await` background operations - use `ctx.waitUntil()`.2829## Bindings3031```typescript32// KV33await env.MY_KV.get('key');34await env.MY_KV.put('key', 'value', { expirationTtl: 3600 });3536// R237const obj = await env.MY_BUCKET.get('file.txt');38await env.MY_BUCKET.put('file.txt', 'content');3940// D141const result = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(1).first();4243// D1 Sessions (2024+) - read-after-write consistency44const session = env.DB.withSession();45await session.prepare('INSERT INTO users (name) VALUES (?)').bind('Alice').run();46const user = await session.prepare('SELECT * FROM users WHERE name = ?').bind('Alice').first(); // Guaranteed fresh4748// Queues49await env.MY_QUEUE.send({ timestamp: Date.now() });5051// Secrets/vars52const key = env.API_KEY;53```5455## Cache API5657```typescript58const cache = caches.default;59let response = await cache.match(request);6061if (!response) {62response = await fetch(request);63response = new Response(response.body, response);64response.headers.set('Cache-Control', 'max-age=3600');65ctx.waitUntil(cache.put(request, response.clone())); // Clone before caching66}67```6869## HTMLRewriter7071```typescript72return new HTMLRewriter()73.on('a[href]', {74element(el) {75const href = el.getAttribute('href');76if (href?.startsWith('http://')) {77el.setAttribute('href', href.replace('http://', 'https://'));78}79}80})81.transform(response);82```8384**Use cases**: A/B testing, analytics injection, link rewriting8586## WebSockets8788### Standard WebSocket8990```typescript91const [client, server] = Object.values(new WebSocketPair());9293server.accept();94server.addEventListener('message', event => {95server.send(`Echo: ${event.data}`);96});9798return new Response(null, { status: 101, webSocket: client });99```100101### WebSocket Hibernation (Recommended for idle connections)102103```typescript104// In Durable Object105export class WebSocketDO {106async webSocketMessage(ws: WebSocket, message: string) {107ws.send(`Echo: ${message}`);108}109110async webSocketClose(ws: WebSocket, code: number, reason: string) {111// Cleanup on close112}113114async webSocketError(ws: WebSocket, error: Error) {115console.error('WebSocket error:', error);116}117}118```119120Hibernation automatically suspends inactive connections (no CPU cost), wakes on events121122## Durable Objects123124### RPC Pattern (Recommended 2024+)125126```typescript127export class Counter {128private value = 0;129130constructor(private state: DurableObjectState) {131state.blockConcurrencyWhile(async () => {132this.value = (await state.storage.get('value')) || 0;133});134}135136// Export methods directly - called via RPC (type-safe, zero serialization)137async increment(): Promise<number> {138this.value++;139await this.state.storage.put('value', this.value);140return this.value;141}142143async getValue(): Promise<number> {144return this.value;145}146}147148// Worker usage:149const stub = env.COUNTER.get(env.COUNTER.idFromName('global'));150const count = await stub.increment(); // Direct method call, full type safety151```152153### Legacy Fetch Pattern (Pre-2024)154155```typescript156async fetch(request: Request): Promise<Response> {157const url = new URL(request.url);158if (url.pathname === '/increment') {159await this.state.storage.put('value', ++this.value);160}161return new Response(String(this.value));162}163// Usage: await stub.fetch('http://x/increment')164```165166**When to use DOs**: Real-time collaboration, rate limiting, strongly consistent state167168## Other Handlers169170```typescript171// Cron: async scheduled(event, env, ctx) { ctx.waitUntil(doCleanup(env)); }172// Queue: async queue(batch) { for (const msg of batch.messages) { await process(msg.body); msg.ack(); } }173// Tail: async tail(events, env) { for (const e of events) if (e.outcome === 'exception') await log(e); }174```175176## Service Bindings177178```typescript179// Worker-to-worker RPC (zero latency, no internet round-trip)180return env.SERVICE_B.fetch(request);181182// With RPC (2024+) - same as Durable Objects RPC183export class ServiceWorker {184async getData() { return { data: 'value' }; }185}186// Usage: const data = await env.SERVICE_B.getData();187```188189**Benefits**: Type-safe method calls, no HTTP overhead, share code between Workers190191## See Also192193- [Configuration](./configuration.md) - Binding setup194- [Patterns](./patterns.md) - Common workflows195- [KV](../kv/README.md), [D1](../d1/README.md), [R2](../r2/README.md), [Durable Objects](../durable-objects/README.md), [Queues](../queues/README.md)196