From 077a406df6f79fdd0e343c3b6b3d0860a3d41a87 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Sun, 7 Dec 2025 22:52:31 -0500 Subject: [PATCH] fix(glmt): add bearer prefix for openai-compatible endpoints OpenAI-compatible endpoints like /chat/completions require Authorization header with 'Bearer ' prefix. Previously the token was sent without prefix, causing 401 Unauthorized errors. Auto-detects endpoint type based on URL path and formats header accordingly. Fixes #61 --- src/glmt/glmt-proxy.ts | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/glmt/glmt-proxy.ts b/src/glmt/glmt-proxy.ts index 2062e3d1..9edb832d 100644 --- a/src/glmt/glmt-proxy.ts +++ b/src/glmt/glmt-proxy.ts @@ -353,6 +353,10 @@ export class GlmtProxy { const url = new URL(this.upstreamUrl); const requestBody = JSON.stringify(openaiRequest); + // OpenAI-compatible endpoints require "Bearer " prefix + const token = process.env.ANTHROPIC_AUTH_TOKEN || ''; + const authHeader = this.formatAuthHeader(token, url.pathname); + const options: https.RequestOptions = { hostname: url.hostname, port: url.port || 443, @@ -361,7 +365,7 @@ export class GlmtProxy { headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(requestBody), - Authorization: process.env.ANTHROPIC_AUTH_TOKEN || '', + Authorization: authHeader, 'User-Agent': 'CCS-GLMT-Proxy/1.0', }, }; @@ -425,6 +429,10 @@ export class GlmtProxy { const url = new URL(this.upstreamUrl); const requestBody = JSON.stringify(openaiRequest); + // OpenAI-compatible endpoints require "Bearer " prefix + const token = process.env.ANTHROPIC_AUTH_TOKEN || ''; + const authHeader = this.formatAuthHeader(token, url.pathname); + const options: https.RequestOptions = { hostname: url.hostname, port: url.port || 443, @@ -433,7 +441,7 @@ export class GlmtProxy { headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(requestBody), - Authorization: process.env.ANTHROPIC_AUTH_TOKEN || '', + Authorization: authHeader, 'User-Agent': 'CCS-GLMT-Proxy/1.0', Accept: 'text/event-stream', }, @@ -540,6 +548,24 @@ export class GlmtProxy { } } + /** + * Format Authorization header based on endpoint type + * OpenAI-compatible endpoints (chat/completions) require "Bearer " prefix + * Anthropic-compatible endpoints use token directly + */ + private formatAuthHeader(token: string, pathname: string): string { + // OpenAI-compatible endpoints use Bearer token format + const isOpenAICompatible = + pathname.includes('chat/completions') || + pathname.includes('/v1/') || + pathname.includes('/paas/'); + + if (isOpenAICompatible && token && !token.startsWith('Bearer ')) { + return `Bearer ${token}`; + } + return token; + } + /** * Parse upstream error and return user-friendly error info */