( options: ModelsHandlerOptions )
| 1264 | * `x-api-key` and `anthropic-version` headers instead of a Bearer token. |
| 1265 | */ |
| 1266 | export function buildAnthropicModelsHandler( |
| 1267 | options: ModelsHandlerOptions |
| 1268 | ): RequestHandler { |
| 1269 | return async (req, res) => { |
| 1270 | const { workspaceId, gatewayId } = z |
| 1271 | .object({ |
| 1272 | workspaceId: z.string(), |
| 1273 | gatewayId: z.string(), |
| 1274 | }) |
| 1275 | .parse(req.params); |
| 1276 | |
| 1277 | const apiKey = |
| 1278 | (req.headers['x-api-key'] as string) ?? |
| 1279 | (req.headers.authorization ?? '').replace('Bearer ', ''); |
| 1280 | let modelApiKey = apiKey; |
| 1281 | const gatewayInfo = await getGatewayInfoCache(workspaceId, gatewayId); |
| 1282 | if (gatewayInfo?.modelApiKey) { |
| 1283 | await verifyUserApiKey(apiKey); |
| 1284 | modelApiKey = gatewayInfo.modelApiKey; |
| 1285 | } |
| 1286 | |
| 1287 | const baseUrl = |
| 1288 | options.isCustomRoute && gatewayInfo?.customModelBaseUrl |
| 1289 | ? gatewayInfo?.customModelBaseUrl |
| 1290 | : options.baseUrl; |
| 1291 | |
| 1292 | try { |
| 1293 | const queryString = new URLSearchParams( |
| 1294 | req.query as Record<string, string> |
| 1295 | ).toString(); |
| 1296 | const upstreamUrl = `${baseUrl}/models${ |
| 1297 | queryString ? `?${queryString}` : '' |
| 1298 | }`; |
| 1299 | const anthropicVersion = |
| 1300 | (req.headers['anthropic-version'] as string) || |
| 1301 | DEFAULT_ANTHROPIC_VERSION; |
| 1302 | |
| 1303 | const headers: Record<string, string> = { |
| 1304 | 'content-type': 'application/json', |
| 1305 | 'x-api-key': modelApiKey, |
| 1306 | 'anthropic-version': anthropicVersion, |
| 1307 | ...options.header?.(req), |
| 1308 | }; |
| 1309 | |
| 1310 | const betaHeader = req.headers['anthropic-beta']; |
| 1311 | if (betaHeader) { |
| 1312 | headers['anthropic-beta'] = String(betaHeader); |
| 1313 | } |
| 1314 | |
| 1315 | const upstreamResponse = await fetch(upstreamUrl, { |
| 1316 | method: 'GET', |
| 1317 | headers, |
| 1318 | }); |
| 1319 | |
| 1320 | const body = await upstreamResponse.text(); |
| 1321 | res.status(upstreamResponse.status); |
| 1322 | res.setHeader( |
| 1323 | 'content-type', |
no test coverage detected