diff --git a/scripts/routstr-daemon.ts b/scripts/routstr-daemon.ts index 45e9ca3..3b8bc11 100644 --- a/scripts/routstr-daemon.ts +++ b/scripts/routstr-daemon.ts @@ -206,6 +206,39 @@ async function saveRequestBody( return filename; } +function toForwardHeaders( + headers: IncomingMessage["headers"] +): Record { + const forwarded: Record = {}; + const hopByHop = new Set([ + "host", + "connection", + "content-length", + "transfer-encoding", + "keep-alive", + "proxy-authenticate", + "proxy-authorization", + "te", + "trailer", + "upgrade", + ]); + + for (const [key, value] of Object.entries(headers)) { + if (!key || hopByHop.has(key.toLowerCase())) { + continue; + } + if (Array.isArray(value)) { + forwarded[key] = value.join(", "); + continue; + } + if (typeof value === "string") { + forwarded[key] = value; + } + } + + return forwarded; +} + async function main(): Promise { const { port, provider, mode } = parseArgs(process.argv); @@ -355,11 +388,14 @@ async function main(): Promise { (req.headers["x-routstr-provider"] as string | undefined) || provider || undefined; + const forwardedHeaders = toForwardHeaders(req.headers); try { const response = await routeRequests({ modelId, requestBody, + path: url.pathname, + headers: forwardedHeaders, forcedProvider, debugLevel: "DEBUG", mode, diff --git a/sdk/routeRequests.ts b/sdk/routeRequests.ts index 3754356..43f9fd6 100644 --- a/sdk/routeRequests.ts +++ b/sdk/routeRequests.ts @@ -30,6 +30,8 @@ export interface RouteRequestOptions { requestBody: unknown; /** Optional: API path (defaults to /v1/chat/completions) */ path?: string; + /** Optional: request headers to forward upstream */ + headers?: Record; /** Optional: force a specific provider base URL */ forcedProvider?: string; /** Wallet adapter for Cashu operations */ @@ -86,6 +88,7 @@ async function resolveRouteRequestContext(options: RouteRequestOptions): Promise baseUrl: string; mintUrl: string; path: string; + headers: Record; modelId: string; proxiedBody: Record; }> { @@ -93,6 +96,7 @@ async function resolveRouteRequestContext(options: RouteRequestOptions): Promise modelId, requestBody, path = "/v1/chat/completions", + headers = {}, forcedProvider, walletAdapter, storageAdapter, @@ -216,6 +220,7 @@ async function resolveRouteRequestContext(options: RouteRequestOptions): Promise baseUrl, mintUrl, path, + headers, modelId, proxiedBody, }; @@ -227,7 +232,7 @@ async function resolveRouteRequestContext(options: RouteRequestOptions): Promise export async function routeRequests( options: RouteRequestOptions ): Promise { - const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = + const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options); try { @@ -235,6 +240,7 @@ export async function routeRequests( path, method: "POST", body: proxiedBody, + headers, baseUrl, mintUrl, modelId, @@ -262,7 +268,7 @@ export async function routeRequestsToNodeResponse( options: RouteRequestToNodeResponseOptions ): Promise { const { res } = options; - const { client, baseUrl, mintUrl, path, modelId, proxiedBody } = + const { client, baseUrl, mintUrl, path, headers, modelId, proxiedBody } = await resolveRouteRequestContext(options); try { @@ -270,6 +276,7 @@ export async function routeRequestsToNodeResponse( path, method: "POST", body: proxiedBody, + headers, baseUrl, mintUrl, modelId,