mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-04 00:15:28 +08:00
Restrict Vercel Node stream path to OpenAI chat to avoid Gemini empty responses
This commit is contained in:
@@ -59,8 +59,9 @@ async function handler(req, res) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep all non-stream behavior on Go side to avoid compatibility regressions.
|
||||
if (!toBool(payload.stream)) {
|
||||
// Keep all non-stream behavior and non-OpenAI-chat paths on Go side to avoid
|
||||
// protocol-shape regressions (e.g. Gemini/Claude clients expecting their own formats).
|
||||
if (!toBool(payload.stream) || !isNodeStreamSupportedPath(req.url || '')) {
|
||||
await proxyToGo(req, res, rawBody);
|
||||
return;
|
||||
}
|
||||
@@ -76,6 +77,23 @@ function isVercelRuntime() {
|
||||
return asString(process.env.VERCEL) !== '' || asString(process.env.NOW_REGION) !== '';
|
||||
}
|
||||
|
||||
function isNodeStreamSupportedPath(rawURL) {
|
||||
const path = extractPathname(rawURL);
|
||||
return path === '/v1/chat/completions';
|
||||
}
|
||||
|
||||
function extractPathname(rawURL) {
|
||||
const text = asString(rawURL);
|
||||
if (!text) {
|
||||
return '';
|
||||
}
|
||||
const q = text.indexOf('?');
|
||||
if (q >= 0) {
|
||||
return text.slice(0, q);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
module.exports = handler;
|
||||
|
||||
module.exports.__test = {
|
||||
@@ -89,4 +107,6 @@ module.exports.__test = {
|
||||
boolDefaultTrue,
|
||||
filterIncrementalToolCallDeltasByAllowed,
|
||||
estimateTokens,
|
||||
isNodeStreamSupportedPath,
|
||||
extractPathname,
|
||||
};
|
||||
|
||||
@@ -18,6 +18,8 @@ const {
|
||||
boolDefaultTrue,
|
||||
filterIncrementalToolCallDeltasByAllowed,
|
||||
shouldSkipPath,
|
||||
isNodeStreamSupportedPath,
|
||||
extractPathname,
|
||||
} = handler.__test;
|
||||
|
||||
test('chat-stream exposes parser test hooks', () => {
|
||||
@@ -225,3 +227,15 @@ test('shouldSkipPath skips dynamic response/fragments/*/status paths only', () =
|
||||
assert.equal(shouldSkipPath('response/fragments/8/status'), true);
|
||||
assert.equal(shouldSkipPath('response/status'), false);
|
||||
});
|
||||
|
||||
test('node stream path guard only allows /v1/chat/completions', () => {
|
||||
assert.equal(isNodeStreamSupportedPath('/v1/chat/completions'), true);
|
||||
assert.equal(isNodeStreamSupportedPath('/v1/chat/completions?x=1'), true);
|
||||
assert.equal(isNodeStreamSupportedPath('/v1beta/models/gemini-2.5-flash:streamGenerateContent'), false);
|
||||
assert.equal(isNodeStreamSupportedPath('/anthropic/v1/messages'), false);
|
||||
});
|
||||
|
||||
test('extractPathname strips query only', () => {
|
||||
assert.equal(extractPathname('/v1/chat/completions?stream=true'), '/v1/chat/completions');
|
||||
assert.equal(extractPathname('/v1beta/models/gemini-2.5-flash:streamGenerateContent?key=1'), '/v1beta/models/gemini-2.5-flash:streamGenerateContent');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user