惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
C
Check Point Blog
Vercel News
Vercel News
Y
Y Combinator Blog
G
Google Developers Blog
P
Proofpoint News Feed
WordPress大学
WordPress大学
MongoDB | Blog
MongoDB | Blog
博客园 - 司徒正美
Last Week in AI
Last Week in AI
博客园 - 【当耐特】
N
Netflix TechBlog - Medium
L
LangChain Blog
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
大猫的无限游戏
大猫的无限游戏
D
DataBreaches.Net
博客园_首页
B
Blog RSS Feed
The Cloudflare Blog
MyScale Blog
MyScale Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Microsoft Security Blog
Microsoft Security Blog

又耳笔记

用AI挣钱之AI建站:二维码生成器工具 用AI挣钱之AI建站:https://markdowntopdf.top Cloudflare Workers实战番外一:用Static Assets托管网站,告别传统方案 Cloudflare Workers实战(五):不止JavaScript,拥抱Python与Rust Cloudflare Workers实战(四):托管和分发静态文件 Cloudflare Workers实战(三):实现认证、重定向与缓存 Cloudflare Workers实战(二):动态修改后端响应 Cloudflare workers不完全指南 使用n8n创作短篇小说 水果风波:信任的代价 用Python将PDF文件转换成图片 rust网络框架Pingora源码阅读3 rust网络框架Pingora源码阅读2 rust网络框架Pingora源码阅读1 Pingora快速入门教程1之总览 Rust模板引擎askama快速入门引擎 使用Loco快速搭建自己的后台系统 用Rust发一封图文并茂的邮件 Rust小项目: 写一个简单的恶意流量阻断器 Rust小项目: 写一个简单的网页爬虫 Rust命令行库Clap快速入门教程 Rust小项目:用Rust写一个端口扫描器 Rust真全栈开发快速入门 rust声明宏快速入门教程 Rust文本处理快速入门教程 RUST web框架axum快速入门教程6之测试 白嫖免费的Rust在线运行时shuttle RUST web框架axum快速入门教程5之中间件 用Rust来做以太坊开发5之事件日志及签名 《英语语法分解大全》读后感
Cloudflare Workers实战(一):随心所欲操作客户端请求
About 又耳宁 关于技术与股票的一些零碎想法 · 2025-07-15 · via 又耳笔记

之前的文章:

  1. Cloudflare workers不完全指南"

首先来看看Cloudflare Workers最基础也最强大的能力之一:处理客户端请求。在请求到达源服务器之前,对客户端发起的HTTP请求进行全面的“增删改查”操作。这让我们可以在网络边缘(Edge)(不知道啥叫网络边缘也没关系,反正就是在后端之前的一个代理)处理流量的超能力,无需改动任何后端代码,就能实现许多非常复杂的功能。

操作客户端请求有啥用?

在传统的Web架构中,请求从客户端发出后,通常直接转发给后端服务器。如果想对请求做一些预处理,往往需要在网关层(如Nginx、APISIX)或后端业务代码中实现。但有了Workers,我们可以在Cloudflare遍布全球的节点上,用几行简单的JavaScript代码实现同样甚至更强大的功能。

常见的应用场景包括但不限于:

  • A/B测试:根据用户的查询参数,Cookie或IP,将请求转发到不同的后端服务,测试新功能,比如根据查询参数?env=test来转发请求。
  • 访问控制:根据请求来源、Header等信息,实现简单的防火墙或认证逻辑,比如没有Token HTTP头就直接拒绝。
  • 请求规范化:统一修改或添加某些HTTP头,确保后端服务接收到的请求格式一致,比如增加client-id的HTTP头
  • 动态重定向:根据用户设备类型,将其重定向到PC版或移动版网站,根据User-Agent来生成不同的重定向请求。

下面看看怎么具体操作。

读取请求信息

Workers通过fetch事件监听器接收请求,事件处理函数的第一个参数request就是一个标准的Request对象,包含了所有客户端请求信息,在此基础上还提供了cloudflare的扩展信息对象cf, 这个cf包括但不限于客户端所在城市,所在国家,经纬度等额外的信息,这样后端就不需要根据IP来查询对应的信息来。

