diff --git a/packages/ui/src/lib/runtime-fetch.test.ts b/packages/ui/src/lib/runtime-fetch.test.ts index 1fe7c127..390620d8 100644 --- a/packages/ui/src/lib/runtime-fetch.test.ts +++ b/packages/ui/src/lib/runtime-fetch.test.ts @@ -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)); diff --git a/packages/ui/src/lib/runtime-fetch.ts b/packages/ui/src/lib/runtime-fetch.ts index ddf8a44f..f46f2e46 100644 --- a/packages/ui/src/lib/runtime-fetch.ts +++ b/packages/ui/src/lib/runtime-fetch.ts @@ -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;