CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Cloudflare 实战入门/课时/Workers 核心
RawBlame
课时目录12 节

Cloudflare 实战入门

  1. 01边缘计算概览
  2. 02Wrangler 与本地开发
  3. 03Workers 核心
  4. 04Workers KV
  5. 05R2 对象存储
  6. 06D1 数据库
  7. 07Queues 消息队列
  8. 08Durable Objects
  9. 09Workers AI
  10. 10Stream 与媒体
  11. 11安全与防护
  12. 12运维与集成

Workers 核心

Fetch API 与中间件。

30 分钟

Workers 核心

这一课你将能做到

  1. 编写完整的 Worker Fetch Handler,处理 GET/POST、JSON、Header、Query 参数
  2. 用 Hono 或原生 Fetch API 实现路由、中间件、错误处理
  3. 解释 Workers 的 Request / Response / ExecutionContext 生命周期

为什么要学

Worker 的核心就是一个 fetch(request, env, ctx) 函数。听起来简单,但里面的门道很多:请求体怎么解析?大文件怎么流式传输?怎么同时转发到多个后端?怎么加鉴权中间件?

人话:Workers 核心就是「如何用标准 Web API 优雅地处理 HTTP 请求」。学会了这套,不管是写 API 网关、做请求聚合、还是做边缘鉴权,都游刃有余。

先建立图像

用户请求 ──> [Cloudflare Edge Node]
                     │
                     ▼
              Worker.fetch(request, env, ctx)
                     │
         ┌───────────┼───────────┐
         ▼           ▼           ▼
    [读取请求]   [业务逻辑]   [访问绑定]
         │           │           │
         ▼           ▼           ▼
    [返回 Response]              [KV/R2/D1/Queue]
                     │
                     ▼
              用户收到响应

ctx(ExecutionContext)是 Workers 特有的:它提供 waitUntil() 和 passThroughOnException(),让你在返回响应后还能继续异步执行(比如写日志、发统计)。

跟着做

步骤 1:最基础的 Fetch Handler

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);
    
    if (url.pathname === '/') {
      return new Response('Hello Edge!');
    }
    
    if (url.pathname === '/api/user') {
      return Response.json({ id: 1, name: 'Alice' });
    }
    
    return new Response('Not Found', { status: 404 });
  },
} satisfies ExportedHandler<Env>;

步骤 2:解析 Query、Header、Body

export default {
  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);
    const q = url.searchParams.get('q');
    const auth = request.headers.get('Authorization');
    
    if (request.method === 'POST') {
      const contentType = request.headers.get('content-type') ?? '';
      
      if (contentType.includes('application/json')) {
        const body = await request.json();
        return Response.json({ received: body });
      }
      
      if (contentType.includes('application/x-www-form-urlencoded')) {
        const formData = await request.formData();
        const name = formData.get('name');
        return Response.json({ name });
      }
    }
    
    return Response.json({ q, auth });
  },
} satisfies ExportedHandler<Env>;

步骤 3:用 Hono 实现路由和中间件

import { Hono } from 'hono';
import { cors } from 'hono/cors';
import { bearerAuth } from 'hono/bearer-auth';

const app = new Hono<{ Bindings: Env }>();

// CORS 中间件
app.use('/api/*', cors());

// 鉴权中间件
app.use('/api/admin/*', bearerAuth({ token: 'secret-token' }));

app.get('/api/users/:id', (c) => {
  const id = c.req.param('id');
  return c.json({ id, name: 'Alice' });
});

app.post('/api/users', async (c) => {
  const body = await c.req.json();
  return c.json({ created: body }, 201);
});

export default app;

步骤 4:请求转发与响应改写

export default {
  async fetch(request: Request): Promise<Response> {
    const url = new URL(request.url);
    
    // 转发到源站
    if (url.pathname.startsWith('/api/')) {
      const backend = new URL(url.pathname.replace('/api', ''), 'https://origin.internal');
      const modifiedRequest = new Request(backend, request);
      modifiedRequest.headers.set('X-Forwarded-By', 'cloudflare-worker');
      
      const response = await fetch(modifiedRequest);
      
      // 改写响应 Header
      const newResponse = new Response(response.body, response);
      newResponse.headers.set('Cache-Control', 'public, max-age=60');
      return newResponse;
    }
    
    return new Response('Static asset');
  },
} satisfies ExportedHandler<Env>;

步骤 5:使用 ctx.waitUntil 做异步任务

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const response = new Response('Processing...');
    
    // 响应返回后,继续执行异步任务
    ctx.waitUntil(
      (async () => {
        await env.MY_QUEUE.send({ type: 'log', path: new URL(request.url).pathname });
        await env.MY_KV.put(`log:${Date.now()}`, request.url);
      })()
    );
    
    return response;
  },
} satisfies ExportedHandler<Env>;

