Skip to content

Commit

Permalink
feat: 支持多 key 负载均衡
Browse files Browse the repository at this point in the history
  • Loading branch information
muxiangqiu committed Apr 18, 2023
1 parent ce1808f commit 8a56981
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ package-backup.json
.Trash-*
packages/plugin/typedoc
plugins
malagu-secret.yml
2 changes: 1 addition & 1 deletion malagu-remote.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
openAIProxy:
defaultAPIKey: ${{env.OPENAI_PROXY_DEFAULT_API_KEY}}
defaultAPIKeys: ${{env.OPENAI_PROXY_DEFAULT_API_KEY}}
malagu:
web:
cors:
Expand Down
1 change: 1 addition & 0 deletions malagu.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mode: secret
23 changes: 20 additions & 3 deletions src/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Middleware, CORS_MIDDLEWARE_PRIORITY, Context } from '@malagu/web/lib/n
import { Component, PostConstruct, Value } from '@malagu/core';

interface OpenAIProxyOptions {
defaultAPIKey?: string;
defaultAPIKeys?: string | string[];
}

@Component(Middleware)
Expand All @@ -15,16 +15,33 @@ export class CodingProxyMiddleware implements Middleware {
@Value('openAIProxy')
protected readonly options?: OpenAIProxyOptions;

protected apiKeys: string[];

@PostConstruct()
protected init(): void {
if (this.options?.defaultAPIKeys) {
this.apiKeys = Array.isArray(this.options.defaultAPIKeys) ? this.options?.defaultAPIKeys : this.options.defaultAPIKeys.split(',');
}
this.proxy = Server.createProxy();
this.proxy.on('proxyReq', proxyReq => {
if (!proxyReq.hasHeader(HttpHeaders.AUTHORIZATION) && this.options?.defaultAPIKey) {
proxyReq.setHeader(HttpHeaders.AUTHORIZATION, `Bearer ${this.options.defaultAPIKey}`);
if (this.useDefaultAPIKey()) {
proxyReq.setHeader(HttpHeaders.AUTHORIZATION, `Bearer ${this.selectAPIKey()}`);
}
});
}

protected useDefaultAPIKey(authorization?: string): boolean {
if (!authorization || authorization.includes('managed')) {
return this.apiKeys.length > 0;
}
return false;
}

protected selectAPIKey(): string {
const randomIndex = Math.floor(Math.random() * this.apiKeys.length);
return this.apiKeys[randomIndex];
}

async handle(ctx: Context, next: () => Promise<void>): Promise<void> {
const { request, response } = ctx;
this.proxy.web(request, response, {
Expand Down

0 comments on commit 8a56981

Please sign in to comment.