// worker.js
export default {
  async fetch(request, env, ctx) {
    // 1. 获取请求方法、URL和HTTP协议版本
    const method = request.method; // "GET", "POST", etc.
    const url = new URL(request.url);
    const httpProtocol = request.cf.httpProtocol; // "HTTP/2", "HTTP/1.1", etc.

    console.log(`收到一个 ${method} 请求,来自 ${url.pathname}`);

    // 2. 读取请求头 (Headers)
    // request.headers 是一个 Headers 对象,可以通过 get() 方法获取特定头的值
    const userAgent = request.headers.get('User-Agent') || 'N/A';
    console.log(`客户端 User-Agent 是: ${userAgent}`);

    // 3. 读取请求体 (Body)
    // request.body 是一个 ReadableStream
    // 即便是不需要读取请求体的GET请求,这个属性也存在
    let requestBody = "请求体为空或未读取";
    if (method === 'POST') {
      // 使用 .json() .text() .arrayBuffer() 等方法来读取流
      // 注意:一个请求体只能被读取一次!
      try {
        const data = await request.json();
        requestBody = JSON.stringify(data, null, 2);
      } catch (e) {
        requestBody = "无法解析为JSON";
      }
    }
    console.log(`请求体内容: \n${requestBody}`);

    // 为了演示,我们直接返回读取到的信息
    return new Response(`请求信息:\n方法: ${method}\n路径: ${url.pathname}\nUser-Agent: ${userAgent}\n请求体: ${requestBody}`,
      {
        headers: { 'Content-Type': 'text/plain; charset=utf-8' },
      }
    );
  },
};

核心知识点

  • request.url是一个字符串,通常需要用new URL(request.url)来方便地解析其各个部分(如主机名hostname、路径pathname、查询参数searchParams)。
  • request.body是一个可读流(ReadableStream)。这意味着请求体数据是分块到达的,这种设计对于处理大文件上传等场景至关重要,可以有效降低内存消耗。一旦调用了request.json()request.text()等方法,流就会被消耗,不能再次读取。

修改请求

直接修改传入的request对象是不被允许的。正确的做法是,基于原始请求,创建一个新的Request对象,并在构造时传入我们想要修改的属性。

示例1:修改URL(请求重写)

假设我们想将所有访问/v1/api的请求,都无缝地转发到后端的/api/v2路径,而对客户端保持透明。

// worker.js
export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    // 检查路径是否匹配
    if (url.pathname.startsWith('/v1/api')) {
      // 替换路径部分
      url.pathname = url.pathname.replace('/v1/api', '/api/v2');

      // 使用修改后的URL创建一个新请求,并将其发送到源站
      const newRequest = new Request(url.toString(), request);
      return fetch(newRequest);
    }

    // 对于其他请求,正常转发
    return fetch(request);
  },
};

示例2:修改、添加、删除请求头

假设我们需要:

  1. 为每个请求添加一个唯一的追踪ID X-Request-Id
  2. 强制指定发往源站的Host头。
  3. 删除客户端可能发送的X-Forwarded-For头,以使用Cloudflare提供的真实IP头。
// worker.js
export default {
  async fetch(request, env, ctx) {
    // 1. 克隆原始请求的头,得到一个可修改的 Headers 对象
    const newHeaders = new Headers(request.headers);

    // 2. 添加一个新的头
    newHeaders.set('X-Request-Id', crypto.randomUUID());

    // 3. 修改一个已有的头(如果存在)
    // 注意:修改Host头需要你的Cloudflare套餐支持
    newHeaders.set('Host', 'api.my-backend.com');

    // 4. 删除一个头
    newHeaders.delete('X-Forwarded-For');

    // 5. 创建一个新请求,并应用修改后的头
    // new Request(request) 是一种快捷方式,等同于 new Request(request.url, request)
    const newRequest = new Request(request, {
      headers: newHeaders,
    });

    // 将带有新头的请求发送到源站
    return fetch(newRequest);
  },
};

总结

workers作为代理自然能够增删改查请求,而跟其他代理不同点在于,这个代理是可编程的,还不要钱。无论是简单的信息获取,还是复杂的请求重写和Header操作,都可以通过标准的Request和Headers API轻松实现。这种在网络边缘处理请求的能力,提供了强大的灵活性。

在下一篇文章中,我们将研究怎么增删改查后端的响应。