之前的文章:
首先来看看Cloudflare Workers最基础也最强大的能力之一:处理客户端请求。在请求到达源服务器之前,对客户端发起的HTTP请求进行全面的“增删改查”操作。这让我们可以在网络边缘(Edge)(不知道啥叫网络边缘也没关系,反正就是在后端之前的一个代理)处理流量的超能力,无需改动任何后端代码,就能实现许多非常复杂的功能。
在传统的Web架构中,请求从客户端发出后,通常直接转发给后端服务器。如果想对请求做一些预处理,往往需要在网关层(如Nginx、APISIX)或后端业务代码中实现。但有了Workers,我们可以在Cloudflare遍布全球的节点上,用几行简单的JavaScript代码实现同样甚至更强大的功能。
常见的应用场景包括但不限于:
?env=test来转发请求。下面看看怎么具体操作。
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对象,并在构造时传入我们想要修改的属性。
假设我们想将所有访问/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);
},
};
假设我们需要:
X-Request-Id。Host头。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轻松实现。这种在网络边缘处理请求的能力,提供了强大的灵活性。
在下一篇文章中,我们将研究怎么增删改查后端的响应。
之前的文章:
首先来看看Cloudflare Workers最基础也最强大的能力之一:处理客户端请求。在请求到达源服务器之前,对客户端发起的HTTP请求进行全面的“增删改查”操作。这让我们可以在网络边缘(Edge)(不知道啥叫网络边缘也没关系,反正就是在后端之前的一个代理)处理流量的超能力,无需改动任何后端代码,就能实现许多非常复杂的功能。
在传统的Web架构中,请求从客户端发出后,通常直接转发给后端服务器。如果想对请求做一些预处理,往往需要在网关层(如Nginx、APISIX)或后端业务代码中实现。但有了Workers,我们可以在Cloudflare遍布全球的节点上,用几行简单的JavaScript代码实现同样甚至更强大的功能。
常见的应用场景包括但不限于:
?env=test来转发请求。下面看看怎么具体操作。
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对象,并在构造时传入我们想要修改的属性。
假设我们想将所有访问/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);
},
};
假设我们需要:
X-Request-Id。Host头。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轻松实现。这种在网络边缘处理请求的能力,提供了强大的灵活性。
在下一篇文章中,我们将研究怎么增删改查后端的响应。