Relax CORS preflight handling across interfaces

This commit is contained in:
CJACK
2026-04-26 00:37:25 +08:00
parent f1ba805173
commit a44afb335a
10 changed files with 440 additions and 17 deletions

View File

@@ -9,6 +9,9 @@ const {
processToolSieveChunk,
flushToolSieve,
} = require('../../internal/js/helpers/stream-tool-sieve.js');
const {
setCorsHeaders,
} = require('../../internal/js/chat-stream/http_internal.js');
const {
parseChunkForContent,
@@ -26,6 +29,18 @@ const {
trimContinuationOverlap,
} = handler.__test;
function createMockResponse() {
const headers = new Map();
return {
setHeader(key, value) {
headers.set(String(key).toLowerCase(), value);
},
getHeader(key) {
return headers.get(String(key).toLowerCase());
},
};
}
test('chat-stream exposes parser test hooks', () => {
assert.equal(typeof parseChunkForContent, 'function');
assert.equal(typeof resolveToolcallPolicy, 'function');
@@ -400,6 +415,32 @@ test('extractPathname strips query only', () => {
assert.equal(extractPathname('/v1beta/models/gemini-2.5-flash:streamGenerateContent?key=1'), '/v1beta/models/gemini-2.5-flash:streamGenerateContent');
});
test('setCorsHeaders reflects requested third-party headers and blocks internal-only headers', () => {
const res = createMockResponse();
setCorsHeaders(res, {
headers: {
origin: 'app://obsidian.md',
'access-control-request-headers': 'authorization, x-stainless-os, x-stainless-runtime, x-ds2-internal-token',
'access-control-request-private-network': 'true',
},
});
assert.equal(res.getHeader('access-control-allow-origin'), 'app://obsidian.md');
assert.equal(res.getHeader('access-control-allow-private-network'), 'true');
assert.equal(res.getHeader('access-control-max-age'), '600');
const allowHeaders = String(res.getHeader('access-control-allow-headers') || '').toLowerCase();
assert.equal(allowHeaders.includes('authorization'), true);
assert.equal(allowHeaders.includes('x-stainless-os'), true);
assert.equal(allowHeaders.includes('x-stainless-runtime'), true);
assert.equal(allowHeaders.includes('x-ds2-internal-token'), false);
const vary = String(res.getHeader('vary') || '').toLowerCase();
assert.equal(vary.includes('origin'), true);
assert.equal(vary.includes('access-control-request-headers'), true);
assert.equal(vary.includes('access-control-request-private-network'), true);
});
test('trimContinuationOverlap preserves short normal tokens and trims long snapshots', () => {
assert.equal(trimContinuationOverlap('我们被问到', '我们'), '我们');
const existing = '我们被问到:这是一个很长的续答快照前缀,用来验证去重逻辑不会误伤正常 token。';