mirror of
https://github.com/Nezumi-2711/transfer-api.git
synced 2026-09-22 13:48:41 +00:00
Add optional WORKER_API_KEY support to src/worker.js
This commit is contained in:
+43
-2
@@ -1,11 +1,11 @@
|
|||||||
const DEFAULT_UPSTREAM_BASE_URL = "https://unlimited.surf";
|
const DEFAULT_UPSTREAM_BASE_URL = "https://unlimited.surf";
|
||||||
const DEFAULT_OPENAI_MODEL = "gateway-gpt-5.5";
|
const DEFAULT_OPENAI_MODEL = "gateway-gpt-5";
|
||||||
const DEFAULT_CLAUDE_MODEL = "claude-opus-4-7-20260101";
|
const DEFAULT_CLAUDE_MODEL = "claude-opus-4-7-20260101";
|
||||||
|
|
||||||
const CORS_HEADERS = {
|
const CORS_HEADERS = {
|
||||||
"Access-Control-Allow-Origin": "*",
|
"Access-Control-Allow-Origin": "*",
|
||||||
"Access-Control-Allow-Methods": "GET,POST,PUT,PATCH,DELETE,OPTIONS",
|
"Access-Control-Allow-Methods": "GET,POST,PUT,PATCH,DELETE,OPTIONS",
|
||||||
"Access-Control-Allow-Headers": "authorization,content-type,x-api-key,anthropic-version,anthropic-beta,openai-beta",
|
"Access-Control-Allow-Headers": "authorization,content-type,x-api-key,anthropic-api-key,anthropic-version,anthropic-beta,openai-beta",
|
||||||
"Access-Control-Expose-Headers": "content-type,request-id,x-request-id",
|
"Access-Control-Expose-Headers": "content-type,request-id,x-request-id",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -19,6 +19,9 @@ export default {
|
|||||||
const path = normalizePath(url.pathname);
|
const path = normalizePath(url.pathname);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const authError = validateWorkerApiKey(request, env);
|
||||||
|
if (authError) return authError;
|
||||||
|
|
||||||
if (path === "/" || path === "/health") {
|
if (path === "/" || path === "/health") {
|
||||||
return jsonResponse(serviceInfo(request, env));
|
return jsonResponse(serviceInfo(request, env));
|
||||||
}
|
}
|
||||||
@@ -818,6 +821,10 @@ function upstreamApiKey(request, env) {
|
|||||||
const key = optionalUpstreamApiKey(request, env);
|
const key = optionalUpstreamApiKey(request, env);
|
||||||
if (key) return key;
|
if (key) return key;
|
||||||
|
|
||||||
|
if (env.WORKER_API_KEY) {
|
||||||
|
throw new Error("Missing upstream API key. Set UNLIMITED_SURF_API_KEY when WORKER_API_KEY is enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
throw new Error("Missing upstream API key. Set UNLIMITED_SURF_API_KEY or pass Authorization: Bearer <key> / x-api-key: <key>.");
|
throw new Error("Missing upstream API key. Set UNLIMITED_SURF_API_KEY or pass Authorization: Bearer <key> / x-api-key: <key>.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -825,6 +832,28 @@ function optionalUpstreamApiKey(request, env) {
|
|||||||
const configured = env.UNLIMITED_SURF_API_KEY || env.API_KEY || env.AUTH_KEY;
|
const configured = env.UNLIMITED_SURF_API_KEY || env.API_KEY || env.AUTH_KEY;
|
||||||
if (configured) return configured;
|
if (configured) return configured;
|
||||||
|
|
||||||
|
if (env.WORKER_API_KEY) return "";
|
||||||
|
|
||||||
|
return clientApiKey(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateWorkerApiKey(request, env) {
|
||||||
|
const expected = env.WORKER_API_KEY;
|
||||||
|
if (!expected) return null;
|
||||||
|
|
||||||
|
const actual = clientApiKey(request);
|
||||||
|
if (actual && constantTimeEqual(actual, expected)) return null;
|
||||||
|
|
||||||
|
return jsonResponse({
|
||||||
|
error: {
|
||||||
|
message: "Invalid or missing Worker API key.",
|
||||||
|
type: "authentication_error",
|
||||||
|
code: "invalid_api_key",
|
||||||
|
},
|
||||||
|
}, { status: 401, headers: { "WWW-Authenticate": "Bearer" } });
|
||||||
|
}
|
||||||
|
|
||||||
|
function clientApiKey(request) {
|
||||||
const auth = request.headers.get("authorization") || "";
|
const auth = request.headers.get("authorization") || "";
|
||||||
if (/^bearer\s+/i.test(auth)) return auth.replace(/^bearer\s+/i, "").trim();
|
if (/^bearer\s+/i.test(auth)) return auth.replace(/^bearer\s+/i, "").trim();
|
||||||
|
|
||||||
@@ -832,6 +861,18 @@ function optionalUpstreamApiKey(request, env) {
|
|||||||
return xKey ? xKey.trim() : "";
|
return xKey ? xKey.trim() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function constantTimeEqual(actual, expected) {
|
||||||
|
const actualText = String(actual || "");
|
||||||
|
const expectedText = String(expected || "");
|
||||||
|
if (actualText.length !== expectedText.length) return false;
|
||||||
|
|
||||||
|
let diff = 0;
|
||||||
|
for (let i = 0; i < actualText.length; i += 1) {
|
||||||
|
diff |= actualText.charCodeAt(i) ^ expectedText.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return diff === 0;
|
||||||
|
}
|
||||||
|
|
||||||
function upstreamBase(env) {
|
function upstreamBase(env) {
|
||||||
return stripTrailingSlash(env.UPSTREAM_BASE_URL || DEFAULT_UPSTREAM_BASE_URL) + "/";
|
return stripTrailingSlash(env.UPSTREAM_BASE_URL || DEFAULT_UPSTREAM_BASE_URL) + "/";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user