关于 workers-runtime-apis
面向 Cloudflare Workers 开发者的运行时 API 参考,涵盖 Fetch、Streams、Crypto、Cache、WebSockets 和文本编码,并提供常见模式与错误处理建议。
主要功能
- 01涵盖六类运行时 API
- 02提供 Fetch 超时与重试模式
- 03介绍流式数据处理
- 04包含加密和缓存示例
- 05整理常见错误及预防方法
适用场景
- 01为外部 HTTP 请求设置超时
- 02处理大型文件或流式数据
- 03为响应添加缓存
- 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.mdcrypto-api.mdencoding-api.mdfetch-api.mdstreams-api.mdwebsockets.mdtemplates/crypto-operations.tsfetch-patterns.tsstream-processing.tswebsocket-handler.ts详细介绍
Cloudflare Workers 运行时 API
掌握 Workers 运行时 API:Fetch、Streams、Crypto、Cache、WebSockets 和文本编码。
快速参考
| API | 用途 | 常见用法 |
|---|---|---|
| Fetch | HTTP 请求 | 外部 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);
}
};
关键规则
- 始终为外部请求设置超时 - Workers 的时间限制为 30s,外部 API 可能会一直挂起
- 读取响应正文前先克隆响应 - 正文只能读取一次
- 对大型负载使用流式处理 - 不要将整个响应缓冲到内存中
- 缓存外部 API 响应 - 降低延迟和 API 成本
- 在 try/catch 中处理 Crypto 操作 - 无效输入会抛出错误
- 使用 WebSocket 休眠来降低成本 - 将 Durable Objects 与休眠功能配合使用
可预防的十大错误
| 错误 | 表现 | 预防方法 |
|---|---|---|
| 正文已读取 | 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 模式
设置超时
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.ts | HTTP 请求工具 | 构建 API 客户端 |
templates/stream-processing.ts | 流转换 | 处理大型文件 |
templates/crypto-operations.ts | Crypto 工具 | 签名、哈希、加密 |
templates/websocket-handler.ts | WebSocket DO | 实时应用 |
资源
- 运行时 API:https://developers.cloudflare.com/workers/runtime-apis/
- Fetch API:https://developers.cloudflare.com/workers/runtime-apis/fetch/
- Streams API:https://developers.cloudflare.com/workers/runtime-apis/streams/
- Web Crypto:https://developers.cloudflare.com/workers/runtime-apis/web-crypto/
- Cache API:https://developers.cloudflare.com/workers/runtime-apis/cache/
- WebSockets:https://developers.cloudflare.com/workers/runtime-apis/websockets/
评论
支持 Markdown