fix
This commit is contained in:
+7
-2
@@ -3,6 +3,7 @@ import {
|
||||
dialog,
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
net,
|
||||
protocol,
|
||||
screen,
|
||||
session,
|
||||
@@ -289,7 +290,11 @@ app
|
||||
diagnostics.record('settings-error')
|
||||
hostNotice = error instanceof Error ? error.message : 'Не удалось восстановить окна'
|
||||
}
|
||||
const packages = new PackageStore(join(app.getPath('userData'), 'packages'))
|
||||
const fetchNetwork: typeof fetch = (input, init) =>
|
||||
net.fetch(input instanceof URL ? input.href : input, init)
|
||||
const packages = new PackageStore(join(app.getPath('userData'), 'packages'), {
|
||||
fetch: fetchNetwork,
|
||||
})
|
||||
await packages.initialize()
|
||||
online = new Online(
|
||||
join(app.getPath('userData'), 'connection'),
|
||||
@@ -303,7 +308,7 @@ app
|
||||
encrypt: (value) => safeStorage.encryptString(value),
|
||||
decrypt: (value) => safeStorage.decryptString(value),
|
||||
},
|
||||
undefined,
|
||||
fetchNetwork,
|
||||
(failure) => diagnostics?.record('request-error', failure),
|
||||
async () => {
|
||||
const result = await dialog.showOpenDialog({
|
||||
|
||||
@@ -33,3 +33,35 @@ test('контекст HTTP сохраняет тип ошибки, статус
|
||||
result.message,
|
||||
)
|
||||
})
|
||||
|
||||
test('ошибки Chromium сохраняют безопасный код без адресов и содержимого', () => {
|
||||
for (const [input, code, message] of [
|
||||
['ERR_NAME_NOT_RESOLVED', 'ENOTFOUND', 'Не удалось определить адрес сервера'],
|
||||
['ERR_CONNECTION_REFUSED', 'ECONNREFUSED', 'Сервер отклонил соединение'],
|
||||
['ERR_CONNECTION_TIMED_OUT', 'ETIMEDOUT', 'Превышено время ожидания соединения с сервером'],
|
||||
[
|
||||
'ERR_PROXY_CONNECTION_FAILED',
|
||||
'ERR_PROXY_CONNECTION_FAILED',
|
||||
'Не удалось подключиться через системный прокси',
|
||||
],
|
||||
[
|
||||
'ERR_TUNNEL_CONNECTION_FAILED',
|
||||
'ERR_TUNNEL_CONNECTION_FAILED',
|
||||
'Не удалось подключиться через системный прокси',
|
||||
],
|
||||
[
|
||||
'ERR_CERT_AUTHORITY_INVALID',
|
||||
'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
||||
'Ошибка защищённого соединения с сервером',
|
||||
],
|
||||
['ERR_UNKNOWN', 'NETWORK', 'Сервер недоступен'],
|
||||
]) {
|
||||
const result = networkFailure(
|
||||
new Error(`net::${input} at https://SECRET.invalid`),
|
||||
new AbortController().signal,
|
||||
)
|
||||
assert.equal(result.code, code)
|
||||
assert.equal(result.message, message)
|
||||
assert.ok(!result.message.includes('SECRET'))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const NETWORK_ERROR_CODES = [
|
||||
'NETWORK',
|
||||
'ERR_PROXY_CONNECTION_FAILED',
|
||||
'ERR_TUNNEL_CONNECTION_FAILED',
|
||||
'TIMEOUT',
|
||||
'ABORTED',
|
||||
'ENOTFOUND',
|
||||
@@ -41,8 +43,26 @@ export class ApiError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
const chromiumCodes: Record<string, NetworkErrorCode> = {
|
||||
ERR_NAME_NOT_RESOLVED: 'ENOTFOUND',
|
||||
ERR_CONNECTION_REFUSED: 'ECONNREFUSED',
|
||||
ERR_CONNECTION_RESET: 'ECONNRESET',
|
||||
ERR_CONNECTION_TIMED_OUT: 'ETIMEDOUT',
|
||||
ERR_TIMED_OUT: 'ETIMEDOUT',
|
||||
ERR_PROXY_CONNECTION_FAILED: 'ERR_PROXY_CONNECTION_FAILED',
|
||||
ERR_TUNNEL_CONNECTION_FAILED: 'ERR_TUNNEL_CONNECTION_FAILED',
|
||||
ERR_CERT_DATE_INVALID: 'CERT_HAS_EXPIRED',
|
||||
ERR_CERT_AUTHORITY_INVALID: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
|
||||
ERR_CERT_COMMON_NAME_INVALID: 'ERR_TLS_CERT_ALTNAME_INVALID',
|
||||
}
|
||||
|
||||
function causeCode(error: unknown, depth = 0): NetworkErrorCode | undefined {
|
||||
if (!error || typeof error !== 'object' || depth > 3) return
|
||||
if (error instanceof Error) {
|
||||
const match = /^net::(ERR_[A-Z_]+)(?:\s|$)/.exec(error.message)
|
||||
const code = match ? chromiumCodes[match[1]!] : undefined
|
||||
if (code) return code
|
||||
}
|
||||
const value = error as { code?: unknown; cause?: unknown; errors?: unknown[] }
|
||||
if (NETWORK_ERROR_CODES.includes(value.code as NetworkErrorCode))
|
||||
return value.code as NetworkErrorCode
|
||||
@@ -64,15 +84,17 @@ export function networkFailure(error: unknown, signal: AbortSignal): NetworkErro
|
||||
const message =
|
||||
code === 'ENOTFOUND' || code === 'EAI_AGAIN'
|
||||
? 'Не удалось определить адрес сервера'
|
||||
: code.includes('CERT') || code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
|
||||
? 'Ошибка защищённого соединения с сервером'
|
||||
: code === 'ETIMEDOUT' || code === 'UND_ERR_CONNECT_TIMEOUT'
|
||||
? 'Превышено время ожидания соединения с сервером'
|
||||
: code === 'ECONNREFUSED'
|
||||
? 'Сервер отклонил соединение'
|
||||
: code === 'ECONNRESET'
|
||||
? 'Соединение с сервером прервано'
|
||||
: 'Сервер недоступен'
|
||||
: code === 'ERR_PROXY_CONNECTION_FAILED' || code === 'ERR_TUNNEL_CONNECTION_FAILED'
|
||||
? 'Не удалось подключиться через системный прокси'
|
||||
: code.includes('CERT') || code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
|
||||
? 'Ошибка защищённого соединения с сервером'
|
||||
: code === 'ETIMEDOUT' || code === 'UND_ERR_CONNECT_TIMEOUT'
|
||||
? 'Превышено время ожидания соединения с сервером'
|
||||
: code === 'ECONNREFUSED'
|
||||
? 'Сервер отклонил соединение'
|
||||
: code === 'ECONNRESET'
|
||||
? 'Соединение с сервером прервано'
|
||||
: 'Сервер недоступен'
|
||||
return new NetworkError(message, code)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user