From 388156e91683caca877eb631a3e119e029a0486b Mon Sep 17 00:00:00 2001 From: Wing900 <2249381074@qq.com> Date: Tue, 17 Mar 2026 00:11:50 +0800 Subject: [PATCH 1/2] Fix SSRF/credential forwarding via client-supplied baseUrl --- app/api/chat/route.ts | 14 ++++++++++++-- app/api/generate/image/route.ts | 12 ++++++++++-- app/api/generate/tts/route.ts | 14 +++++++++++--- app/api/generate/video/route.ts | 12 ++++++++++-- app/api/parse-pdf/route.ts | 13 +++++++++++-- app/api/transcription/route.ts | 13 +++++++++++-- app/api/verify-image-provider/route.ts | 12 ++++++++++-- app/api/verify-pdf-provider/route.ts | 18 ++++++++++++++++-- app/api/verify-video-provider/route.ts | 12 ++++++++++-- lib/server/resolve-model.ts | 14 ++++++++++++-- 10 files changed, 113 insertions(+), 21 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 801f465..4edf2b1 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -20,6 +20,7 @@ import type { StatelessChatRequest, StatelessEvent } from '@/lib/types/chat'; import type { ThinkingConfig } from '@/lib/types/provider'; import { apiError } from '@/lib/server/api-response'; import { createLogger } from '@/lib/logger'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('Chat API'); // Allow streaming responses up to 60 seconds @@ -63,8 +64,17 @@ export async function POST(req: NextRequest) { // Resolve API key: client > server > empty const modelString = body.model || 'gpt-4o-mini'; const { providerId, modelId } = parseModelString(modelString); - const effectiveApiKey = resolveApiKey(providerId, body.apiKey); - const effectiveBaseUrl = resolveBaseUrl(providerId, body.baseUrl); + + const clientBaseUrl = body.baseUrl || undefined; + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + + const effectiveApiKey = clientBaseUrl ? body.apiKey || '' : resolveApiKey(providerId, body.apiKey); + const effectiveBaseUrl = clientBaseUrl ? clientBaseUrl : resolveBaseUrl(providerId, body.baseUrl); const proxy = resolveProxy(providerId); if (!effectiveApiKey) { diff --git a/app/api/generate/image/route.ts b/app/api/generate/image/route.ts index 1c95618..563e01e 100644 --- a/app/api/generate/image/route.ts +++ b/app/api/generate/image/route.ts @@ -21,6 +21,7 @@ import { resolveImageApiKey, resolveImageBaseUrl } from '@/lib/server/provider-c import type { ImageProviderId, ImageGenerationOptions } from '@/lib/media/types'; import { createLogger } from '@/lib/logger'; import { apiError, apiSuccess } from '@/lib/server/api-response'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('ImageGeneration API'); @@ -39,7 +40,14 @@ export async function POST(request: NextRequest) { const clientBaseUrl = request.headers.get('x-base-url') || undefined; const clientModel = request.headers.get('x-image-model') || undefined; - const apiKey = resolveImageApiKey(providerId, clientApiKey); + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + + const apiKey = clientBaseUrl ? clientApiKey || '' : resolveImageApiKey(providerId, clientApiKey); if (!apiKey) { return apiError( 'MISSING_API_KEY', @@ -48,7 +56,7 @@ export async function POST(request: NextRequest) { ); } - const baseUrl = resolveImageBaseUrl(providerId, clientBaseUrl); + const baseUrl = clientBaseUrl ? clientBaseUrl : resolveImageBaseUrl(providerId, clientBaseUrl); // Resolve dimensions from aspect ratio if not explicitly set if (!body.width && !body.height && body.aspectRatio) { diff --git a/app/api/generate/tts/route.ts b/app/api/generate/tts/route.ts index 4ae820c..26fa054 100644 --- a/app/api/generate/tts/route.ts +++ b/app/api/generate/tts/route.ts @@ -13,6 +13,7 @@ import { resolveTTSApiKey, resolveTTSBaseUrl } from '@/lib/server/provider-confi import type { TTSProviderId } from '@/lib/audio/types'; import { createLogger } from '@/lib/logger'; import { apiError, apiSuccess } from '@/lib/server/api-response'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('TTS API'); @@ -45,9 +46,16 @@ export async function POST(req: NextRequest) { return apiError('INVALID_REQUEST', 400, 'browser-native-tts must be handled client-side'); } - // Resolve API key and base URL (server-side fallback) - const apiKey = resolveTTSApiKey(ttsProviderId, ttsApiKey || undefined); - const baseUrl = resolveTTSBaseUrl(ttsProviderId, ttsBaseUrl || undefined); + const clientBaseUrl = ttsBaseUrl || undefined; + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + + const apiKey = clientBaseUrl ? ttsApiKey || '' : resolveTTSApiKey(ttsProviderId, ttsApiKey || undefined); + const baseUrl = clientBaseUrl ? clientBaseUrl : resolveTTSBaseUrl(ttsProviderId, ttsBaseUrl || undefined); // Build TTS config const config = { diff --git a/app/api/generate/video/route.ts b/app/api/generate/video/route.ts index c852666..5198aeb 100644 --- a/app/api/generate/video/route.ts +++ b/app/api/generate/video/route.ts @@ -22,6 +22,7 @@ import { resolveVideoApiKey, resolveVideoBaseUrl } from '@/lib/server/provider-c import type { VideoProviderId, VideoGenerationOptions } from '@/lib/media/types'; import { createLogger } from '@/lib/logger'; import { apiError, apiSuccess } from '@/lib/server/api-response'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('VideoGeneration API'); @@ -40,7 +41,14 @@ export async function POST(request: NextRequest) { const clientBaseUrl = request.headers.get('x-base-url') || undefined; const clientModel = request.headers.get('x-video-model') || undefined; - const apiKey = resolveVideoApiKey(providerId, clientApiKey); + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + + const apiKey = clientBaseUrl ? clientApiKey || '' : resolveVideoApiKey(providerId, clientApiKey); if (!apiKey) { return apiError( 'MISSING_API_KEY', @@ -49,7 +57,7 @@ export async function POST(request: NextRequest) { ); } - const baseUrl = resolveVideoBaseUrl(providerId, clientBaseUrl); + const baseUrl = clientBaseUrl ? clientBaseUrl : resolveVideoBaseUrl(providerId, clientBaseUrl); // Normalize options against provider capabilities const options = normalizeVideoOptions(providerId, body); diff --git a/app/api/parse-pdf/route.ts b/app/api/parse-pdf/route.ts index 2a6e5ab..1612a04 100644 --- a/app/api/parse-pdf/route.ts +++ b/app/api/parse-pdf/route.ts @@ -5,6 +5,7 @@ import type { PDFProviderId } from '@/lib/pdf/types'; import type { ParsedPdfContent } from '@/lib/types/pdf'; import { createLogger } from '@/lib/logger'; import { apiError, apiSuccess } from '@/lib/server/api-response'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('Parse PDF'); export async function POST(req: NextRequest) { @@ -32,10 +33,18 @@ export async function POST(req: NextRequest) { // providerId is required from the client — no server-side store to fall back to const effectiveProviderId = providerId || ('unpdf' as PDFProviderId); + const clientBaseUrl = baseUrl || undefined; + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + const config = { providerId: effectiveProviderId, - apiKey: resolvePDFApiKey(effectiveProviderId, apiKey || undefined), - baseUrl: resolvePDFBaseUrl(effectiveProviderId, baseUrl || undefined), + apiKey: clientBaseUrl ? apiKey || '' : resolvePDFApiKey(effectiveProviderId, apiKey || undefined), + baseUrl: clientBaseUrl ? clientBaseUrl : resolvePDFBaseUrl(effectiveProviderId, baseUrl || undefined), }; // Convert PDF to buffer diff --git a/app/api/transcription/route.ts b/app/api/transcription/route.ts index d496ff1..d1dbdfa 100644 --- a/app/api/transcription/route.ts +++ b/app/api/transcription/route.ts @@ -4,6 +4,7 @@ import { resolveASRApiKey, resolveASRBaseUrl } from '@/lib/server/provider-confi import type { ASRProviderId } from '@/lib/audio/types'; import { createLogger } from '@/lib/logger'; import { apiError, apiSuccess } from '@/lib/server/api-response'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('Transcription'); export const maxDuration = 60; @@ -24,11 +25,19 @@ export async function POST(req: NextRequest) { // providerId is required from the client — no server-side store to fall back to const effectiveProviderId = providerId || ('openai-whisper' as ASRProviderId); + const clientBaseUrl = baseUrl || undefined; + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + const config = { providerId: effectiveProviderId, language: language || 'auto', - apiKey: resolveASRApiKey(effectiveProviderId, apiKey || undefined), - baseUrl: resolveASRBaseUrl(effectiveProviderId, baseUrl || undefined), + apiKey: clientBaseUrl ? apiKey || '' : resolveASRApiKey(effectiveProviderId, apiKey || undefined), + baseUrl: clientBaseUrl ? clientBaseUrl : resolveASRBaseUrl(effectiveProviderId, baseUrl || undefined), }; // Convert audio file to buffer diff --git a/app/api/verify-image-provider/route.ts b/app/api/verify-image-provider/route.ts index 75dc8fd..b9827b1 100644 --- a/app/api/verify-image-provider/route.ts +++ b/app/api/verify-image-provider/route.ts @@ -20,6 +20,7 @@ import { resolveImageApiKey, resolveImageBaseUrl } from '@/lib/server/provider-c import type { ImageProviderId } from '@/lib/media/types'; import { apiError, apiSuccess } from '@/lib/server/api-response'; import { createLogger } from '@/lib/logger'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('VerifyImageProvider'); @@ -30,8 +31,15 @@ export async function POST(request: NextRequest) { const clientApiKey = request.headers.get('x-api-key') || undefined; const clientBaseUrl = request.headers.get('x-base-url') || undefined; - const apiKey = resolveImageApiKey(providerId, clientApiKey); - const baseUrl = resolveImageBaseUrl(providerId, clientBaseUrl); + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + + const apiKey = clientBaseUrl ? clientApiKey || '' : resolveImageApiKey(providerId, clientApiKey); + const baseUrl = clientBaseUrl ? clientBaseUrl : resolveImageBaseUrl(providerId, clientBaseUrl); if (!apiKey) { return apiError('MISSING_API_KEY', 400, 'No API key configured'); diff --git a/app/api/verify-pdf-provider/route.ts b/app/api/verify-pdf-provider/route.ts index 97b3e0b..2b3a58f 100644 --- a/app/api/verify-pdf-provider/route.ts +++ b/app/api/verify-pdf-provider/route.ts @@ -2,6 +2,7 @@ import { NextRequest } from 'next/server'; import { createLogger } from '@/lib/logger'; import { apiError, apiSuccess } from '@/lib/server/api-response'; import { resolvePDFApiKey, resolvePDFBaseUrl } from '@/lib/server/provider-config'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('Verify PDF Provider'); @@ -13,12 +14,20 @@ export async function POST(req: NextRequest) { return apiError('MISSING_REQUIRED_FIELD', 400, 'Provider ID is required'); } - const resolvedBaseUrl = resolvePDFBaseUrl(providerId, baseUrl); + const clientBaseUrl = (baseUrl as string | undefined) || undefined; + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + + const resolvedBaseUrl = clientBaseUrl ? clientBaseUrl : resolvePDFBaseUrl(providerId, baseUrl); if (!resolvedBaseUrl) { return apiError('MISSING_REQUIRED_FIELD', 400, 'Base URL is required'); } - const resolvedApiKey = resolvePDFApiKey(providerId, apiKey); + const resolvedApiKey = clientBaseUrl ? (apiKey as string | undefined) || '' : resolvePDFApiKey(providerId, apiKey); const headers: Record = {}; if (resolvedApiKey) { @@ -28,8 +37,13 @@ export async function POST(req: NextRequest) { const response = await fetch(resolvedBaseUrl, { headers, signal: AbortSignal.timeout(10000), + redirect: 'manual', }); + if (response.status >= 300 && response.status < 400) { + return apiError('REDIRECT_NOT_ALLOWED', 403, 'Redirects are not allowed'); + } + // MinerU's FastAPI root returns 404 (no root route), but the server is reachable. // Any HTTP response (including 404) means the server is up. return apiSuccess({ diff --git a/app/api/verify-video-provider/route.ts b/app/api/verify-video-provider/route.ts index d11f971..6635157 100644 --- a/app/api/verify-video-provider/route.ts +++ b/app/api/verify-video-provider/route.ts @@ -20,6 +20,7 @@ import { resolveVideoApiKey, resolveVideoBaseUrl } from '@/lib/server/provider-c import type { VideoProviderId } from '@/lib/media/types'; import { apiError, apiSuccess } from '@/lib/server/api-response'; import { createLogger } from '@/lib/logger'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; const log = createLogger('VerifyVideoProvider'); @@ -30,8 +31,15 @@ export async function POST(request: NextRequest) { const clientApiKey = request.headers.get('x-api-key') || undefined; const clientBaseUrl = request.headers.get('x-base-url') || undefined; - const apiKey = resolveVideoApiKey(providerId, clientApiKey); - const baseUrl = resolveVideoBaseUrl(providerId, clientBaseUrl); + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + return apiError('INVALID_URL', 403, ssrfError); + } + } + + const apiKey = clientBaseUrl ? clientApiKey || '' : resolveVideoApiKey(providerId, clientApiKey); + const baseUrl = clientBaseUrl ? clientBaseUrl : resolveVideoBaseUrl(providerId, clientBaseUrl); if (!apiKey) { return apiError('MISSING_API_KEY', 400, 'No API key configured'); diff --git a/lib/server/resolve-model.ts b/lib/server/resolve-model.ts index 02c5084..69863ff 100644 --- a/lib/server/resolve-model.ts +++ b/lib/server/resolve-model.ts @@ -8,6 +8,7 @@ import type { NextRequest } from 'next/server'; import { getModel, parseModelString, type ModelWithInfo } from '@/lib/ai/providers'; import { resolveApiKey, resolveBaseUrl, resolveProxy } from '@/lib/server/provider-config'; +import { validateUrlForSSRF } from '@/lib/server/ssrf-guard'; export interface ResolvedModel extends ModelWithInfo { /** Original model string (e.g. "openai/gpt-4o-mini") */ @@ -28,8 +29,17 @@ export function resolveModel(params: { }): ResolvedModel { const modelString = params.modelString || process.env.DEFAULT_MODEL || 'gpt-4o-mini'; const { providerId, modelId } = parseModelString(modelString); - const apiKey = resolveApiKey(providerId, params.apiKey || ''); - const baseUrl = resolveBaseUrl(providerId, params.baseUrl); + + const clientBaseUrl = params.baseUrl || undefined; + if (clientBaseUrl && process.env.NODE_ENV === 'production') { + const ssrfError = validateUrlForSSRF(clientBaseUrl); + if (ssrfError) { + throw new Error(ssrfError); + } + } + + const apiKey = clientBaseUrl ? params.apiKey || '' : resolveApiKey(providerId, params.apiKey || ''); + const baseUrl = clientBaseUrl ? clientBaseUrl : resolveBaseUrl(providerId, params.baseUrl); const proxy = resolveProxy(providerId); const { model, modelInfo } = getModel({ providerId, From bd6d2d5a681d5d5382d242b362fd9c7928cd5e2c Mon Sep 17 00:00:00 2001 From: Wing900 <2249381074@qq.com> Date: Tue, 17 Mar 2026 09:47:06 +0800 Subject: [PATCH 2/2] chore: format SSRF fix --- app/api/chat/route.ts | 8 ++++++-- app/api/generate/image/route.ts | 4 +++- app/api/generate/tts/route.ts | 8 ++++++-- app/api/generate/video/route.ts | 4 +++- app/api/parse-pdf/route.ts | 8 ++++++-- app/api/transcription/route.ts | 8 ++++++-- app/api/verify-image-provider/route.ts | 4 +++- app/api/verify-pdf-provider/route.ts | 4 +++- app/api/verify-video-provider/route.ts | 4 +++- lib/server/resolve-model.ts | 4 +++- 10 files changed, 42 insertions(+), 14 deletions(-) diff --git a/app/api/chat/route.ts b/app/api/chat/route.ts index 4edf2b1..c37817d 100644 --- a/app/api/chat/route.ts +++ b/app/api/chat/route.ts @@ -73,8 +73,12 @@ export async function POST(req: NextRequest) { } } - const effectiveApiKey = clientBaseUrl ? body.apiKey || '' : resolveApiKey(providerId, body.apiKey); - const effectiveBaseUrl = clientBaseUrl ? clientBaseUrl : resolveBaseUrl(providerId, body.baseUrl); + const effectiveApiKey = clientBaseUrl + ? body.apiKey || '' + : resolveApiKey(providerId, body.apiKey); + const effectiveBaseUrl = clientBaseUrl + ? clientBaseUrl + : resolveBaseUrl(providerId, body.baseUrl); const proxy = resolveProxy(providerId); if (!effectiveApiKey) { diff --git a/app/api/generate/image/route.ts b/app/api/generate/image/route.ts index 563e01e..a3b8c3a 100644 --- a/app/api/generate/image/route.ts +++ b/app/api/generate/image/route.ts @@ -47,7 +47,9 @@ export async function POST(request: NextRequest) { } } - const apiKey = clientBaseUrl ? clientApiKey || '' : resolveImageApiKey(providerId, clientApiKey); + const apiKey = clientBaseUrl + ? clientApiKey || '' + : resolveImageApiKey(providerId, clientApiKey); if (!apiKey) { return apiError( 'MISSING_API_KEY', diff --git a/app/api/generate/tts/route.ts b/app/api/generate/tts/route.ts index 26fa054..542f105 100644 --- a/app/api/generate/tts/route.ts +++ b/app/api/generate/tts/route.ts @@ -54,8 +54,12 @@ export async function POST(req: NextRequest) { } } - const apiKey = clientBaseUrl ? ttsApiKey || '' : resolveTTSApiKey(ttsProviderId, ttsApiKey || undefined); - const baseUrl = clientBaseUrl ? clientBaseUrl : resolveTTSBaseUrl(ttsProviderId, ttsBaseUrl || undefined); + const apiKey = clientBaseUrl + ? ttsApiKey || '' + : resolveTTSApiKey(ttsProviderId, ttsApiKey || undefined); + const baseUrl = clientBaseUrl + ? clientBaseUrl + : resolveTTSBaseUrl(ttsProviderId, ttsBaseUrl || undefined); // Build TTS config const config = { diff --git a/app/api/generate/video/route.ts b/app/api/generate/video/route.ts index 5198aeb..7ec3399 100644 --- a/app/api/generate/video/route.ts +++ b/app/api/generate/video/route.ts @@ -48,7 +48,9 @@ export async function POST(request: NextRequest) { } } - const apiKey = clientBaseUrl ? clientApiKey || '' : resolveVideoApiKey(providerId, clientApiKey); + const apiKey = clientBaseUrl + ? clientApiKey || '' + : resolveVideoApiKey(providerId, clientApiKey); if (!apiKey) { return apiError( 'MISSING_API_KEY', diff --git a/app/api/parse-pdf/route.ts b/app/api/parse-pdf/route.ts index 1612a04..94feff5 100644 --- a/app/api/parse-pdf/route.ts +++ b/app/api/parse-pdf/route.ts @@ -43,8 +43,12 @@ export async function POST(req: NextRequest) { const config = { providerId: effectiveProviderId, - apiKey: clientBaseUrl ? apiKey || '' : resolvePDFApiKey(effectiveProviderId, apiKey || undefined), - baseUrl: clientBaseUrl ? clientBaseUrl : resolvePDFBaseUrl(effectiveProviderId, baseUrl || undefined), + apiKey: clientBaseUrl + ? apiKey || '' + : resolvePDFApiKey(effectiveProviderId, apiKey || undefined), + baseUrl: clientBaseUrl + ? clientBaseUrl + : resolvePDFBaseUrl(effectiveProviderId, baseUrl || undefined), }; // Convert PDF to buffer diff --git a/app/api/transcription/route.ts b/app/api/transcription/route.ts index d1dbdfa..c3bf5a2 100644 --- a/app/api/transcription/route.ts +++ b/app/api/transcription/route.ts @@ -36,8 +36,12 @@ export async function POST(req: NextRequest) { const config = { providerId: effectiveProviderId, language: language || 'auto', - apiKey: clientBaseUrl ? apiKey || '' : resolveASRApiKey(effectiveProviderId, apiKey || undefined), - baseUrl: clientBaseUrl ? clientBaseUrl : resolveASRBaseUrl(effectiveProviderId, baseUrl || undefined), + apiKey: clientBaseUrl + ? apiKey || '' + : resolveASRApiKey(effectiveProviderId, apiKey || undefined), + baseUrl: clientBaseUrl + ? clientBaseUrl + : resolveASRBaseUrl(effectiveProviderId, baseUrl || undefined), }; // Convert audio file to buffer diff --git a/app/api/verify-image-provider/route.ts b/app/api/verify-image-provider/route.ts index b9827b1..9ec0446 100644 --- a/app/api/verify-image-provider/route.ts +++ b/app/api/verify-image-provider/route.ts @@ -38,7 +38,9 @@ export async function POST(request: NextRequest) { } } - const apiKey = clientBaseUrl ? clientApiKey || '' : resolveImageApiKey(providerId, clientApiKey); + const apiKey = clientBaseUrl + ? clientApiKey || '' + : resolveImageApiKey(providerId, clientApiKey); const baseUrl = clientBaseUrl ? clientBaseUrl : resolveImageBaseUrl(providerId, clientBaseUrl); if (!apiKey) { diff --git a/app/api/verify-pdf-provider/route.ts b/app/api/verify-pdf-provider/route.ts index 2b3a58f..3b0ac3f 100644 --- a/app/api/verify-pdf-provider/route.ts +++ b/app/api/verify-pdf-provider/route.ts @@ -27,7 +27,9 @@ export async function POST(req: NextRequest) { return apiError('MISSING_REQUIRED_FIELD', 400, 'Base URL is required'); } - const resolvedApiKey = clientBaseUrl ? (apiKey as string | undefined) || '' : resolvePDFApiKey(providerId, apiKey); + const resolvedApiKey = clientBaseUrl + ? (apiKey as string | undefined) || '' + : resolvePDFApiKey(providerId, apiKey); const headers: Record = {}; if (resolvedApiKey) { diff --git a/app/api/verify-video-provider/route.ts b/app/api/verify-video-provider/route.ts index 6635157..69d4d33 100644 --- a/app/api/verify-video-provider/route.ts +++ b/app/api/verify-video-provider/route.ts @@ -38,7 +38,9 @@ export async function POST(request: NextRequest) { } } - const apiKey = clientBaseUrl ? clientApiKey || '' : resolveVideoApiKey(providerId, clientApiKey); + const apiKey = clientBaseUrl + ? clientApiKey || '' + : resolveVideoApiKey(providerId, clientApiKey); const baseUrl = clientBaseUrl ? clientBaseUrl : resolveVideoBaseUrl(providerId, clientBaseUrl); if (!apiKey) { diff --git a/lib/server/resolve-model.ts b/lib/server/resolve-model.ts index 69863ff..71b9500 100644 --- a/lib/server/resolve-model.ts +++ b/lib/server/resolve-model.ts @@ -38,7 +38,9 @@ export function resolveModel(params: { } } - const apiKey = clientBaseUrl ? params.apiKey || '' : resolveApiKey(providerId, params.apiKey || ''); + const apiKey = clientBaseUrl + ? params.apiKey || '' + : resolveApiKey(providerId, params.apiKey || ''); const baseUrl = clientBaseUrl ? clientBaseUrl : resolveBaseUrl(providerId, params.baseUrl); const proxy = resolveProxy(providerId); const { model, modelInfo } = getModel({