讲清楚要点

  1. Request 是流式的:request.body 是一个 ReadableStream,如果只需要 JSON 就直接 await request.json();大文件建议用 request.body.pipeTo() 直接转发到 R2 或另一个后端,避免内存爆掉。
  2. Response 也是流式的:可以用 new Response(stream) 返回流式数据,配合 TransformStream 做实时压缩、加密、格式转换。
  3. Hono 是事实标准:虽然原生 Fetch Handler 也能写路由,但 Hono 提供了中间件、参数解析、错误处理、CORS、JWT 等开箱即用的功能,代码更简洁。
  4. ctx.waitUntil 不是万能的:它最多再运行 30 秒(或更久,取决于 plan),适合写日志、发消息,不适合做长时间任务。长时间任务应该用 Queues 或 Cron Triggers。
  5. 不要依赖全局状态:Worker 实例可能被复用,也可能被销毁。全局变量可能在不同请求间共享,也可能不共享。状态请放到 KV、D1、Durable Objects。

你可能会懵的地方

  • 为什么 request.json() 会报错 Unexpected end of JSON input? 请求体为空或格式不对。先检查 content-type 是否真的是 JSON,再用 try-catch 包裹解析逻辑。

  • Response 返回了但 ctx.waitUntil 里的代码没执行? waitUntil 不保证一定执行,Worker 可能因为超时或平台限制被提前终止。关键业务不要放在 waitUntil 里。

  • 怎么在 Hono 里访问绑定的 KV? 通过 c.env.MY_KV,前提是你在 new Hono<{ Bindings: Env }>() 里声明了 Bindings 泛型。

  • Worker 能处理 WebSocket 吗? 可以,但需要用 Durable Objects 来管理连接状态。普通 Worker 只能做 WebSocket 的「升级握手」,真正的长连接消息处理需要 DO。

  • Worker 里能调用外部 API 吗? 可以,用标准 fetch()。注意默认没有超时,建议用 AbortController 设置超时。

错法对照

错法问题正解
把大文件 await request.arrayBuffer() 全部读进内存内存超限,Worker 崩溃用 request.body.pipeTo() 流式转发
在全局作用域 let cache = {} 存数据不同请求/节点不共享,可能读到脏数据用 KV 或 Durable Objects
ctx.waitUntil 里做关键业务逻辑可能不执行或超时关键逻辑放在响应前,或用 Queues
直接 fetch(request) 转发原始请求会带上原始 Host Header,导致源站拒绝创建 new Request(backendUrl, request) 并修改 headers
用 process.env 读环境变量Workers 没有 process通过 env 参数或 c.env 访问

卡点急救

  1. POST 请求体解析失败:确认 content-type 正确;如果是 multipart/form-data,用 request.formData() 而不是 request.json()。
  2. Hono 路由 404:检查路径是否以 / 开头;检查是否绑定了正确的 HTTP 方法(app.get vs app.post)。
  3. 响应被 Cloudflare CDN 缓存了:在 Response 里加 Cache-Control: no-cache,或在 Dashboard 的 Page Rules 里关闭缓存。

面试常问

  • Workers 的 fetch handler 和 Express 的 app.get 有什么本质区别? Workers 的 fetch 是请求驱动的,没有常驻进程;Express 是常驻 Node.js 进程。Workers 的 Request/Response 是 Web 标准 API,Express 的是 Node 特有的 req/res 对象。Workers 天然分布式,Express 需要自己部署多实例。

  • ctx.waitUntil 适合做什么? 适合「响应后异步执行」的非关键任务:写日志、发统计、清理缓存。不适合关键业务逻辑,因为不保证执行完成,且有 30 秒限制。

  • Workers 里怎么实现中间件? 用 Hono 的 app.use(),或者自己封装高阶函数:接收 request,返回 Response 或 null(继续下一个)。核心思想是「洋葱模型」:请求进入时逐层处理,响应返回时逐层处理。

自测三问

  1. Request 和 Response 在 Workers 中是什么类型的对象?它们和 Node.js 的 req/res 有什么区别?
  2. 什么时候应该用 ctx.waitUntil,什么时候不应该?
  3. 如果要在 Worker 里同时调用三个外部 API 并合并结果,你会怎么写?(提示:Promise.all)

小结一句话

Workers 核心就是标准 Web API 的 fetch handler:用 Request/Response/ExecutionContext 处理 HTTP 请求,用 Hono 简化路由和中间件,用 ctx.waitUntil 处理响应后的异步任务。

延伸

  • Workers Fetch Handler 官方文档
  • Hono 官方文档
  • 下一课:Workers KV,学习边缘键值存储的读写模式与缓存策略。
加载本节练习…
← 上一课Wrangler 与本地开发下一课 →Workers KV