63 lines
1.8 KiB
JavaScript
63 lines
1.8 KiB
JavaScript
// Thin relay: this Worker owns no state.
|
|
//
|
|
// It forwards every request to the relay server and streams the answer back, so
|
|
// the panel, the database and the agent API all live on your own host. Nothing
|
|
// is stored in Cloudflare except what the platform keeps in transit.
|
|
//
|
|
// Bindings:
|
|
// var SERVER_URL https://your-server.example
|
|
// secret PROXY_SECRET optional shared header the server can require
|
|
|
|
export default {
|
|
async fetch(request, env)
|
|
{
|
|
const base = (env.SERVER_URL || "").replace(/\/$/, "");
|
|
|
|
if (!base)
|
|
return new Response("SERVER_URL is not configured", { status: 500 });
|
|
|
|
const url = new URL(request.url);
|
|
const target = base + url.pathname + url.search;
|
|
|
|
const headers = new Headers(request.headers);
|
|
|
|
// Do not leak Cloudflare internals to the origin.
|
|
headers.delete("cf-connecting-ip");
|
|
headers.delete("cf-ray");
|
|
headers.delete("cf-visitor");
|
|
headers.delete("x-forwarded-proto");
|
|
|
|
if (env.PROXY_SECRET)
|
|
headers.set("X-Proxy-Secret", env.PROXY_SECRET);
|
|
|
|
const init = {
|
|
method: request.method,
|
|
headers,
|
|
redirect: "manual"
|
|
};
|
|
|
|
if (request.method !== "GET" && request.method !== "HEAD")
|
|
init.body = request.body;
|
|
|
|
let upstream;
|
|
|
|
try
|
|
{
|
|
upstream = await fetch(target, init);
|
|
}
|
|
catch (err)
|
|
{
|
|
return new Response("relay unreachable: " + (err && err.message ? err.message : err), { status: 502 });
|
|
}
|
|
|
|
const response = new Response(upstream.body, {
|
|
status: upstream.status,
|
|
statusText: upstream.statusText,
|
|
headers: upstream.headers
|
|
});
|
|
|
|
response.headers.set("Cache-Control", "no-store");
|
|
return response;
|
|
}
|
|
};
|