fix(runtime): avoid encoding latin1 directory headers

This commit is contained in:
Bohdan Triapitsyn
2026-06-24 00:43:03 +03:00
parent 37aec95f37
commit c3cf914fda
2 changed files with 11 additions and 7 deletions
+7 -1
View File
@@ -394,9 +394,15 @@ describe('runtimeFetch header sanitization', () => {
expect(result).toBeFalsy();
});
test('sanitizeHeadersForBrowser always encodes directory hints with marker', () => {
test('sanitizeHeadersForBrowser leaves Latin-1 directory hints unchanged', () => {
const path = 'C:\\work\\foo%20bar';
const result = sanitizeHeadersForBrowser({ 'x-opencode-directory': path });
expect(result).toBeFalsy();
});
test('sanitizeHeadersForBrowser encodes non-Latin-1 directory hints with marker', () => {
const path = 'D:\\文件夹';
const result = sanitizeHeadersForBrowser({ 'x-opencode-directory': path });
expect(result).toBeTruthy();
const encoded = Object.fromEntries(result!);
expect(encoded['x-opencode-directory']).toBe(encodeURIComponent(path));
+4 -6
View File
@@ -99,9 +99,9 @@ const shouldAttachRuntimeAuth = (input: string | URL | Request): boolean => {
// Headers API only accepts ISO-8859-1 (Latin-1) characters. Any value containing
// characters outside \u0000-\u00FF causes "Failed to construct/set 'Headers':
// String contains non ISO-8859-1 code point." Encode those values so they round-trip
// safely through the browser's Headers API. Directory hints are always encoded
// with an explicit marker header so the server decodes only values produced by
// this transport and preserves literal percent sequences from direct clients.
// safely through the browser's Headers API. Directory hints get an explicit marker
// only when encoded, so plain ASCII paths remain compatible with routes that read
// the header directly.
export const isLatin1Safe = (value: string): boolean => {
for (let i = 0; i < value.length; i += 1) {
if (value.charCodeAt(i) > 0xFF) return false;
@@ -109,9 +109,7 @@ export const isLatin1Safe = (value: string): boolean => {
return true;
};
const shouldEncodeHeaderValue = (key: string, value: string): boolean => (
key.toLowerCase() === 'x-opencode-directory' || !isLatin1Safe(value)
);
const shouldEncodeHeaderValue = (_key: string, value: string): boolean => !isLatin1Safe(value);
export const sanitizeHeadersForBrowser = (init?: HeadersInit): [string, string][] | undefined => {
if (!init) return undefined;