简单来说,由于某些原因,一些网站或其提供的 API 服务器架设在国外,如美国或法国,导致国内请求变得异常缓慢,比如 supabase、appwrite。为了解决这个问题,我想到了使用边缘函数,将该网站的所有接口服务转接一下,这样可以显著提高请求速度,还可以做一些非常神奇的事情。
废话不多说,复制代码
你只需要改代码里面需要代理的 host 的就 ok 了,改完之后复制代码。
这个服务器的核心要点有重写头部以避免 iframe、跨域支持等问题。如果有特殊需要,可以继续加限制的,防止盗用,但是我没有这个需求。
const HOST = "baidu.com"; // 改我就行了
/** 复制头部 */
const copyHeaders = (headers: Headers) => {
const newHeader = new Headers();
for (let i of headers.entries()) {
newHeader.append(...i);
}
return newHeader;
};
/** 重写请求头部信息 */
const ReqHeadersRewrite = (req: Request, Url: URL) => {
const newH = copyHeaders(req.headers);
newH.delete("X-deno-transparent");
// 重写 referer 和 origin 保证能够获取到数据
newH.set("referer", Url.toString());
newH.set("origin", Url.toString());
return newH;
};
const ResHeadersReWrite = (res: Response, domain: string) => {
const newHeader = copyHeaders(res.headers);
newHeader.set("access-control-allow-origin", "*");
const cookie = newHeader.get("set-cookie");
cookie && newHeader.set("set-cookie", cookie.replace(/domain=(.+?);/, `domain=${domain};`));
newHeader.delete("X-Frame-Options"); // 防止不准 iframe 嵌套
return newHeader;
};
/** 代理整个网站,包括所有请求模式 */
const proxy = (host: string, req: Request) => {
// const Url = getTransparentURL(req);
const Url = new URL(req.url);
Url.host = host;
if (Url instanceof Response) return Url;
// console.log(Url.toString());
const newH = ReqHeadersRewrite(req, Url);
return fetch(Url, {
headers: newH,
method: req.method,
// 所有 body 将会转交,故没啥兼容问题
body: req.body,
redirect: req.redirect,
}).then((res) => {
const newHeader = ResHeadersReWrite(res, new URL(req.url).host);
const config = {
status: res.status,
statusText: res.statusText,
headers: newHeader,
};
console.log(res.status, res.url);
if (res.status >= 300 && res.status < 400) {
console.log("重定向至", req.url);
return Response.redirect(req.url, res.status);
}
return new Response(res.body, config);
});
};
Deno.serve(
(req: Request) => {
return proxy(HOST, req);
},
{
onError(e) {
return new Response(JSON.stringify({ error: e, code: 101 }), {
headers: {
"access-control-allow-origin": "*",
},
});
},
}
);
登录 Deno Deploy,直接 playground 部署!
Deno Deploy 进入 Deno 的网站,然后使用 Github 登录,点击 New Playground 创建一个新的边缘函数。
直接拷贝上面的代码,点击 Save & Deplay, 稍等片刻就可以看到我们在 Deno 的域名下代理了某度。
结语
其实基于 Faas 的平台都支持 HTTP 代理的,比如 Vercel、Cloudflare 等,上面的代码核心函数也就是 proxy,进行迁移也极其简单。