Hugging8N / cloudflare-worker.js
somratpro's picture
feat: enhance Cloudflare proxy with shared secret support, add uptime monitoring features, and improve startup timeout handling
7f99b73
raw
history blame
3.36 kB
/**
* Cloudflare Worker: Universal Outbound Proxy
*
* Deployment:
* 1. Go to dash.cloudflare.com -> Workers & Pages -> Create Worker.
* 2. Paste this code and deploy.
* 3. Use your worker URL (e.g., https://my-proxy.workers.dev) as CLOUDFLARE_PROXY_URL.
*
* This worker reads the 'x-target-host' header to determine where to forward the request.
*/
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const targetHost = request.headers.get("x-target-host");
const proxySecret = (
env.CLOUDFLARE_PROXY_SECRET ||
env.PROXY_SHARED_SECRET ||
""
).trim();
// Secret check is optional: when unset, requests are allowed without x-proxy-key.
if (proxySecret) {
const providedSecret = request.headers.get("x-proxy-key") || "";
if (providedSecret !== proxySecret) {
return new Response("Unauthorized", { status: 401 });
}
}
const allowedTargetsRaw = (
env.ALLOWED_TARGETS ||
"api.telegram.org,discord.com,discordapp.com,gateway.discord.gg,status.discord.com"
).trim();
const allowProxyAll =
String(env.ALLOW_PROXY_ALL || "false").toLowerCase() === "true";
const allowedTargets = allowedTargetsRaw
.split(",")
.map((value) => value.trim().toLowerCase())
.filter(Boolean);
const isAllowedHost = (hostname) => {
if (!hostname) return false;
const normalized = String(hostname).trim().toLowerCase();
if (!normalized) return false;
if (allowProxyAll) return true;
return allowedTargets.some(
(domain) => normalized === domain || normalized.endsWith(`.${domain}`),
);
};
let targetBase = "";
if (targetHost) {
// Use the host provided in the header (preferred)
if (!isAllowedHost(targetHost)) {
return new Response("Target host is not allowed.", { status: 403 });
}
targetBase = `https://${targetHost}`;
} else {
// Fallback: Guess based on path (legacy support)
if (url.pathname.startsWith("/bot")) {
targetBase = "https://api.telegram.org";
} else if (
url.pathname.startsWith("/api/webhooks") ||
url.pathname.startsWith("/api/v")
) {
targetBase = "https://discord.com";
} else {
return new Response(
"Invalid request. 'x-target-host' header missing and target not recognized via path.",
{ status: 400 },
);
}
}
const targetUrl = targetBase + url.pathname + url.search;
// Copy headers and remove internal/Cloudflare-specific ones
const headers = new Headers(request.headers);
headers.delete("cf-connecting-ip");
headers.delete("cf-ray");
headers.delete("cf-visitor");
headers.delete("x-real-ip");
headers.delete("x-target-host"); // Don't leak this to the target
const modifiedRequest = new Request(targetUrl, {
method: request.method,
headers: headers,
body: request.body,
redirect: "follow",
});
try {
const response = await fetch(modifiedRequest);
// Special handling for Discord/Telegram which might return 403 on some CF IPs
// If needed, you can add retry logic here.
return response;
} catch (e) {
return new Response(`Proxy Error: ${e.message}`, { status: 502 });
}
},
};