fix: accept uppercase endpoint URL schemes (#5443)
Some checks are pending
Qwen Code CI / Classify PR (push) Waiting to run
Qwen Code CI / Lint (push) Blocked by required conditions
Qwen Code CI / Test (macos-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (ubuntu-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Test (windows-latest, Node 22.x) (push) Blocked by required conditions
Qwen Code CI / Post Coverage Comment (push) Blocked by required conditions
Qwen Code CI / CodeQL (push) Blocked by required conditions
Qwen Code CI / Integration Tests (CLI, No Sandbox) (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:docker (push) Waiting to run
E2E Tests / E2E Test (Linux) - sandbox:none (push) Waiting to run
E2E Tests / E2E Test - macOS (push) Waiting to run

This commit is contained in:
tt-a1i 2026-06-21 02:09:29 +08:00 committed by GitHub
parent 4d2724005b
commit 26c13091d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 40 additions and 3 deletions

View file

@ -1225,6 +1225,14 @@ describe('QwenContentGenerator', () => {
input: 'https://api.example.com:443',
expected: 'https://api.example.com:443/v1',
},
{
input: 'HTTPS://api.example.com',
expected: 'HTTPS://api.example.com/v1',
},
{
input: 'HtTp://localhost:8080',
expected: 'HtTp://localhost:8080/v1',
},
{
input: 'api.example.com:9000/api',
expected: 'https://api.example.com:9000/api/v1',

View file

@ -61,7 +61,7 @@ export class QwenContentGenerator extends OpenAIContentGenerator {
const suffix = '/v1';
// Normalize the URL: add protocol if missing, ensure /v1 suffix
const normalizedUrl = baseEndpoint.startsWith('http')
const normalizedUrl = /^https?:\/\//i.test(baseEndpoint)
? baseEndpoint
: `https://${baseEndpoint}`;

View file

@ -138,6 +138,17 @@ describe('QwenLogger', () => {
});
});
describe('getProxyAgent', () => {
it('accepts uppercase proxy URL schemes', () => {
const config = makeFakeConfig({
getProxy: () => 'HTTPS://proxy.example.com:8080',
});
const logger = QwenLogger.getInstance(config)!;
expect(logger.getProxyAgent()).toBeDefined();
});
});
describe('createRumPayload', () => {
it('includes os metadata in payload', async () => {
const logger = QwenLogger.getInstance(mockConfig)!;

View file

@ -1070,7 +1070,7 @@ export class QwenLogger {
if (!proxyUrl) return undefined;
// undici which is widely used in the repo can only support http & https proxy protocol,
// https://github.com/nodejs/undici/issues/2224
if (proxyUrl.startsWith('http')) {
if (/^https?:\/\//i.test(proxyUrl)) {
return new HttpsProxyAgent(proxyUrl);
} else {
throw new Error('Unsupported proxy type');

View file

@ -176,6 +176,24 @@ describe('refreshApiRenew via refresh()', () => {
expect(fetchCalls[0]!.url).toBe('https://auth.example.com/oauth/token');
});
test('handles absolute renew URL with uppercase scheme', async () => {
mockGet.mockImplementationOnce(() => Promise.resolve({
value: 'old-token', expiresAt: Date.now() - 60_000,
}));
mockFetch({ access_token: 'new-token', expires_in: 3600 });
const source = createRenewSource({
api: {
baseUrl: 'https://api.example.com',
authType: 'bearer',
renewEndpoint: { path: 'HTTPS://auth.example.com/oauth/token' },
},
});
await credManager.refresh(source);
expect(fetchCalls[0]!.url).toBe('HTTPS://auth.example.com/oauth/token');
});
test('returns null on 401 response', async () => {
mockGet.mockImplementationOnce(() => Promise.resolve({
value: 'old-token', expiresAt: Date.now() - 60_000,

View file

@ -975,7 +975,7 @@ export class SourceCredentialManager {
try {
// 1. Resolve URL
const url = renewConfig.path.startsWith('http')
const url = /^https?:\/\//i.test(renewConfig.path)
? renewConfig.path
: new URL(renewConfig.path, baseUrl.endsWith('/') ? baseUrl : `${baseUrl}/`).toString();