一键导入
infrastructure-cloudflare-workers
Building serverless APIs at the edge (low latency globally)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Building serverless APIs at the edge (low latency globally)
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | infrastructure-cloudflare-workers |
| description | Building serverless APIs at the edge (low latency globally) |
Scope: Edge computing with Cloudflare Workers - Edge functions, KV storage, Durable Objects, R2 Lines: 365 Last Updated: 2025-10-18 Format Version: 1.0 (Atomic)
Activate when:
Prerequisites:
npm install -g wrangler)Common scenarios:
// src/index.js - Simple worker
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Simple routing
if (url.pathname === '/api/hello') {
return new Response(JSON.stringify({
message: 'Hello from the edge!',
location: request.cf.city,
country: request.cf.country
}), {
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
}
});
}
// 404 response
return new Response('Not Found', { status: 404 });
}
};
# wrangler.toml
name = "my-worker"
main = "src/index.js"
compatibility_date = "2024-01-01"
# Environment variables
[vars]
ENVIRONMENT = "production"
API_VERSION = "v1"
# KV Namespace bindings
[[kv_namespaces]]
binding = "CACHE"
id = "abcdef1234567890abcdef1234567890"
# Durable Object bindings
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
# R2 bucket bindings
[[r2_buckets]]
binding = "ASSETS"
bucket_name = "my-assets"
# Secrets (set with: wrangler secret put SECRET_NAME)
# Access via env.SECRET_NAME
# Routes (custom domain)
[[routes]]
pattern = "api.example.com/*"
zone_name = "example.com"
# Workers for Platforms (optional)
[dispatch_namespaces]
binding = "DISPATCHER"
namespace = "my-namespace"
// src/index.ts - TypeScript worker
interface Env {
CACHE: KVNamespace;
API_KEY: string;
ENVIRONMENT: string;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
// CORS handling
if (request.method === 'OPTIONS') {
return handleCORS();
}
// Authentication
const apiKey = request.headers.get('X-API-Key');
if (apiKey !== env.API_KEY) {
return new Response('Unauthorized', { status: 401 });
}
// Route handling
switch (url.pathname) {
case '/api/data':
return handleData(request, env, ctx);
case '/api/upload':
return handleUpload(request, env);
default:
return new Response('Not Found', { status: 404 });
}
}
};
function handleCORS(): Response {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, X-API-Key',
'Access-Control-Max-Age': '86400',
}
});
}
async function handleData(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const cacheKey = new URL(request.url).pathname;
// Check cache first
const cached = await env.CACHE.get(cacheKey, 'json');
if (cached) {
return Response.json(cached, {
headers: { 'X-Cache': 'HIT' }
});
}
// Fetch data
const data = await fetchData();
// Cache in background
ctx.waitUntil(
env.CACHE.put(cacheKey, JSON.stringify(data), {
expirationTtl: 3600 // 1 hour
})
);
return Response.json(data, {
headers: { 'X-Cache': 'MISS' }
});
}
async function fetchData() {
// Fetch from origin API
const response = await fetch('https://api.example.com/data');
return response.json();
}
// KV operations
interface Env {
CACHE: KVNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const key = url.searchParams.get('key');
if (request.method === 'GET') {
// Get value
const value = await env.CACHE.get(key);
if (!value) {
return new Response('Not Found', { status: 404 });
}
return new Response(value);
}
if (request.method === 'POST') {
// Put value with expiration
const value = await request.text();
await env.CACHE.put(key, value, {
expirationTtl: 3600, // Seconds
metadata: { timestamp: Date.now() }
});
return new Response('Stored', { status: 201 });
}
if (request.method === 'DELETE') {
// Delete value
await env.CACHE.delete(key);
return new Response('Deleted', { status: 204 });
}
// List keys with prefix
if (url.pathname === '/list') {
const prefix = url.searchParams.get('prefix') || '';
const list = await env.CACHE.list({ prefix, limit: 100 });
return Response.json(list.keys);
}
return new Response('Method Not Allowed', { status: 405 });
}
};
// src/counter.ts - Durable Object
export class Counter {
state: DurableObjectState;
value: number;
constructor(state: DurableObjectState, env: Env) {
this.state = state;
this.value = 0;
}
async initialize() {
// Load state from storage
const stored = await this.state.storage.get('value');
this.value = stored || 0;
}
async fetch(request: Request): Promise<Response> {
await this.initialize();
const url = new URL(request.url);
if (url.pathname === '/increment') {
this.value++;
await this.state.storage.put('value', this.value);
return Response.json({ value: this.value });
}
if (url.pathname === '/decrement') {
this.value--;
await this.state.storage.put('value', this.value);
return Response.json({ value: this.value });
}
if (url.pathname === '/get') {
return Response.json({ value: this.value });
}
return new Response('Not Found', { status: 404 });
}
}
// src/index.ts - Use Durable Object
export { Counter } from './counter';
interface Env {
COUNTER: DurableObjectNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Get Durable Object instance by ID
const id = env.COUNTER.idFromName('global-counter');
const stub = env.COUNTER.get(id);
// Forward request to Durable Object
return stub.fetch(request);
}
};
// R2 bucket operations
interface Env {
ASSETS: R2Bucket;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const key = url.pathname.slice(1); // Remove leading /
if (request.method === 'GET') {
// Get object
const object = await env.ASSETS.get(key);
if (!object) {
return new Response('Not Found', { status: 404 });
}
const headers = new Headers();
object.writeHttpMetadata(headers);
headers.set('etag', object.httpEtag);
return new Response(object.body, { headers });
}
if (request.method === 'PUT') {
// Upload object
await env.ASSETS.put(key, request.body, {
httpMetadata: {
contentType: request.headers.get('content-type') || 'application/octet-stream',
},
customMetadata: {
uploadedBy: 'worker',
timestamp: new Date().toISOString(),
}
});
return new Response('Uploaded', { status: 201 });
}
if (request.method === 'DELETE') {
// Delete object
await env.ASSETS.delete(key);
return new Response('Deleted', { status: 204 });
}
return new Response('Method Not Allowed', { status: 405 });
}
};
// Cache API with edge caching
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const cache = caches.default;
// Try to get from cache
let response = await cache.match(request);
if (response) {
return response;
}
// Fetch from origin
response = await fetch(request);
// Cache successful responses
if (response.ok) {
const responseToCache = response.clone();
ctx.waitUntil(cache.put(request, responseToCache));
}
return response;
}
};
// Rewrite requests to different origins
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// API proxy
if (url.pathname.startsWith('/api/')) {
url.hostname = 'api.backend.com';
url.pathname = url.pathname.replace('/api/', '/v1/');
const modifiedRequest = new Request(url.toString(), {
method: request.method,
headers: request.headers,
body: request.body,
});
return fetch(modifiedRequest);
}
// Default to static assets
url.hostname = 'static.example.com';
return fetch(url.toString());
}
};
// A/B testing with cookie-based variants
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// Check for existing variant cookie
let variant = getCookie(request, 'ab_variant');
if (!variant) {
// Assign random variant
variant = Math.random() < 0.5 ? 'A' : 'B';
}
// Fetch variant-specific content
const response = await fetch(`https://origin.com/${variant}${url.pathname}`);
// Set variant cookie
const newResponse = new Response(response.body, response);
newResponse.headers.set('Set-Cookie', `ab_variant=${variant}; Path=/; Max-Age=86400`);
return newResponse;
}
};
function getCookie(request: Request, name: string): string | null {
const cookies = request.headers.get('Cookie');
if (!cookies) return null;
const cookie = cookies.split(';').find(c => c.trim().startsWith(`${name}=`));
return cookie ? cookie.split('=')[1] : null;
}
// Rate limiting with Durable Objects
export class RateLimiter {
state: DurableObjectState;
requests: Map<string, number[]>;
constructor(state: DurableObjectState) {
this.state = state;
this.requests = new Map();
}
async fetch(request: Request): Promise<Response> {
const clientId = request.headers.get('CF-Connecting-IP') || 'unknown';
const now = Date.now();
const windowMs = 60000; // 1 minute
const maxRequests = 100;
// Get request timestamps for this client
let timestamps = this.requests.get(clientId) || [];
// Remove old timestamps outside window
timestamps = timestamps.filter(ts => now - ts < windowMs);
// Check if limit exceeded
if (timestamps.length >= maxRequests) {
return new Response('Rate limit exceeded', {
status: 429,
headers: {
'Retry-After': '60'
}
});
}
// Add current request
timestamps.push(now);
this.requests.set(clientId, timestamps);
return Response.json({
allowed: true,
remaining: maxRequests - timestamps.length
});
}
}
// Image transformation
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// Parse resize parameters
const width = parseInt(url.searchParams.get('width') || '800');
const quality = parseInt(url.searchParams.get('quality') || '85');
const format = url.searchParams.get('format') || 'auto';
// Fetch original image
const imageUrl = url.searchParams.get('url');
if (!imageUrl) {
return new Response('Missing url parameter', { status: 400 });
}
const response = await fetch(imageUrl);
// Transform with Cloudflare Image Resizing
return new Response(response.body, {
headers: {
'Content-Type': 'image/jpeg',
'Cache-Control': 'public, max-age=31536000',
'CF-Image-Width': width.toString(),
'CF-Image-Quality': quality.toString(),
'CF-Image-Format': format,
}
});
}
};
# Development
wrangler dev # Local development server
wrangler dev --remote # Remote development (actual edge)
# Deployment
wrangler deploy # Deploy to production
wrangler deploy --env staging # Deploy to staging
# KV operations
wrangler kv:namespace create "CACHE"
wrangler kv:key put --binding=CACHE "key" "value"
wrangler kv:key get --binding=CACHE "key"
wrangler kv:key delete --binding=CACHE "key"
wrangler kv:key list --binding=CACHE
# R2 operations
wrangler r2 bucket create my-bucket
wrangler r2 object put my-bucket/file.txt --file=./file.txt
wrangler r2 object get my-bucket/file.txt
# Secrets
wrangler secret put API_KEY
wrangler secret delete API_KEY
wrangler secret list
# Logs
wrangler tail # Stream logs
wrangler tail --format=pretty
# Account info
wrangler whoami
wrangler deployments list
CPU Time: 10ms (free), 30s (paid) per request
Memory: 128 MB
Subrequest limit: 50 (free), 1000 (paid)
Script size: 1 MB (free), 10 MB (paid)
KV read: 100,000/day (free), unlimited (paid)
KV write: 1,000/day (free), unlimited (paid)
Durable Objects: Paid feature only
R2 storage: 10 GB (free), unlimited (paid)
// ❌ NEVER: Store secrets in code
const API_KEY = "sk-1234567890abcdef"; // NEVER
// ✅ CORRECT: Use environment bindings
interface Env {
API_KEY: string; // Set with: wrangler secret put API_KEY
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (request.headers.get('X-API-Key') !== env.API_KEY) {
return new Response('Unauthorized', { status: 401 });
}
// ...
}
};
// ❌ NEVER: Perform blocking operations
export default {
async fetch(request: Request): Promise<Response> {
// CPU-intensive synchronous work
let result = 0;
for (let i = 0; i < 1000000000; i++) { // Will hit CPU limit
result += i;
}
return Response.json({ result });
}
};
// ✅ CORRECT: Use Durable Objects for stateful work
// Or offload to origin API for heavy computation
// ❌ NEVER: Use global state
let counter = 0; // Not shared across requests!
export default {
async fetch(request: Request): Promise<Response> {
counter++; // Each request gets own isolate
return Response.json({ counter }); // Always 1
}
};
// ✅ CORRECT: Use KV or Durable Objects
interface Env {
CACHE: KVNamespace;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const counter = parseInt(await env.CACHE.get('counter') || '0');
await env.CACHE.put('counter', (counter + 1).toString());
return Response.json({ counter: counter + 1 });
}
};
// ❌ Don't forget CORS headers
export default {
async fetch(request: Request): Promise<Response> {
return Response.json({ data: 'value' });
// Browser will block cross-origin requests
}
};
// ✅ CORRECT: Add CORS headers
export default {
async fetch(request: Request): Promise<Response> {
const headers = {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
};
return Response.json({ data: 'value' }, { headers });
}
};
Infrastructure:
aws-serverless.md - Alternative serverless platform (Lambda, API Gateway)infrastructure-security.md - Authentication, authorization patternscost-optimization.md - Workers pricing, caching strategiesDevelopment:
modal-functions-basics.md - Python-focused serverless alternativeterraform-patterns.md - Infrastructure as Code for Cloudflare resourcesStandards from CLAUDE.md:
wrangler secret putLast Updated: 2025-10-18 Format Version: 1.0 (Atomic)
Index of Build Systems Skills
Coordination patterns for distributed dataflow systems including barriers, epochs, and distributed snapshots
Windowing, sessionization, time-series aggregation, and late data handling for streaming systems
Comprehensive guide to GNU Debugger (GDB) for debugging C/C++/Rust programs. Covers breakpoints, stack traces, variable inspection, TUI mode, .gdbinit customization, Python scripting, remote debugging, and core file analysis.
Paxos consensus algorithm including Basic Paxos, Multi-Paxos, roles, phases, and practical implementations
Gossip protocols for disseminating information, failure detection, and eventual consistency in large-scale distributed systems