fix: Vercel serverless function crash and await async completions routes
- Make generateDeviceFingerprint resilient to os.cpus() and os.hostname() returning empty or throwing in lambda sandboxes. - Await async handleChatCompletion and handleAnthropicMessages calls in route handlers to prevent unhandled promise rejections. - Catch runtime exceptions from completions and return clean HTTP 500 JSON error responses. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2171a01974
commit
d1d6f607b0
+20
-5
@@ -34,11 +34,26 @@ const EXPIRY_BUFFER_MS = 300_000; // 5 minutes
|
||||
* Uses Web Crypto API (available in Bun, Workers, and Node.js 20+).
|
||||
*/
|
||||
async function generateDeviceFingerprint(): Promise<string> {
|
||||
const hostname = os.hostname();
|
||||
const platform = process.platform;
|
||||
const arch = process.arch;
|
||||
const cpus = os.cpus();
|
||||
const cpuModel = cpus.length > 0 ? (cpus[0]?.model ?? "unknown") : "unknown";
|
||||
let hostname = "unknown";
|
||||
try {
|
||||
hostname = os.hostname() ?? "unknown";
|
||||
} catch {
|
||||
// OS module hostname not available in this sandbox
|
||||
}
|
||||
|
||||
const platform = process.platform ?? "unknown";
|
||||
const arch = process.arch ?? "unknown";
|
||||
|
||||
let cpuModel = "unknown";
|
||||
try {
|
||||
const cpus = os.cpus();
|
||||
if (cpus && cpus.length > 0) {
|
||||
cpuModel = cpus[0]?.model ?? "unknown";
|
||||
}
|
||||
} catch {
|
||||
// OS module cpus not available in this sandbox
|
||||
}
|
||||
|
||||
const username = process.env.USER ?? process.env.USERNAME ?? "unknown";
|
||||
|
||||
const raw = `${hostname}|${platform}|${arch}|${cpuModel}|${username}`;
|
||||
|
||||
+25
-9
@@ -9,7 +9,6 @@ import {
|
||||
createErrorResponse,
|
||||
createCorsPreflightResponse,
|
||||
getCorsHeaders,
|
||||
classifyFetchError,
|
||||
} from "./relay-utils";
|
||||
|
||||
import { checkBodySize } from "../middleware/body-limiter";
|
||||
@@ -615,11 +614,18 @@ export async function handleRequest(
|
||||
try {
|
||||
const body = await req.json();
|
||||
const sessionId = crypto.randomUUID();
|
||||
return handleChatCompletion(body, proxyPool!, sessionPool!, sessionId);
|
||||
} catch {
|
||||
return await handleChatCompletion(body, proxyPool!, sessionPool!, sessionId);
|
||||
} catch (err) {
|
||||
const isJsonError = err instanceof Error && (err.name === "SyntaxError" || err.message.includes("JSON"));
|
||||
if (isJsonError) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: { message: "Invalid JSON body", type: "invalid_request_error" } }),
|
||||
{ status: 400, headers: { "Content-Type": "application/json", ...getCorsHeaders() } },
|
||||
);
|
||||
}
|
||||
return new Response(
|
||||
JSON.stringify({ error: { message: "Invalid JSON body", type: "invalid_request_error" } }),
|
||||
{ status: 400, headers: { "Content-Type": "application/json", ...getCorsHeaders() } },
|
||||
JSON.stringify({ error: { message: err instanceof Error ? err.message : "Internal Server Error", type: "server_error" } }),
|
||||
{ status: 500, headers: { "Content-Type": "application/json", ...getCorsHeaders() } },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -634,14 +640,24 @@ export async function handleRequest(
|
||||
const body = await req.json();
|
||||
const sessionId = crypto.randomUUID();
|
||||
const anthropicVersion = req.headers.get("anthropic-version") ?? undefined;
|
||||
return handleAnthropicMessages(body, proxyPool!, sessionPool!, sessionId, undefined, anthropicVersion);
|
||||
} catch {
|
||||
return await handleAnthropicMessages(body, proxyPool!, sessionPool!, sessionId, undefined, anthropicVersion);
|
||||
} catch (err) {
|
||||
const isJsonError = err instanceof Error && (err.name === "SyntaxError" || err.message.includes("JSON"));
|
||||
if (isJsonError) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
type: "error",
|
||||
error: { message: "Invalid JSON body", type: "invalid_request_error" },
|
||||
}),
|
||||
{ status: 400, headers: { "Content-Type": "application/json", ...getCorsHeaders() } },
|
||||
);
|
||||
}
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
type: "error",
|
||||
error: { message: "Invalid JSON body", type: "invalid_request_error" },
|
||||
error: { message: err instanceof Error ? err.message : "Internal Server Error", type: "server_error" },
|
||||
}),
|
||||
{ status: 400, headers: { "Content-Type": "application/json", ...getCorsHeaders() } },
|
||||
{ status: 500, headers: { "Content-Type": "application/json", ...getCorsHeaders() } },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user