This commit is contained in:
2026-10-18 23:48:36 +07:00
parent d3681d9df5
commit a58f0866d3
4 changed files with 83 additions and 0 deletions
+2
View File
@@ -25,6 +25,7 @@ import { Online } from './online.js'
import type { OnlineState } from '../src/types/online.js'
import { PackageStore } from './package-store.js'
import { packageMediaResponse } from './package-media.js'
import { prepareFetchHeaders } from './response-headers.js'
import type { HostInfo } from '../src/types/screen.js'
// Ozone выбирается до main.js; поздний appendSwitch смешивает Wayland и X11.
@@ -334,6 +335,7 @@ app
diagnostics.record('settings-error')
hostNotice = error instanceof Error ? error.message : 'Не удалось восстановить окна'
}
prepareFetchHeaders(session.defaultSession)
const fetchNetwork: typeof fetch = (input, init) =>
net.fetch(input instanceof URL ? input.href : input, init)
const packages = new PackageStore(join(app.getPath('userData'), 'packages'), {
+24
View File
@@ -0,0 +1,24 @@
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { byteStringResponseHeaders } from './response-headers.js'
test('заголовки с кириллицей совместимы с Headers, обычные значения сохраняются', () => {
const original = {
'X-Name': ['пример'],
Location: ['https://media.test/папка/трек.mp3?name=%D0%B0'],
'Content-Disposition': ['attachment; filename="пример.mp3"'],
'Content-Length': ['1024'],
'Content-Type': ['audio/wav'],
'X-Latin': ['caf\u00e9'],
'Set-Cookie': ['a=1', 'b=2'],
}
const result = byteStringResponseHeaders(original)
const headers = new Headers(Object.fromEntries(Object.entries(result).map(([name, values]) => [name, values.join(', ')])))
assert.equal(headers.get('x-name'), encodeURIComponent('пример'))
assert.equal(headers.get('location'), new URL(original.Location[0]!).href)
assert.equal(result['Content-Disposition']![0], `attachment; filename="${encodeURIComponent('пример')}.mp3"`)
for (const name of ['Content-Length', 'Content-Type', 'X-Latin', 'Set-Cookie'] as const)
assert.deepEqual(result[name], original[name])
assert.equal(original['X-Name'][0], 'пример')
assert.deepEqual(byteStringResponseHeaders(), {})
})
+13
View File
@@ -0,0 +1,13 @@
export function byteStringResponseHeaders(headers: Record<string, string[]> = {}) {
return Object.fromEntries(Object.entries(headers).map(([name, values]) => [
name,
values.map((value) => value.replace(/[^\x00-\xff]+/gu, encodeURIComponent)),
]))
}
export function prepareFetchHeaders(target: Electron.Session) {
// Electron net.fetch throws outside its promise when a response header contains Unicode.
target.webRequest.onHeadersReceived((details, callback) => {
callback({ responseHeaders: byteStringResponseHeaders(details.responseHeaders) })
})
}