@slicedearth/whoisleuth-cli 1.47.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -177
- package/SECURITY.md +6 -3
- package/bin/whoisleuth.mjs +2 -1
- package/cli/archive-inspect.mjs +28 -10
- package/cli/arguments.mjs +204 -174
- package/cli/artifact-structure.mjs +837 -163
- package/cli/artifact-verify.mjs +90 -61
- package/cli/bounded-json.mjs +1 -1
- package/cli/bulk-checkpoint.mjs +33 -20
- package/cli/bulk.mjs +9 -2
- package/cli/case-pack.mjs +180 -576
- package/cli/ci-report.mjs +6 -1
- package/cli/collection-preflight.mjs +2 -2
- package/cli/command-catalogue.mjs +12 -3
- package/cli/command-reference.mjs +910 -92
- package/cli/completion.mjs +504 -226
- package/cli/config-profile.mjs +13 -3
- package/cli/discover.mjs +7 -1
- package/cli/discovery-observation-snapshot.mjs +24 -28
- package/cli/discovery-scan-command-runner.mjs +9 -9
- package/cli/discovery-scan.mjs +17 -3
- package/cli/discovery-snapshot.mjs +15 -7
- package/cli/domain-control-monitor.mjs +203 -30
- package/cli/domain-control-observations.mjs +15 -21
- package/cli/errors.mjs +8 -3
- package/cli/evidence-signing.mjs +10 -20
- package/cli/external-observation-mapping.mjs +3 -3
- package/cli/formatters/json.mjs +20 -32
- package/cli/formatters/terminal.mjs +583 -22
- package/cli/input.mjs +7 -2
- package/cli/interactive-launcher.mjs +226 -0
- package/cli/interchange-report.mjs +19 -19
- package/cli/investigation-manifest.mjs +1 -1
- package/cli/investigation-plan.mjs +167 -16
- package/cli/investigation-run.mjs +9 -1
- package/cli/lookalike-calibration.mjs +3 -1
- package/cli/lookup-brief.mjs +13 -8
- package/cli/lookup-browser.mjs +844 -0
- package/cli/lookup-command-runner.mjs +94 -31
- package/cli/lookup-diff.mjs +2 -2
- package/cli/lookup-plan.mjs +1 -0
- package/cli/mail-review.mjs +206 -94
- package/cli/manual.mjs +5 -5
- package/cli/offline-evidence-review.mjs +18 -7
- package/cli/open-asset-model-bridge.mjs +1 -1
- package/cli/output-file.mjs +70 -14
- package/cli/page-compare.mjs +11 -6
- package/cli/progress-events.mjs +2 -1
- package/cli/progress.mjs +3 -3
- package/cli/registry-cohort.mjs +9 -51
- package/cli/registry-doctor.mjs +67 -28
- package/cli/retained-artifact-diff.mjs +7 -8
- package/cli/risk-calibration.mjs +85 -38
- package/cli/runner.mjs +189 -75
- package/cli/saved-lookup.mjs +424 -57
- package/cli/sharing-review.mjs +6 -1
- package/cli/source-reliability.mjs +75 -36
- package/cli/terminal-presentation.mjs +43 -18
- package/docs/cli-reference.md +125 -1708
- package/docs/cli.md +86 -254
- package/frontend/src/lib/analysis/domain-control-manifest-core.js +3 -145
- package/frontend/src/lib/analysis/domain-control-records.js +3 -88
- package/lib/availability.mjs +58 -40
- package/lib/bounded-contract-normalizers.mjs +2 -4
- package/lib/bounded-file.mjs +78 -4
- package/lib/bounded-json.mjs +51 -13
- package/lib/browser-library-profile.mjs +1 -1
- package/lib/classify.mjs +56 -5
- package/lib/client-behavior-profile.mjs +1 -1
- package/lib/credential-surface-profile.mjs +1 -1
- package/lib/cryptographic-assurance.mjs +35 -17
- package/lib/ct-query.mjs +3 -3
- package/lib/ct-search.mjs +37 -21
- package/lib/distributed-operation-budget.mjs +4 -2
- package/lib/dns-delegation-health.mjs +9 -6
- package/lib/dns-intelligence.mjs +1 -1
- package/lib/dnssec-chain-validation.mjs +2 -3
- package/lib/dnssec-evidence-validation.mjs +13 -7
- package/lib/domain-assurance.mjs +12 -12
- package/lib/domain-change-packet.mjs +1 -1
- package/lib/domain-control-flight-recorder.mjs +442 -78
- package/lib/domain-control-manifest.mjs +314 -59
- package/lib/domain-posture-analysis.mjs +5 -2
- package/lib/encrypted-dns-contract.mjs +2 -3
- package/lib/evidence-export.mjs +518 -36
- package/lib/external-intelligence-risk.mjs +26 -10
- package/lib/feature-policy.mjs +1 -1
- package/lib/homepage-metadata-contract.mjs +290 -0
- package/lib/hostname.mjs +1 -1
- package/lib/html-signals.mjs +89 -5
- package/lib/http-intelligence.mjs +331 -2
- package/lib/interchange-fidelity-registry.mjs +28 -26
- package/lib/lookup-cache.mjs +6 -4
- package/lib/lookup.mjs +25 -2
- package/lib/observed-network-context.mjs +1 -1
- package/lib/page-fingerprints.mjs +2 -2
- package/lib/page-role-profile.mjs +1 -1
- package/lib/portable-generator.mjs +8 -0
- package/lib/provider-policy-admission.mjs +3 -1
- package/lib/rdap-bootstrap.mjs +76 -16
- package/lib/rdap-client.mjs +20 -12
- package/lib/rdap-normalization.mjs +306 -75
- package/lib/rdap-transport.mjs +2 -2
- package/lib/rdap-validation.mjs +65 -14
- package/lib/rdap.mjs +2 -2
- package/lib/registrable-domain.mjs +36 -0
- package/lib/registry-insights.mjs +7 -0
- package/lib/response-policy.mjs +27 -4
- package/lib/risk-calibration-summary.mjs +35 -33
- package/lib/risk-scoring.mjs +4 -3
- package/lib/safe-fetch.mjs +62 -40
- package/lib/security-txt.mjs +1 -1
- package/lib/smtp-transport-review.mjs +8 -5
- package/lib/sslbl-intelligence.mjs +6 -8
- package/lib/static-html-analysis.mjs +301 -4
- package/lib/structured-data-identity.mjs +51 -19
- package/lib/threat-intelligence-fixtures.mjs +2 -4
- package/lib/threat-intelligence-manifests.mjs +2 -7
- package/lib/threat-intelligence-runtime.mjs +3 -5
- package/lib/threat-intelligence-types.mjs +3 -0
- package/lib/threatfox-intelligence.mjs +7 -3
- package/lib/tls-intelligence.mjs +4 -4
- package/lib/urlhaus-intelligence.mjs +4 -2
- package/lib/urlscan-intelligence.mjs +6 -5
- package/lib/website-security-posture.mjs +1 -1
- package/lib/website-technology.mjs +1 -1
- package/lib/whois-authority.mjs +43 -8
- package/lib/whois-chain.mjs +25 -3
- package/lib/whois-normalization.mjs +3 -1
- package/lib/whois-transport.mjs +12 -3
- package/lib/zone-intent-review.mjs +1 -1
- package/package.json +12 -4
- package/{frontend/src/lib/analysis/case-brand-profile-references.js → packages/cases/case-brand-profile-references.mjs} +2 -2
- package/{frontend/src/lib/analysis/case-evidence-model.js → packages/cases/case-evidence-model.mjs} +35 -14
- package/{frontend/src/lib/analysis/case-investigation-branch-model.js → packages/cases/case-investigation-branch-model.mjs} +10 -12
- package/packages/cases/case-migration-model.mjs +476 -0
- package/{frontend/src/lib/analysis/case-model.js → packages/cases/case-model.mjs} +3 -3
- package/{frontend/src/lib/analysis/case-record-contracts.js → packages/cases/case-record-contracts.mjs} +3 -21
- package/{frontend/src/lib/analysis/case-record-core.js → packages/cases/case-record-core.mjs} +58 -31
- package/packages/cases/case-record-model.mjs +9 -0
- package/{frontend/src/lib/analysis/case-record-operations.js → packages/cases/case-record-operations.mjs} +72 -29
- package/{frontend/src/lib/analysis/case-report.js → packages/cases/case-report.mjs} +108 -14
- package/packages/cases/case-response-model.mjs +1604 -0
- package/packages/cases/case-response-packet.mjs +1312 -0
- package/{frontend/src/lib/analysis/case-storage-model.js → packages/cases/case-storage-model.mjs} +2 -2
- package/{frontend/src/lib/analysis/http-summary.js → packages/cases/http-summary.mjs} +1 -1
- package/{frontend/src/lib/analysis/comparison-ledger-bulk.js → packages/comparison/comparison-ledger-bulk.mjs} +2 -2
- package/{frontend/src/lib/analysis/comparison-ledger-contract.js → packages/comparison/comparison-ledger-contract.mjs} +4 -4
- package/{frontend/src/lib/analysis/comparison-ledger-json.js → packages/comparison/comparison-ledger-json.mjs} +1 -0
- package/{frontend/src/lib/analysis/comparison-ledger-serialization.js → packages/comparison/comparison-ledger-serialization.mjs} +1 -0
- package/packages/comparison/favicon-similarity.mjs +78 -0
- package/{frontend/src/lib/analysis/page-similarity.js → packages/comparison/page-similarity.mjs} +4 -3
- package/{frontend/src/lib/analysis/relationship-evidence.js → packages/comparison/relationship-evidence.mjs} +6 -7
- package/packages/contracts/analyst-review-state-contract.mjs +61 -0
- package/packages/contracts/analyst-review-state.mjs +50 -0
- package/packages/contracts/case-portability.mjs +1310 -0
- package/packages/contracts/cli-command-catalogue.mjs +2 -0
- package/packages/contracts/cli-lookup.mjs +394 -0
- package/packages/contracts/domain-control-flight-recorder.mjs +461 -0
- package/packages/contracts/domain-control-manifest.mjs +1027 -0
- package/packages/contracts/domain-control-monitor.mjs +310 -0
- package/packages/contracts/domain-control-review.mjs +828 -0
- package/packages/contracts/domain-name.mjs +4 -0
- package/packages/contracts/external-observation-interchange.mjs +224 -0
- package/packages/contracts/extracted-domain-lifecycle.mjs +218 -0
- package/packages/contracts/investigation-portability.mjs +331 -0
- package/packages/contracts/offline-comparison.mjs +160 -0
- package/packages/contracts/risk-calibration.mjs +1288 -0
- package/packages/contracts/schema-compatibility.mjs +71 -0
- package/packages/contracts/schema-lifecycle.mjs +1702 -0
- package/packages/contracts/sslbl-snapshot.mjs +17 -0
- package/packages/contracts/workspace-portability.mjs +1347 -0
- package/{frontend/src/lib/analysis/artifact-integrity.js → packages/evidence/artifact-integrity.mjs} +13 -11
- package/packages/evidence/decision-fact.mjs +735 -0
- package/packages/evidence/domain-control-runtime.mjs +547 -0
- package/packages/evidence/domain-name.mjs +41 -0
- package/packages/evidence/observation.mjs +384 -0
- package/{frontend/src/lib/analysis/external-findings-import.js → packages/interchange/external-findings-import.mjs} +24 -22
- package/packages/interchange/retained-text.mjs +8 -0
- package/{frontend/src/lib/analysis/acquisition-decision-packet.js → packages/investigation/acquisition-decision-packet.mjs} +9 -6
- package/{frontend/src/lib/analysis/bulk-domain-comparison.js → packages/investigation/bulk-domain-comparison.mjs} +5 -6
- package/{frontend/src/lib/analysis/bulk-mail-exposure.js → packages/investigation/bulk-mail-exposure.mjs} +4 -6
- package/{frontend/src/lib/analysis/bulk-review-export.js → packages/investigation/bulk-review-export.mjs} +5 -5
- package/packages/investigation/bulk-review-policy.mjs +1 -0
- package/{frontend/src/lib/analysis/investigation-capsule.js → packages/investigation/investigation-capsule.mjs} +30 -32
- package/packages/investigation/lookup-artefact-inputs.mjs +1 -0
- package/{frontend/src/lib/analysis/lookup-asset-graph.js → packages/investigation/lookup-asset-graph.mjs} +4 -2
- package/{frontend/src/lib/analysis/lookup-claim-passport.js → packages/investigation/lookup-claim-passport.mjs} +6 -10
- package/{frontend/src/lib/analysis/lookup-claim-readiness.js → packages/investigation/lookup-claim-readiness.mjs} +9 -2
- package/packages/investigation/lookup-investigation-brief.mjs +172 -0
- package/packages/monitoring/analyst-review-state.mjs +680 -0
- package/{frontend/src/lib/analysis/brand-profile-model.js → packages/workspace/brand-profile-model.mjs} +70 -47
- package/{frontend/src/lib/analysis/bulk-review-model.js → packages/workspace/bulk-review-model.mjs} +13 -14
- package/{frontend/src/lib/analysis/bulk-session-model.js → packages/workspace/bulk-session-model.mjs} +33 -59
- package/{frontend/src/lib/analysis/bulk-sort.js → packages/workspace/bulk-sort.mjs} +8 -5
- package/{frontend/src/lib/analysis/campaign-model.js → packages/workspace/campaign-model.mjs} +20 -22
- package/{frontend/src/lib/analysis/detection-rule-model.js → packages/workspace/detection-rule-model.mjs} +15 -17
- package/packages/workspace/hostile-input.mjs +172 -0
- package/{frontend/src/lib/analysis/investigation-guide.js → packages/workspace/investigation-guide.mjs} +8 -45
- package/{frontend/src/lib/analysis/investigation-template-model.js → packages/workspace/investigation-template-model.mjs} +18 -21
- package/{frontend/src/lib/analysis/page-baseline.js → packages/workspace/page-baseline.mjs} +6 -13
- package/{frontend/src/lib/analysis/relationship-observation-model.js → packages/workspace/relationship-observation-model.mjs} +13 -17
- package/{frontend/src/lib/analysis/shortlist-model.js → packages/workspace/shortlist-model.mjs} +20 -18
- package/{frontend/src/lib/analysis/watchlist-history.js → packages/workspace/watchlist-history.mjs} +9 -16
- package/{frontend/src/lib/analysis/watchlist-store.js → packages/workspace/watchlist-store.mjs} +24 -17
- package/{frontend/src/lib/analysis/website-snapshot-model.js → packages/workspace/website-snapshot-model.mjs} +13 -13
- package/{frontend/src/lib/analysis/workspace-archive-crypto.js → packages/workspace/workspace-archive-crypto.mjs} +49 -19
- package/{frontend/src/lib/analysis/workspace-archive.js → packages/workspace/workspace-archive.mjs} +110 -89
- package/third-party-notices.txt +14 -14
- package/frontend/src/lib/analysis/bulk-retry-plan.js +0 -79
- package/frontend/src/lib/analysis/bulk-source-coverage.js +0 -76
- package/frontend/src/lib/analysis/case-migration-model.js +0 -305
- package/frontend/src/lib/analysis/case-record-model.js +0 -9
- package/frontend/src/lib/analysis/case-response-model.js +0 -728
- package/frontend/src/lib/analysis/case-response-packet.js +0 -583
- package/frontend/src/lib/analysis/lookup-decision-support.js +0 -542
- package/frontend/src/lib/analysis/lookup-investigation-brief.js +0 -153
- package/frontend/src/lib/analysis/lookup-presentation.js +0 -120
- package/frontend/src/lib/analysis/lookup-response.js +0 -2
- package/frontend/src/lib/analysis/lookup-source-refresh.js +0 -277
- package/frontend/src/lib/analysis/lookup-summary-model.js +0 -398
- package/frontend/src/lib/analysis/scoring.js +0 -55
- package/frontend/src/lib/analysis/utils.js +0 -255
- package/frontend/src/lib/analysis/visualization-bounds.js +0 -26
- package/frontend/src/lib/analysis/visualization-force-graph.js +0 -352
- package/frontend/src/lib/analysis/visualization-matrix.js +0 -131
- package/frontend/src/lib/analysis/visualization-models.js +0 -338
- package/frontend/src/lib/analysis/visualization-time-series.js +0 -185
- package/lib/bounded-json-response.mjs +0 -170
- package/lib/lookup-response-contract.mjs +0 -1034
- package/lib/observation.mjs +0 -115
- /package/{frontend/src/lib/analysis/opaque-reference-id.js → packages/cases/opaque-reference-id.mjs} +0 -0
- /package/{frontend/src/lib/analysis/acquisition-due-diligence.js → packages/investigation/acquisition-due-diligence.mjs} +0 -0
- /package/{frontend/src/lib/analysis/evidence-coverage-ledger.js → packages/investigation/evidence-coverage-ledger.mjs} +0 -0
- /package/{frontend/src/lib/analysis/dns-record-normalization.js → packages/workspace/dns-record-normalization.mjs} +0 -0
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
// Environment-neutral browser/server JSON response boundary. It enforces a
|
|
2
|
-
// declared and streamed byte ceiling before parsing and can apply one deadline
|
|
3
|
-
// across both the fetch and body-read phases.
|
|
4
|
-
export const SMALL_JSON_RESPONSE_BYTES = 64 * 1024;
|
|
5
|
-
export const STANDARD_JSON_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
6
|
-
export const LARGE_JSON_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
7
|
-
export const DEFAULT_JSON_RESPONSE_TIMEOUT_MS = 40_000;
|
|
8
|
-
const MAX_JSON_RESPONSE_TIMEOUT_MS = 120_000;
|
|
9
|
-
export class BoundedJsonResponseError extends Error {
|
|
10
|
-
code;
|
|
11
|
-
constructor(code, message) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.name = 'BoundedJsonResponseError';
|
|
14
|
-
this.code = code;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
async function raceWithAbort(promise, signal, onLateResolution) {
|
|
18
|
-
if (signal.aborted)
|
|
19
|
-
throw signal.reason ?? new Error('Request aborted.');
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
let aborted = false;
|
|
22
|
-
const onAbort = () => {
|
|
23
|
-
aborted = true;
|
|
24
|
-
reject(signal.reason ?? new Error('Request aborted.'));
|
|
25
|
-
};
|
|
26
|
-
signal.addEventListener('abort', onAbort, { once: true });
|
|
27
|
-
void promise.then((value) => {
|
|
28
|
-
signal.removeEventListener('abort', onAbort);
|
|
29
|
-
if (aborted) {
|
|
30
|
-
void Promise.resolve(onLateResolution?.(value)).catch(() => { });
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
resolve(value);
|
|
34
|
-
}, (cause) => {
|
|
35
|
-
signal.removeEventListener('abort', onAbort);
|
|
36
|
-
reject(cause);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
function boundedPositiveInteger(value, fallback, maximum) {
|
|
41
|
-
return typeof value === 'number' && Number.isFinite(value)
|
|
42
|
-
? Math.max(1, Math.min(maximum, Math.round(value)))
|
|
43
|
-
: fallback;
|
|
44
|
-
}
|
|
45
|
-
export async function readJsonResponseCapped(response, maximumBytes = STANDARD_JSON_RESPONSE_BYTES, signal, validateRawJson) {
|
|
46
|
-
const maxBytes = boundedPositiveInteger(maximumBytes, STANDARD_JSON_RESPONSE_BYTES, LARGE_JSON_RESPONSE_BYTES);
|
|
47
|
-
const declared = response.headers.get('content-length');
|
|
48
|
-
if (declared && /^\d+$/u.test(declared)) {
|
|
49
|
-
const bytes = Number(declared);
|
|
50
|
-
if (!Number.isSafeInteger(bytes) || bytes > maxBytes) {
|
|
51
|
-
await response.body?.cancel().catch(() => { });
|
|
52
|
-
throw new BoundedJsonResponseError('response_too_large', `JSON response exceeded ${maxBytes} bytes.`);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
if (!response.body)
|
|
56
|
-
return null;
|
|
57
|
-
const reader = response.body.getReader();
|
|
58
|
-
const cancelOnAbort = () => { void reader.cancel(signal?.reason).catch(() => { }); };
|
|
59
|
-
signal?.addEventListener('abort', cancelOnAbort, { once: true });
|
|
60
|
-
const chunks = [];
|
|
61
|
-
let total = 0;
|
|
62
|
-
try {
|
|
63
|
-
while (true) {
|
|
64
|
-
const read = reader.read();
|
|
65
|
-
const { done, value } = signal ? await raceWithAbort(read, signal) : await read;
|
|
66
|
-
if (done)
|
|
67
|
-
break;
|
|
68
|
-
if (!value)
|
|
69
|
-
continue;
|
|
70
|
-
total += value.byteLength;
|
|
71
|
-
if (total > maxBytes) {
|
|
72
|
-
await reader.cancel().catch(() => { });
|
|
73
|
-
throw new BoundedJsonResponseError('response_too_large', `JSON response exceeded ${maxBytes} bytes.`);
|
|
74
|
-
}
|
|
75
|
-
chunks.push(value);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
finally {
|
|
79
|
-
signal?.removeEventListener('abort', cancelOnAbort);
|
|
80
|
-
reader.releaseLock();
|
|
81
|
-
}
|
|
82
|
-
const bytes = new Uint8Array(total);
|
|
83
|
-
let offset = 0;
|
|
84
|
-
for (const chunk of chunks) {
|
|
85
|
-
bytes.set(chunk, offset);
|
|
86
|
-
offset += chunk.byteLength;
|
|
87
|
-
}
|
|
88
|
-
let raw;
|
|
89
|
-
try {
|
|
90
|
-
raw = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
throw new BoundedJsonResponseError('invalid_json', 'Response body was not valid UTF-8.');
|
|
94
|
-
}
|
|
95
|
-
try {
|
|
96
|
-
validateRawJson?.(raw);
|
|
97
|
-
}
|
|
98
|
-
catch {
|
|
99
|
-
throw new BoundedJsonResponseError('invalid_json', 'Response body did not satisfy the bounded JSON structure contract.');
|
|
100
|
-
}
|
|
101
|
-
try {
|
|
102
|
-
return JSON.parse(raw);
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
throw new BoundedJsonResponseError('invalid_json', 'Response body was not valid JSON.');
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
export async function requestJsonCapped(input, init = {}, options = {}) {
|
|
109
|
-
const timeoutMs = boundedPositiveInteger(options.timeoutMs, DEFAULT_JSON_RESPONSE_TIMEOUT_MS, MAX_JSON_RESPONSE_TIMEOUT_MS);
|
|
110
|
-
const controller = new AbortController();
|
|
111
|
-
const upstreamSignal = init.signal;
|
|
112
|
-
const forwardAbort = () => controller.abort(upstreamSignal?.reason);
|
|
113
|
-
if (upstreamSignal?.aborted)
|
|
114
|
-
forwardAbort();
|
|
115
|
-
else
|
|
116
|
-
upstreamSignal?.addEventListener('abort', forwardAbort, { once: true });
|
|
117
|
-
const timeoutReason = Object.freeze({ type: 'bounded-json-timeout' });
|
|
118
|
-
const timeout = setTimeout(() => controller.abort(timeoutReason), timeoutMs);
|
|
119
|
-
try {
|
|
120
|
-
if (controller.signal.aborted) {
|
|
121
|
-
throw new BoundedJsonResponseError('aborted', 'Request was cancelled.');
|
|
122
|
-
}
|
|
123
|
-
const fetchRequest = (options.fetchImpl ?? fetch)(input, {
|
|
124
|
-
...init,
|
|
125
|
-
signal: controller.signal,
|
|
126
|
-
});
|
|
127
|
-
const response = await raceWithAbort(fetchRequest, controller.signal, async (lateResponse) => lateResponse.body?.cancel().catch(() => { }));
|
|
128
|
-
const contentType = response.headers.get('content-type')?.toLowerCase() ?? '';
|
|
129
|
-
const plausibleJson = !contentType
|
|
130
|
-
|| contentType.includes('application/json')
|
|
131
|
-
|| contentType.includes('+json');
|
|
132
|
-
if (options.allowNonJsonErrorResponse !== false && !response.ok && !plausibleJson) {
|
|
133
|
-
await response.body?.cancel().catch(() => { });
|
|
134
|
-
return { response, body: null };
|
|
135
|
-
}
|
|
136
|
-
let body;
|
|
137
|
-
try {
|
|
138
|
-
body = await readJsonResponseCapped(response, options.maximumBytes, controller.signal, options.validateRawJson);
|
|
139
|
-
}
|
|
140
|
-
catch (cause) {
|
|
141
|
-
// Reverse proxies and hosting adapters can replace an upstream JSON
|
|
142
|
-
// error with a bounded HTML or plain-text response. Preserve the HTTP
|
|
143
|
-
// status so callers can apply retry and generic error handling, while
|
|
144
|
-
// continuing to require valid JSON for successful responses.
|
|
145
|
-
if (options.allowNonJsonErrorResponse !== false
|
|
146
|
-
&& !response.ok
|
|
147
|
-
&& cause instanceof BoundedJsonResponseError
|
|
148
|
-
&& cause.code === 'invalid_json') {
|
|
149
|
-
body = null;
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
throw cause;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return { response, body };
|
|
156
|
-
}
|
|
157
|
-
catch (cause) {
|
|
158
|
-
if (controller.signal.aborted) {
|
|
159
|
-
const timedOut = controller.signal.reason === timeoutReason;
|
|
160
|
-
throw new BoundedJsonResponseError(timedOut ? 'timeout' : 'aborted', timedOut ? `Request timed out after ${timeoutMs} ms.` : 'Request was cancelled.');
|
|
161
|
-
}
|
|
162
|
-
if (cause instanceof BoundedJsonResponseError)
|
|
163
|
-
throw cause;
|
|
164
|
-
throw cause;
|
|
165
|
-
}
|
|
166
|
-
finally {
|
|
167
|
-
clearTimeout(timeout);
|
|
168
|
-
upstreamSignal?.removeEventListener('abort', forwardAbort);
|
|
169
|
-
}
|
|
170
|
-
}
|