2026-06-10 21:38:04 +07:00
|
|
|
/**
|
|
|
|
|
* Cloudflare Workers-compatible relay handler.
|
|
|
|
|
*
|
2026-06-24 23:48:16 +07:00
|
|
|
* Thin wrapper around the shared router in src/lib/router.ts.
|
2026-06-10 21:38:04 +07:00
|
|
|
* Uses `env` bindings for configuration instead of `process.env`.
|
2026-06-24 23:48:16 +07:00
|
|
|
* Does NOT support WebSocket upgrades.
|
|
|
|
|
* Exports `{ fetch }` as required by Cloudflare Workers.
|
2026-06-10 21:38:04 +07:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import {
|
2026-06-24 23:48:16 +07:00
|
|
|
handleRelayPlain,
|
|
|
|
|
handleRequest,
|
|
|
|
|
getClientIP,
|
|
|
|
|
} from "./lib/router";
|
|
|
|
|
import type { RouterEnv } from "./lib/router";
|
2026-06-10 21:38:04 +07:00
|
|
|
|
2026-06-24 18:18:49 +07:00
|
|
|
import { getTestPageHtml } from "./lib/test-page";
|
2026-06-10 21:38:04 +07:00
|
|
|
|
2026-06-11 03:56:26 +07:00
|
|
|
// --- Types -------------------------------------------------------------------
|
2026-06-10 21:38:04 +07:00
|
|
|
|
|
|
|
|
export interface Env {
|
|
|
|
|
RELAY_TIMEOUT_MS?: string;
|
|
|
|
|
RATE_LIMIT_MAX?: string;
|
|
|
|
|
RATE_LIMIT_WINDOW_MS?: string;
|
|
|
|
|
PORT?: string;
|
2026-06-11 00:56:18 +07:00
|
|
|
API_KEY?: string;
|
2026-06-10 21:38:04 +07:00
|
|
|
}
|
|
|
|
|
|
2026-06-24 23:48:16 +07:00
|
|
|
// --- Convert Workers Env to RouterEnv ----------------------------------------
|
2026-06-11 03:56:26 +07:00
|
|
|
|
2026-06-24 23:48:16 +07:00
|
|
|
function toRouterEnv(env: Env): RouterEnv {
|
|
|
|
|
return {
|
|
|
|
|
RELAY_TIMEOUT_MS: env.RELAY_TIMEOUT_MS,
|
|
|
|
|
RATE_LIMIT_MAX: env.RATE_LIMIT_MAX,
|
|
|
|
|
RATE_LIMIT_WINDOW_MS: env.RATE_LIMIT_WINDOW_MS,
|
|
|
|
|
API_KEY: env.API_KEY,
|
|
|
|
|
};
|
2026-06-11 03:56:26 +07:00
|
|
|
}
|
|
|
|
|
|
2026-06-24 23:48:16 +07:00
|
|
|
// --- Exported Worker Handler -------------------------------------------------
|
2026-06-10 21:38:04 +07:00
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
async fetch(req: Request, env: Env): Promise<Response> {
|
2026-06-24 23:48:16 +07:00
|
|
|
const routerEnv = toRouterEnv(env);
|
|
|
|
|
const clientIP = getClientIP(req);
|
2026-06-10 21:38:04 +07:00
|
|
|
|
2026-06-24 23:48:16 +07:00
|
|
|
// Static routes
|
|
|
|
|
if (new URL(req.url).pathname === "/health") {
|
|
|
|
|
const { handleHealth } = await import("./lib/router");
|
|
|
|
|
return handleHealth();
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
new URL(req.url).pathname === "/docs" ||
|
|
|
|
|
new URL(req.url).pathname === "/test"
|
|
|
|
|
) {
|
2026-06-24 18:18:49 +07:00
|
|
|
return new Response(getTestPageHtml(), {
|
|
|
|
|
status: 200,
|
|
|
|
|
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
|
|
|
});
|
2026-06-17 13:37:23 +07:00
|
|
|
}
|
2026-06-10 21:59:09 +07:00
|
|
|
if (
|
2026-06-24 23:48:16 +07:00
|
|
|
new URL(req.url).pathname === "/" &&
|
2026-06-10 21:59:09 +07:00
|
|
|
req.method === "GET" &&
|
|
|
|
|
!req.headers.get("x-relay-target")
|
|
|
|
|
) {
|
2026-06-24 23:48:16 +07:00
|
|
|
const { handleIndex } = await import("./lib/router");
|
2026-06-10 21:59:09 +07:00
|
|
|
return handleIndex();
|
|
|
|
|
}
|
2026-06-10 21:38:04 +07:00
|
|
|
|
2026-06-24 23:48:16 +07:00
|
|
|
// Delegate to shared router
|
|
|
|
|
const result = await handleRequest(req, routerEnv, clientIP, {
|
|
|
|
|
isWebSocketSupported: false,
|
|
|
|
|
skipProxyPool: true,
|
|
|
|
|
});
|
|
|
|
|
if (result !== undefined) return result;
|
2026-06-10 21:38:04 +07:00
|
|
|
|
2026-06-24 23:48:16 +07:00
|
|
|
return handleRelayPlain(req, routerEnv, clientIP);
|
2026-06-10 21:38:04 +07:00
|
|
|
},
|
|
|
|
|
};
|