workers-runtime-apis

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Cloudflare Workers Runtime APIs

Cloudflare Workers Runtime API

Master the Workers runtime APIs: Fetch, Streams, Crypto, Cache, WebSockets, and text encoding.
熟练掌握Workers运行时API:Fetch、Streams、Crypto、Cache、WebSockets和文本编码。

Quick Reference

快速参考

APIPurposeCommon Use
FetchHTTP requestsExternal APIs, proxying
StreamsData streamingLarge files, real-time
CryptoCryptographyHashing, signing, encryption
CacheResponse cachingPerformance optimization
WebSocketsReal-time connectionsChat, live updates
EncodingText encodingUTF-8, Base64
API用途常见场景
FetchHTTP请求调用外部API、代理
Streams数据流传输大文件处理、实时传输
Crypto加密运算哈希计算、签名、加密
Cache响应缓存性能优化
WebSockets实时连接聊天、实时更新
Encoding文本编码UTF-8、Base64处理

Quick Start: Fetch API

快速上手:Fetch API

typescript
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // Basic fetch
    const response = await fetch('https://api.example.com/data');

    // With options
    const postResponse = await fetch('https://api.example.com/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${env.API_KEY}`,
      },
      body: JSON.stringify({ name: 'John' }),
    });

    // Clone for multiple reads
    const clone = response.clone();
    const json = await response.json();
    const text = await clone.text();

    return Response.json(json);
  }
};
typescript
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    // 基础fetch调用
    const response = await fetch('https://api.example.com/data');

    // 带参数的请求
    const postResponse = await fetch('https://api.example.com/users', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${env.API_KEY}`,
      },
      body: JSON.stringify({ name: 'John' }),
    });

    // 克隆响应以支持多次读取
    const clone = response.clone();
    const json = await response.json();
    const text = await clone.text();

    return Response.json(json);
  }
};

Critical Rules

核心规则

  1. Always set timeouts for external requests - Workers have a 30s limit, external APIs can hang
  2. Clone responses before reading body - Body can only be read once
  3. Use streaming for large payloads - Don't buffer entire response in memory
  4. Cache external API responses - Reduce latency and API costs
  5. Handle Crypto operations in try/catch - Invalid inputs throw errors
  6. WebSocket hibernation for cost - Use Durable Objects with hibernation
  1. 外部请求务必设置超时 - Workers有30秒运行限制,外部API可能挂起
  2. 读取响应体前先克隆 - 响应体仅可读取一次
  3. 大负载使用流传输 - 不要将整个响应缓冲到内存中
  4. 缓存外部API响应 - 降低延迟和API调用成本
  5. 在try/catch中处理Crypto操作 - 无效输入会抛出错误
  6. 使用WebSocket休眠降低成本 - 搭配支持休眠的Durable Objects使用

Top 10 Errors Prevented

可避免的10大常见错误

ErrorSymptomPrevention
Body already read
TypeError: Body has already been consumed
Clone response before reading
Fetch timeoutRequest hangs, worker times outUse
AbortController
with timeout
Invalid JSON
SyntaxError: Unexpected token
Check content-type before parsing
Stream locked
TypeError: ReadableStream is locked
Don't read stream multiple times
Crypto key error
DOMException: Invalid keyData
Validate key format and algorithm
Cache missReturns
undefined
instead of response
Check cache before returning
WebSocket closeConnection drops unexpectedlyHandle close event, implement reconnect
Encoding error
TypeError: Invalid code point
Use TextEncoder/TextDecoder properly
CORS blockedBrowser rejects responseAdd proper CORS headers
Request size
413 Request Entity Too Large
Stream large uploads
错误表现预防方案
响应体已被读取
TypeError: Body has already been consumed
读取前先克隆响应
Fetch超时请求挂起,worker运行超时搭配
AbortController
设置超时
无效JSON
SyntaxError: Unexpected token
解析前先检查content-type
流被锁定
TypeError: ReadableStream is locked
不要多次读取同一个流
Crypto密钥错误
DOMException: Invalid keyData
校验密钥格式和算法是否匹配
缓存未命中返回
undefined
而非响应
返回前先检查缓存是否存在
WebSocket断开连接意外中断处理close事件,实现重连逻辑
编码错误
TypeError: Invalid code point
正确使用TextEncoder/TextDecoder
CORS拦截浏览器拒绝响应添加正确的CORS头
请求过大
413 Request Entity Too Large
流式传输大体积上传内容

Fetch API Patterns

Fetch API 常用模式

With Timeout

带超时实现

typescript
async function fetchWithTimeout(url: string, timeout: number = 5000): Promise<Response> {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    const response = await fetch(url, { signal: controller.signal });
    return response;
  } finally {
    clearTimeout(timeoutId);
  }
}
typescript
async function fetchWithTimeout(url: string, timeout: number = 5000): Promise<Response> {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);

  try {
    const response = await fetch(url, { signal: controller.signal });
    return response;
  } finally {
    clearTimeout(timeoutId);
  }
}

With Retry

带重试实现

typescript
async function fetchWithRetry(
  url: string,
  options: RequestInit = {},
  retries: number = 3
): Promise<Response> {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (response.ok) return response;

      // Retry on 5xx errors
      if (response.status >= 500 && i < retries - 1) {
        await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
        continue;
      }

      return response;
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
    }
  }
  throw new Error('Max retries exceeded');
}
typescript
async function fetchWithRetry(
  url: string,
  options: RequestInit = {},
  retries: number = 3
): Promise<Response> {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (response.ok) return response;

      // 5xx错误时重试
      if (response.status >= 500 && i < retries - 1) {
        await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
        continue;
      }

      return response;
    } catch (error) {
      if (i === retries - 1) throw error;
      await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
    }
  }
  throw new Error('Max retries exceeded');
}

Streams API

Streams API

Transform Stream

转换流

typescript
function createUppercaseStream(): TransformStream<string, string> {
  return new TransformStream({
    transform(chunk, controller) {
      controller.enqueue(chunk.toUpperCase());
    }
  });
}

// Usage
const response = await fetch('https://example.com/text');
const transformed = response.body!
  .pipeThrough(new TextDecoderStream())
  .pipeThrough(createUppercaseStream())
  .pipeThrough(new TextEncoderStream());

return new Response(transformed);
typescript
function createUppercaseStream(): TransformStream<string, string> {
  return new TransformStream({
    transform(chunk, controller) {
      controller.enqueue(chunk.toUpperCase());
    }
  });
}

// 使用示例
const response = await fetch('https://example.com/text');
const transformed = response.body!
  .pipeThrough(new TextDecoderStream())
  .pipeThrough(createUppercaseStream())
  .pipeThrough(new TextEncoderStream());

return new Response(transformed);

Stream Large Response

大响应流处理

typescript
async function streamLargeFile(url: string): Promise<Response> {
  const response = await fetch(url);

  // Stream directly without buffering
  return new Response(response.body, {
    headers: {
      'Content-Type': response.headers.get('Content-Type') || 'application/octet-stream',
    },
  });
}
typescript
async function streamLargeFile(url: string): Promise<Response> {
  const response = await fetch(url);

  // 直接流式传输无需缓冲
  return new Response(response.body, {
    headers: {
      'Content-Type': response.headers.get('Content-Type') || 'application/octet-stream',
    },
  });
}

Crypto API

Crypto API

Hashing

哈希计算

typescript
async function sha256(data: string): Promise<string> {
  const encoder = new TextEncoder();
  const dataBuffer = encoder.encode(data);
  const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
typescript
async function sha256(data: string): Promise<string> {
  const encoder = new TextEncoder();
  const dataBuffer = encoder.encode(data);
  const hashBuffer = await crypto.subtle.digest('SHA-256', dataBuffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}

HMAC Signing

HMAC签名

typescript
async function signHMAC(key: string, data: string): Promise<string> {
  const encoder = new TextEncoder();
  const keyData = encoder.encode(key);
  const dataBuffer = encoder.encode(data);

  const cryptoKey = await crypto.subtle.importKey(
    'raw',
    keyData,
    { name: 'HMAC', hash: 'SHA-256' },
    false,
    ['sign']
  );

  const signature = await crypto.subtle.sign('HMAC', cryptoKey, dataBuffer);
  return btoa(String.fromCharCode(...new Uint8Array(signature)));
}
typescript
async function signHMAC(key: string, data: string): Promise<string> {
  const encoder = new TextEncoder();
  const keyData = encoder.encode(key);
  const dataBuffer = encoder.encode(data);

  const cryptoKey = await crypto.subtle.importKey(
    'raw',
    keyData,
    { name: 'HMAC', hash: 'SHA-256' },
    false,
    ['sign']
  );

  const signature = await crypto.subtle.sign('HMAC', cryptoKey, dataBuffer);
  return btoa(String.fromCharCode(...new Uint8Array(signature)));
}

Cache API

Cache API

typescript
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const cache = caches.default;
    const cacheKey = new Request(request.url, { method: 'GET' });

    // Check cache
    let response = await cache.match(cacheKey);
    if (response) {
      return response;
    }

    // Fetch and cache
    response = await fetch(request);
    response = new Response(response.body, response);
    response.headers.set('Cache-Control', 'public, max-age=3600');

    // Store in cache (don't await)
    ctx.waitUntil(cache.put(cacheKey, response.clone()));

    return response;
  }
};
typescript
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const cache = caches.default;
    const cacheKey = new Request(request.url, { method: 'GET' });

    // 检查缓存
    let response = await cache.match(cacheKey);
    if (response) {
      return response;
    }

    // 拉取数据并缓存
    response = await fetch(request);
    response = new Response(response.body, response);
    response.headers.set('Cache-Control', 'public, max-age=3600');

    // 存入缓存(无需等待执行完成)
    ctx.waitUntil(cache.put(cacheKey, response.clone()));

    return response;
  }
};

WebSockets (Durable Objects)

WebSockets(Durable Objects)

typescript
// Durable Object with WebSocket hibernation
export class WebSocketRoom {
  state: DurableObjectState;

  constructor(state: DurableObjectState) {
    this.state = state;
  }

  async fetch(request: Request): Promise<Response> {
    const upgradeHeader = request.headers.get('Upgrade');
    if (upgradeHeader !== 'websocket') {
      return new Response('Expected websocket', { status: 426 });
    }

    const pair = new WebSocketPair();
    const [client, server] = Object.values(pair);

    // Accept with hibernation
    this.state.acceptWebSocket(server);

    return new Response(null, { status: 101, webSocket: client });
  }

  async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer) {
    // Handle incoming message
    const data = typeof message === 'string' ? message : new TextDecoder().decode(message);

    // Broadcast to all connected clients
    for (const client of this.state.getWebSockets()) {
      client.send(data);
    }
  }

  async webSocketClose(ws: WebSocket, code: number, reason: string) {
    ws.close(code, reason);
  }
}
typescript
// 支持WebSocket休眠的Durable Object
export class WebSocketRoom {
  state: DurableObjectState;

  constructor(state: DurableObjectState) {
    this.state = state;
  }

  async fetch(request: Request): Promise<Response> {
    const upgradeHeader = request.headers.get('Upgrade');
    if (upgradeHeader !== 'websocket') {
      return new Response('Expected websocket', { status: 426 });
    }

    const pair = new WebSocketPair();
    const [client, server] = Object.values(pair);

    // 接受连接并启用休眠
    this.state.acceptWebSocket(server);

    return new Response(null, { status: 101, webSocket: client });
  }

  async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer) {
    // 处理 incoming 消息
    const data = typeof message === 'string' ? message : new TextDecoder().decode(message);

    // 广播给所有连接的客户端
    for (const client of this.state.getWebSockets()) {
      client.send(data);
    }
  }

  async webSocketClose(ws: WebSocket, code: number, reason: string) {
    ws.close(code, reason);
  }
}

When to Load References

何时加载对应参考文档

Load specific references based on the task:
  • Making HTTP requests? → Load
    references/fetch-api.md
    for timeout, retry, proxy patterns
  • Processing large data? → Load
    references/streams-api.md
    for TransformStream, chunking
  • Encryption/signing? → Load
    references/crypto-api.md
    for AES, RSA, JWT verification
  • Caching responses? → Load
    references/cache-api.md
    for Cache API patterns, TTL strategies
  • Real-time features? → Load
    references/websockets.md
    for WebSocket patterns, Durable Objects
  • Text encoding? → Load
    references/encoding-api.md
    for TextEncoder, Base64, Unicode
根据任务需求加载特定参考文档:
  • 需要发起HTTP请求? → 加载
    references/fetch-api.md
    获取超时、重试、代理模式
  • 需要处理大数据? → 加载
    references/streams-api.md
    获取TransformStream、分块处理相关内容
  • 需要加密/签名? → 加载
    references/crypto-api.md
    获取AES、RSA、JWT验证相关内容
  • 需要缓存响应? → 加载
    references/cache-api.md
    获取Cache API模式、TTL策略相关内容
  • 需要实现实时功能? → 加载
    references/websockets.md
    获取WebSocket模式、Durable Objects相关内容
  • 需要处理文本编码? → 加载
    references/encoding-api.md
    获取TextEncoder、Base64、Unicode相关内容

Templates

模板

TemplatePurposeUse When
templates/fetch-patterns.ts
HTTP request utilitiesBuilding API clients
templates/stream-processing.ts
Stream transformationProcessing large files
templates/crypto-operations.ts
Crypto utilitiesSigning, hashing, encryption
templates/websocket-handler.ts
WebSocket DOReal-time applications
模板路径用途适用场景
templates/fetch-patterns.ts
HTTP请求工具构建API客户端
templates/stream-processing.ts
流转换工具处理大文件
templates/crypto-operations.ts
加密工具签名、哈希计算、加密
templates/websocket-handler.ts
WebSocket DO实现实时应用开发

Resources

资源