mcpField
C
cloudflare-workers-runtime-apis

cloudflare-workers-runtime-apis

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

关于 cloudflare-workers-runtime-apis

面向 Cloudflare Workers 开发者的运行时 API 指南,涵盖 Fetch、Streams、Crypto、Cache、WebSockets 和文本编码。提供常见模式、错误规避建议及按任务分类的参考资料。

主要功能

  1. 01Fetch 请求与超时、重试模式
  2. 02Streams 流式处理示例
  3. 03Crypto 哈希与签名示例
  4. 04Cache API 响应缓存
  5. 05WebSockets 与 Durable Objects
  6. 06文本编码参考

适用场景

  1. 01为外部 HTTP 请求添加超时或重试
  2. 02流式处理大型响应数据
  3. 03在 Workers 中实现缓存或实时连接

安装

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

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

安装后在 Claude Code 中输入/cloudflare-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