随橙想,开了 Tampermonkey WebDAV 同步把坚果云 1G 流量造完了,只好另谋生路——这一谋就搜到了这篇文章《Alist 事件后,我如何用 Deno 解决 Koofr WebDAV 在国内的访问难题》。
然而然而,我以为很简单的一个复制粘贴先后经历了:
- Deno Deploy 无法注册(第二天好了);
- 链接代码无法部署;
- 让 ChatGPT 改,纯属添乱。
只好自己动手,注意这个代码对应的服务器地址应为 https://APP.ORG.deno.net/koofr。
改完之后发现 Deno Deploy 早在上文发布之前就被墙了这是怎么回事呢!
const mapping: Record<string, string> = {
"/anthropic": "api.anthropic.com",
"/cohere": "api.cohere.ai",
"/discord": "discord.com/api",
"/fireworks": "api.fireworks.ai/inference",
"/gemini": "generativelanguage.googleapis.com",
"/groq": "api.groq.com/openai",
"/huggingface": "api-inference.huggingface.co",
"/koofr": "app.koofr.net/dav/Koofr",
"/novita": "api.novita.ai",
"/openai": "api.openai.com",
"/openrouter": "openrouter.ai/api",
"/portkey": "api.portkey.ai",
"/telegram": "api.telegram.org",
"/together": "api.together.xyz",
"/xai": "api.x.ai",
};
Deno.serve(async (req: Request) => {
const url = new URL(req.url);
const hostname = url.hostname;
const pathname = url.pathname;
if (pathname === "/") {
return new Response(null, { status: 404 });
}
if (pathname === "/robots.txt") {
return new Response("User-agent: *\nDisallow: /", {
headers: { "content-type": "text/plain" },
});
}
let href = "";
for (const key in mapping) {
if (pathname.startsWith(key)) {
href = req.url.replace(hostname + key, mapping[key]);
break;
}
}
if (href === req.url) {
return new Response("Not Found", { status: 404 });
}
const reqHeaders = new Headers(req.headers);
reqHeaders.set("host", new URL(href).host);
reqHeaders.delete("x-forwarded-for");
reqHeaders.delete("x-real-ip");
reqHeaders.delete("forwarded");
reqHeaders.delete("via");
try {
const res = await fetch(href, {
headers: reqHeaders,
method: req.method,
body: req.body,
redirect: "manual"
});
const resHeaders = new Headers(res.headers);
resHeaders.set("x-content-type-options", "nosniff");
resHeaders.delete("connection");
resHeaders.delete("keep-alive");
resHeaders.delete("proxy-authenticate");
resHeaders.delete("proxy-authorization");
resHeaders.delete("te");
resHeaders.delete("trailers");
resHeaders.delete("transfer-encoding");
resHeaders.delete("upgrade");
if (pathname.startsWith("/koofr") && req.method === "PROPFIND") {
const type = res.headers.get("Content-Type") || "";
if (res.ok && (type.includes("application/xml") || type.includes("text/xml"))) {
resHeaders.delete("Content-Length");
const text = await res.text();
const body = text.replaceAll("/dav/Koofr/", "/koofr/");
return new Response(body, {
status: res.status,
headers: resHeaders
});
}
}
return new Response(res.body, {
status: res.status,
headers: resHeaders
});
} catch (err) {
return new Response("Upstream error", { status: 502 });
}
});