mcpField
W
workers-runtime-apis

workers-runtime-apis

github.com/secondsky开发24079 次安装5 周前更新
代码仓库

关于 workers-runtime-apis

面向 Cloudflare Workers 开发者的运行时 API 参考,涵盖 Fetch、Streams、Crypto、Cache、WebSockets 和文本编码,并提供常见模式与错误处理建议。

主要功能

  1. 01涵盖六类运行时 API
  2. 02提供 Fetch 超时与重试模式
  3. 03介绍流式数据处理
  4. 04包含加密和缓存示例
  5. 05整理常见错误及预防方法

适用场景

  1. 01为外部 HTTP 请求设置超时
  2. 02处理大型文件或流式数据
  3. 03为响应添加缓存
  4. 04构建 WebSocket 实时功能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/secondsky/claude-skills --skill workers-runtime-apis

安装后在 Claude Code 中输入/workers-runtime-apis确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
cache-api.md
crypto-api.md
encoding-api.md
fetch-api.md
streams-api.md
websockets.md
templates/
crypto-operations.ts
fetch-patterns.ts
stream-processing.ts
websocket-handler.ts

详细介绍

Cloudflare Workers 运行时 API

掌握 Workers 运行时 API:Fetch、Streams、Crypto、Cache、WebSockets 和文本编码。

快速参考

API用途常见用法
FetchHTTP 请求外部 API、代理
Streams数据流式处理大文件、实时处理
Crypto密码学哈希、签名、加密
Cache响应缓存性能优化
WebSockets实时连接聊天、实时更新
Encoding文本编码UTF-8、Base64

快速入门:Fetch API

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);
  }
};

关键规则

  1. 始终为外部请求设置超时 - Workers 的时间限制为 30s,外部 API 可能会一直挂起
  2. 读取响应正文前先克隆响应 - 正文只能读取一次
  3. 对大型负载使用流式处理 - 不要将整个响应缓冲到内存中
  4. 缓存外部 API 响应 - 降低延迟和 API 成本
  5. 在 try/catch 中处理 Crypto 操作 - 无效输入会抛出错误
  6. 使用 WebSocket 休眠来降低成本 - 将 Durable Objects 与休眠功能配合使用

可预防的十大错误

错误表现预防方法
正文已读取TypeError: Body has already been consumed读取前克隆响应
Fetch 超时请求挂起,Worker 超时使用 AbortController 设置超时
无效 JSONSyntaxError: 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 模式

设置超时
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);
  }
}
重试
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');
}

Streams API

转换流
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);
流式处理大型响应
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',
    },
  });
}

Crypto API

哈希
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 签名
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

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;
  }
};

WebSockets(Durable Objects)

// 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);
  }
}

何时加载参考资料

根据任务加载相应的参考资料:

  • 需要发送 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/fetch-patterns.tsHTTP 请求工具构建 API 客户端
templates/stream-processing.ts流转换处理大型文件
templates/crypto-operations.tsCrypto 工具签名、哈希、加密
templates/websocket-handler.tsWebSocket DO实时应用

资源

评论

支持 Markdown