Dialog portalem do body, hlavicky odpovedi u chyby
Dialog se vykresloval uvnitr karty konektoru misto pres obrazovku. Samo position: fixed nestaci: rodic s backdrop-filter (nase .glass, tedy skoro kazdy panel a karta) je pro fixed potomka containing block. Modal proto jde portalem do document.body. Tykalo se to vsech dialogu, videt to bylo az u Logu, ktere jsou v male karte. K chybe se zapisuji vybrane hlavicky odpovedi: server, via, content-type, www-authenticate, retry-after, x-request-id, date. Rikaji, kdo odpoved vydal. Server: Kestrel je sama aplikace, Via: 1.1 Caddy proxy pred ni. U 403 od proxy byva telo prazdne a bez hlavicek by nezbylo vubec nic. Allowlist, ne vsechno: Set-Cookie a podobne do zaznamu nepatri. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
5a124a53d8
commit
ab88979627
+39
-3
@@ -102,6 +102,33 @@ const reasonListKeys = ['missingHeaders', 'errors', 'Errors'];
|
||||
/** Strop na duvod v hlasce. Cele telo zustava v `detail`, tohle je jen veta. */
|
||||
const reasonBytes = 400;
|
||||
|
||||
/**
|
||||
* Hlavicky odpovedi, ktere se zapisuji k chybe.
|
||||
*
|
||||
* Allowlist, ne vsechno: v odpovedi muze byt `Set-Cookie` nebo token a ten
|
||||
* do zaznamu nepatri. Tyhle rikaji, **kdo** odpoved vydal - `Server: Kestrel`
|
||||
* je sama aplikace, `Via: 1.1 Caddy` proxy pred ni. U 403 bez tela je to
|
||||
* jedina stopa, ktera zbyde.
|
||||
*/
|
||||
const keptResponseHeaders = [
|
||||
'server',
|
||||
'via',
|
||||
'content-type',
|
||||
'www-authenticate',
|
||||
'retry-after',
|
||||
'x-request-id',
|
||||
'date',
|
||||
];
|
||||
|
||||
function pickResponseHeaders(response: Response): Record<string, string> {
|
||||
const picked: Record<string, string> = {};
|
||||
for (const name of keptResponseHeaders) {
|
||||
const value = response.headers.get(name);
|
||||
if (value !== null && value !== '') picked[name] = truncate(value, 200);
|
||||
}
|
||||
return picked;
|
||||
}
|
||||
|
||||
function reasonFromText(value: string, depth: number): string | null {
|
||||
const raw = value.trim();
|
||||
if (raw === '') return null;
|
||||
@@ -183,13 +210,17 @@ function statusError(
|
||||
status: number,
|
||||
request: ScriptRequestInfo,
|
||||
detail: string,
|
||||
responseHeaders: Record<string, string>,
|
||||
): ScriptError {
|
||||
const where = `${request.method} ${request.url} vrátilo HTTP ${status}`;
|
||||
const reason = reasonFromBody(detail);
|
||||
// Kdyz telo nic nerika, aspon se rekne, kdo odpoved vydal. Prazdne telo
|
||||
// u 403 obvykle znamena, ze to nevydala aplikace, ale neco pred ni.
|
||||
const who = responseHeaders.server ?? responseHeaders.via;
|
||||
const said = reason
|
||||
? ` Služba odpověděla: ${reason}`
|
||||
: ' Služba k tomu nenapsala nic, tělo odpovědi je prázdné.';
|
||||
const options = { status, detail, request };
|
||||
: ` Tělo odpovědi je prázdné${who ? `, odpověď vydal ${who}` : ''}.`;
|
||||
const options = { status, detail, request, responseHeaders };
|
||||
|
||||
if (retryableStatuses.has(status)) {
|
||||
return new ScriptError('retryable', `Služba je momentálně nedostupná: ${where}.${said}`, options);
|
||||
@@ -339,7 +370,12 @@ export function createHttp(options: CreateHttpOptions): ScriptHttp {
|
||||
if (!response.ok && !allowed.includes(response.status)) {
|
||||
// Zamerne surove telo, ne prochazene pres JSON.stringify - u chyby chceme
|
||||
// presne to, co sluzba poslala, vcetne pripadneho HTML nebo textu.
|
||||
throw statusError(response.status, request, redact(truncate(raw, config.errorDetailBytes)));
|
||||
throw statusError(
|
||||
response.status,
|
||||
request,
|
||||
redact(truncate(raw, config.errorDetailBytes)),
|
||||
pickResponseHeaders(response),
|
||||
);
|
||||
}
|
||||
|
||||
return { status: response.status, body: parsed as T };
|
||||
|
||||
@@ -185,6 +185,14 @@ export class ScriptError extends Error {
|
||||
*/
|
||||
readonly detail?: string;
|
||||
readonly request?: ScriptRequestInfo;
|
||||
/**
|
||||
* Vybrane hlavicky odpovedi. Rikaji, **kdo** odpoved vydal: `Server: Kestrel`
|
||||
* je aplikace, `Via: 1.1 Caddy` sama proxy. U kodu bez tela (a 403 od proxy
|
||||
* telo casto nema) je to jedina stopa, ktera zbyde.
|
||||
*
|
||||
* Allowlist, ne vsechno: `Set-Cookie` a podobne do zaznamu nepatri.
|
||||
*/
|
||||
readonly responseHeaders?: Record<string, string>;
|
||||
|
||||
constructor(
|
||||
kind: ScriptErrorKind,
|
||||
@@ -193,6 +201,7 @@ export class ScriptError extends Error {
|
||||
status?: number;
|
||||
detail?: string;
|
||||
request?: ScriptRequestInfo;
|
||||
responseHeaders?: Record<string, string>;
|
||||
cause?: unknown;
|
||||
} = {},
|
||||
) {
|
||||
@@ -202,6 +211,7 @@ export class ScriptError extends Error {
|
||||
this.status = options.status;
|
||||
this.detail = options.detail;
|
||||
this.request = options.request;
|
||||
this.responseHeaders = options.responseHeaders;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user