在第一讲中我们介绍了worker的优点,接下来我们就来实现一个api proxy的功能,主要是为了熟悉worker的开发和部署流程。
功能介绍
由于一些原因呢,我们无法访问一些网站。假设我们无法访问https://api.google.com/v1/user/info,那么我们可以给worker发送一个如下的请求
GET http://xxx.worker.dev/v1/user/info
Host: xxx.worker.dev
Proxy-Host: api.google.com
Proxy-Proto: https
Worker会提取Header头里面的Proxy-Host和Proxy-Proto来构造请求https://api.google.com/v1/user/info,并将获得的请求返回给我们。
创建worker
访问你的worker页面https://dash.cloudflare.com/xxxxxxspaceid/workers-and-pages/create/workers/new

代码
addEventListener("fetch", (event) => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
// 提取原来请求的headers
var hds = {};
for (let k of request.headers.keys()){
if (typeof k === "string"){
// 不需要原来的host,发送代理请求时候,会用新的Host添加上去
if(k === "host")continue;
// 不需要cf开头的,不需要proxy-开头的
if(k.startsWith("cf-") || k.startsWith("proxy-"))continue
hds[k] = request.headers.get(k) || "";
}
}
// 提取需要代理的协议和Host
const proxy_host = request.headers.get('Proxy-Host') || "";
let proxy_proto = request.headers.get('Proxy-Proto') || "";
if (proxy_host ==="" || proxy_proto === ""){
return new Response(
JSON.stringify(hds), {status:401, headers: {"content-type": "application/json"}}
)
}
if (!proxy_proto.endsWith(":")){
proxy_proto += ":";
}
// 替换到真实的url
const url = new URL(request.url);
const fetchAPI = request.url.replace(url.host, proxy_host).replace(url.protocol, proxy_proto);
// 支持option method,用来跨站
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'OPTIONS',
'Access-Control-Allow-Headers': '*',
};
if(request.method === "OPTIONS"){
return new Response(null, {headers: corsHeaders});
}
// 构造代理请求,使用新的url,用原来的method,原来的headers,原来的body
let areq = new Request(
fetchAPI,
{
method: request.method,
headers: new Headers(hds),
body: request.body,
}
)
console.log('method: '+ request.method + ' , url: ' + fetchAPI)
// worker发送请求
const response = await fetch(areq)
// 将代理的response,发送给客户端
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
CloudFlare有个比较好的地方,就是这个playground,既能编辑代码,又能测试,还能看到输入和输出,非常方便。

本次例子使用的是api-proxy,主要因为api的response一般都是json格式,因此只需要原封不动返回给客户端。而如果代理的是网页html的话,需要将Response里面的外链和资源的src都进行一个替换,所以会更复杂一些,我们就下一次再讲解。