mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-05-22 05:30:19 +09:00

Adds support for using models hosted on AWS Bedrock, specifically Anthropic Claude models. Key changes: - Added '@aws-sdk/client-bedrock-runtime' dependency. - Updated constants, server config, and auth logic for Bedrock. - Implemented backend API handler () to communicate with the Bedrock API, handling streaming and non-streaming responses, and formatting output to be OpenAI compatible. - Updated dynamic API router () to dispatch requests to the Bedrock handler. - Created frontend client () and updated client factory (). - Updated with necessary Bedrock environment variables (AWS keys, region, enable flag) and an example for using to alias Bedrock models.
130 lines
3.9 KiB
TypeScript
130 lines
3.9 KiB
TypeScript
import { NextRequest } from "next/server";
|
|
import { getServerSideConfig } from "../config/server";
|
|
import md5 from "spark-md5";
|
|
import { ACCESS_CODE_PREFIX, ModelProvider } from "../constant";
|
|
|
|
function getIP(req: NextRequest) {
|
|
let ip = req.ip ?? req.headers.get("x-real-ip");
|
|
const forwardedFor = req.headers.get("x-forwarded-for");
|
|
|
|
if (!ip && forwardedFor) {
|
|
ip = forwardedFor.split(",").at(0) ?? "";
|
|
}
|
|
|
|
return ip;
|
|
}
|
|
|
|
function parseApiKey(bearToken: string) {
|
|
const token = bearToken.trim().replaceAll("Bearer ", "").trim();
|
|
const isApiKey = !token.startsWith(ACCESS_CODE_PREFIX);
|
|
|
|
return {
|
|
accessCode: isApiKey ? "" : token.slice(ACCESS_CODE_PREFIX.length),
|
|
apiKey: isApiKey ? token : "",
|
|
};
|
|
}
|
|
|
|
export function auth(req: NextRequest, modelProvider: ModelProvider) {
|
|
const authToken = req.headers.get("Authorization") ?? "";
|
|
|
|
// check if it is openai api key or user token
|
|
const { accessCode, apiKey } = parseApiKey(authToken);
|
|
|
|
const hashedCode = md5.hash(accessCode ?? "").trim();
|
|
|
|
const serverConfig = getServerSideConfig();
|
|
console.log("[Auth] allowed hashed codes: ", [...serverConfig.codes]);
|
|
console.log("[Auth] got access code:", accessCode);
|
|
console.log("[Auth] hashed access code:", hashedCode);
|
|
console.log("[User IP] ", getIP(req));
|
|
console.log("[Time] ", new Date().toLocaleString());
|
|
|
|
if (serverConfig.needCode && !serverConfig.codes.has(hashedCode) && !apiKey) {
|
|
return {
|
|
error: true,
|
|
msg: !accessCode ? "empty access code" : "wrong access code",
|
|
};
|
|
}
|
|
|
|
if (serverConfig.hideUserApiKey && !!apiKey) {
|
|
return {
|
|
error: true,
|
|
msg: "you are not allowed to access with your own api key",
|
|
};
|
|
}
|
|
|
|
// if user does not provide an api key, inject system api key
|
|
if (!apiKey) {
|
|
const serverConfig = getServerSideConfig();
|
|
let systemApiKey: string | undefined;
|
|
|
|
switch (modelProvider) {
|
|
case ModelProvider.Stability:
|
|
systemApiKey = serverConfig.stabilityApiKey;
|
|
break;
|
|
case ModelProvider.GeminiPro:
|
|
systemApiKey = serverConfig.googleApiKey;
|
|
break;
|
|
case ModelProvider.Claude:
|
|
systemApiKey = serverConfig.anthropicApiKey;
|
|
break;
|
|
case ModelProvider.Doubao:
|
|
systemApiKey = serverConfig.bytedanceApiKey;
|
|
break;
|
|
case ModelProvider.Ernie:
|
|
systemApiKey = serverConfig.baiduApiKey;
|
|
break;
|
|
case ModelProvider.Qwen:
|
|
systemApiKey = serverConfig.alibabaApiKey;
|
|
break;
|
|
case ModelProvider.Moonshot:
|
|
systemApiKey = serverConfig.moonshotApiKey;
|
|
break;
|
|
case ModelProvider.Iflytek:
|
|
systemApiKey =
|
|
serverConfig.iflytekApiKey + ":" + serverConfig.iflytekApiSecret;
|
|
break;
|
|
case ModelProvider.DeepSeek:
|
|
systemApiKey = serverConfig.deepseekApiKey;
|
|
break;
|
|
case ModelProvider.XAI:
|
|
systemApiKey = serverConfig.xaiApiKey;
|
|
break;
|
|
case ModelProvider.ChatGLM:
|
|
systemApiKey = serverConfig.chatglmApiKey;
|
|
break;
|
|
case ModelProvider.SiliconFlow:
|
|
systemApiKey = serverConfig.siliconFlowApiKey;
|
|
break;
|
|
case ModelProvider.Bedrock:
|
|
console.log(
|
|
"[Auth] Using AWS credentials for Bedrock, no API key override.",
|
|
);
|
|
return { error: false };
|
|
case ModelProvider.GPT:
|
|
default:
|
|
if (req.nextUrl.pathname.includes("azure/deployments")) {
|
|
systemApiKey = serverConfig.azureApiKey;
|
|
} else {
|
|
systemApiKey = serverConfig.apiKey;
|
|
}
|
|
}
|
|
|
|
if (systemApiKey) {
|
|
console.log("[Auth] use system api key");
|
|
req.headers.set("Authorization", `Bearer ${systemApiKey}`);
|
|
} else {
|
|
console.log(
|
|
"[Auth] admin did not provide an api key for provider:",
|
|
modelProvider,
|
|
);
|
|
}
|
|
} else {
|
|
console.log("[Auth] use user api key");
|
|
}
|
|
|
|
return {
|
|
error: false,
|
|
};
|
|
}
|