support authentication via APIKEY configuration

This commit is contained in:
jinhui.li
2025-07-17 12:49:14 +08:00
parent f7f6943d31
commit 49502e1534
9 changed files with 69 additions and 4 deletions

View File

@@ -5,6 +5,7 @@ import { join } from "path";
import { initConfig, initDir } from "./utils";
import { createServer } from "./server";
import { router } from "./utils/router";
import { apiKeyAuth } from "./middleware/auth";
import {
cleanupPidFile,
isServiceRunning,
@@ -46,6 +47,14 @@ async function run(options: RunOptions = {}) {
await initializeClaudeConfig();
await initDir();
const config = await initConfig();
let HOST = config.HOST;
if (config.HOST && !config.APIKEY) {
HOST = "127.0.0.1";
console.warn(
"⚠️ API key is not set. HOST is forced to 127.0.0.1."
);
}
const port = options.port || 3456;
@@ -64,6 +73,7 @@ async function run(options: RunOptions = {}) {
cleanupPidFile();
process.exit(0);
});
console.log(HOST)
// Use port from environment variable if set (for background process)
const servicePort = process.env.SERVICE_PORT
@@ -74,6 +84,7 @@ async function run(options: RunOptions = {}) {
initialConfig: {
// ...config,
providers: config.Providers || config.providers,
HOST: HOST,
PORT: servicePort,
LOG_FILE: join(
homedir(),
@@ -82,6 +93,7 @@ async function run(options: RunOptions = {}) {
),
},
});
server.addHook("preHandler", apiKeyAuth(config));
server.addHook("preHandler", async (req, reply) =>
router(req, reply, config)
);

33
src/middleware/auth.ts Normal file
View File

@@ -0,0 +1,33 @@
import { FastifyRequest, FastifyReply } from "fastify";
export const apiKeyAuth =
(config: any) =>
(req: FastifyRequest, reply: FastifyReply, done: () => void) => {
if (["/", "/health"].includes(req.url)) {
return done();
}
const apiKey = config.APIKEY;
if (!apiKey) {
return done();
}
const authKey: string =
req.headers.authorization || req.headers["x-api-key"];
if (!authKey) {
reply.status(401).send("APIKEY is missing");
return;
}
let token = "";
if (authKey.startsWith("Bearer")) {
token = authKey.split(" ")[1];
} else {
token = authKey;
}
if (token !== apiKey) {
reply.status(401).send("Invalid API key");
return;
}
done();
};

View File

@@ -4,9 +4,11 @@ import {
decrementReferenceCount,
} from "./processCheck";
import { closeService } from "./close";
import { readConfigFile } from ".";
export async function executeCodeCommand(args: string[] = []) {
// Set environment variables
const config = await readConfigFile();
const env = {
...process.env,
ANTHROPIC_AUTH_TOKEN: "test",
@@ -14,6 +16,11 @@ export async function executeCodeCommand(args: string[] = []) {
API_TIMEOUT_MS: "600000",
};
if (config?.APIKEY) {
env.ANTHROPIC_API_KEY = config.APIKEY;
delete env.ANTHROPIC_AUTH_TOKEN;
}
// Increment reference count when command starts
incrementReferenceCount();

View File

@@ -48,7 +48,7 @@ export const readConfigFile = async () => {
return JSON.parse(config);
} catch {
const name = await question("Enter Provider Name: ");
const apiKey = await question("Enter Provider API KEY: ");
const APIKEY = await question("Enter Provider API KEY: ");
const baseUrl = await question("Enter Provider URL: ");
const model = await question("Enter MODEL Name: ");
const config = Object.assign({}, DEFAULT_CONFIG, {
@@ -56,7 +56,7 @@ export const readConfigFile = async () => {
{
name,
api_base_url: baseUrl,
api_key: apiKey,
api_key: APIKEY,
models: [model],
},
],