@apifuse/provider-sdk 2.2.0-beta.62 → 2.2.0-beta.63
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/AUTHORING.md +268 -9
- package/CHANGELOG.md +4 -0
- package/README.md +1 -0
- package/bin/apifuse-check.ts +84 -2
- package/bin/apifuse-dev.ts +11 -31
- package/bin/apifuse-migrate-deployment.ts +200 -0
- package/bin/apifuse-pack-check.ts +11 -4
- package/bin/apifuse-pack-types.ts +187 -4
- package/bin/apifuse-record.ts +44 -32
- package/bin/apifuse-test.ts +3 -1
- package/dist/cli/commands.d.ts +1 -1
- package/dist/cli/commands.js +11 -0
- package/dist/cli/deployment-intent.d.ts +178 -0
- package/dist/cli/deployment-intent.js +277 -0
- package/dist/cli/migrate-deployment-intent.d.ts +132 -0
- package/dist/cli/migrate-deployment-intent.js +1552 -0
- package/dist/cli/migrate-provider-shape.d.ts +5 -1
- package/dist/cli/migrate-provider-shape.js +4 -2
- package/dist/cli/resolver-runtime.d.ts +21 -0
- package/dist/cli/resolver-runtime.js +31 -0
- package/dist/define.d.ts +3 -0
- package/dist/define.js +5 -0
- package/dist/dev.d.ts +3 -1
- package/dist/dev.js +6 -1
- package/dist/engine.d.ts +35 -1
- package/dist/engine.js +21 -2
- package/dist/error-resolution.d.ts +1 -0
- package/dist/error-resolution.js +54 -0
- package/dist/errors.d.ts +39 -1
- package/dist/errors.js +50 -0
- package/dist/i18n/error-messages.d.ts +86 -0
- package/dist/i18n/error-messages.js +192 -0
- package/dist/i18n/index.d.ts +1 -0
- package/dist/i18n/index.js +1 -0
- package/dist/i18n/keys.d.ts +12 -0
- package/dist/i18n/keys.js +76 -5
- package/dist/index.d.ts +7 -1
- package/dist/index.js +6 -0
- package/dist/lint.d.ts +10 -0
- package/dist/lint.js +412 -49
- package/dist/provider.d.ts +5 -5
- package/dist/provider.js +2 -2
- package/dist/runtime/browser-telemetry-binding.d.ts +5 -0
- package/dist/runtime/browser-telemetry-binding.js +83 -0
- package/dist/runtime/browser-telemetry.d.ts +76 -0
- package/dist/runtime/browser-telemetry.js +165 -0
- package/dist/runtime/browser.d.ts +3 -0
- package/dist/runtime/browser.js +208 -47
- package/dist/runtime/cache-telemetry.d.ts +71 -0
- package/dist/runtime/cache-telemetry.js +177 -0
- package/dist/runtime/cache.js +67 -7
- package/dist/runtime/capability-response.d.ts +3 -0
- package/dist/runtime/capability-response.js +56 -0
- package/dist/runtime/capability-telemetry.d.ts +46 -0
- package/dist/runtime/capability-telemetry.js +68 -0
- package/dist/runtime/diagnostic-env.d.ts +3 -0
- package/dist/runtime/diagnostic-env.js +10 -1
- package/dist/runtime/engine-mode.d.ts +74 -0
- package/dist/runtime/engine-mode.js +152 -0
- package/dist/runtime/http-telemetry-guard.d.ts +10 -0
- package/dist/runtime/http-telemetry-guard.js +62 -10
- package/dist/runtime/http.js +141 -35
- package/dist/runtime/instrumentation.js +92 -13
- package/dist/runtime/ocr-telemetry.d.ts +82 -0
- package/dist/runtime/ocr-telemetry.js +192 -0
- package/dist/runtime/ocr.js +30 -8
- package/dist/runtime/request-telemetry.d.ts +2 -0
- package/dist/runtime/request-telemetry.js +2 -1
- package/dist/runtime/resolver-runtime-options.d.ts +14 -0
- package/dist/runtime/resolver-runtime-options.js +33 -0
- package/dist/runtime/resolver-shared.d.ts +3 -2
- package/dist/runtime/resolver-shared.js +4 -4
- package/dist/runtime/resolver-telemetry.d.ts +1 -0
- package/dist/runtime/resolver-telemetry.js +1 -1
- package/dist/runtime/resolver-vendors/browser.d.ts +2 -0
- package/dist/runtime/resolver-vendors/browser.js +46 -0
- package/dist/runtime/resolver-vendors/hosts.d.ts +21 -0
- package/dist/runtime/resolver-vendors/hosts.js +35 -0
- package/dist/runtime/resolver-vendors/hypersolutions.js +2 -2
- package/dist/runtime/resolver-vendors/types.d.ts +5 -4
- package/dist/runtime/resolver.d.ts +4 -1
- package/dist/runtime/resolver.js +46 -13
- package/dist/runtime/state-telemetry.d.ts +79 -0
- package/dist/runtime/state-telemetry.js +194 -0
- package/dist/runtime/state.d.ts +3 -0
- package/dist/runtime/state.js +26 -7
- package/dist/runtime/stealth-cookies.d.ts +5 -1
- package/dist/runtime/stealth-cookies.js +21 -1
- package/dist/runtime/stealth-owned-headers.d.ts +26 -0
- package/dist/runtime/stealth-owned-headers.js +37 -0
- package/dist/runtime/stealth-telemetry.d.ts +92 -0
- package/dist/runtime/stealth-telemetry.js +179 -0
- package/dist/runtime/stealth.d.ts +4 -1
- package/dist/runtime/stealth.js +228 -85
- package/dist/runtime/stt-telemetry.d.ts +77 -0
- package/dist/runtime/stt-telemetry.js +176 -0
- package/dist/runtime/stt.js +15 -6
- package/dist/server/error-stack-frames.d.ts +35 -0
- package/dist/server/error-stack-frames.js +219 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/index.js +4 -0
- package/dist/server/sdk-version.d.ts +3 -0
- package/dist/server/sdk-version.js +19 -0
- package/dist/server/self-test.js +1 -18
- package/dist/server/sensitive-values.d.ts +1 -1
- package/dist/server/sensitive-values.js +9 -0
- package/dist/server/serve-implementation.d.ts +51 -2
- package/dist/server/serve-implementation.js +337 -90
- package/dist/server/types.d.ts +1 -0
- package/dist/server/types.js +7 -0
- package/dist/stateful/stateful-provider-owner-forwarder.js +22 -0
- package/dist/stateful/stateful-provider-runtime-context.d.ts +3 -0
- package/dist/stateful/stateful-provider-runtime-context.js +1 -0
- package/dist/types.d.ts +94 -1
- package/package.json +6 -1
- package/src/cli/commands.ts +14 -0
- package/src/cli/deployment-intent.ts +364 -0
- package/src/cli/migrate-deployment-intent.ts +1908 -0
- package/src/cli/migrate-provider-shape.ts +10 -4
- package/src/cli/resolver-runtime.ts +72 -0
- package/src/define.ts +13 -0
- package/src/dev.ts +9 -2
- package/src/engine.ts +38 -2
- package/src/error-resolution.ts +58 -0
- package/src/errors.ts +77 -1
- package/src/i18n/error-messages.ts +255 -0
- package/src/i18n/index.ts +1 -0
- package/src/i18n/keys.ts +80 -6
- package/src/index.ts +72 -0
- package/src/lint.ts +522 -50
- package/src/provider.ts +10 -0
- package/src/runtime/browser-telemetry-binding.ts +92 -0
- package/src/runtime/browser-telemetry.ts +289 -0
- package/src/runtime/browser.ts +249 -65
- package/src/runtime/cache-telemetry.ts +247 -0
- package/src/runtime/cache.ts +68 -17
- package/src/runtime/capability-response.ts +53 -0
- package/src/runtime/capability-telemetry.ts +101 -0
- package/src/runtime/diagnostic-env.ts +11 -1
- package/src/runtime/engine-mode.ts +233 -0
- package/src/runtime/http-telemetry-guard.ts +66 -13
- package/src/runtime/http.ts +168 -37
- package/src/runtime/instrumentation.ts +105 -16
- package/src/runtime/ocr-telemetry.ts +308 -0
- package/src/runtime/ocr.ts +109 -74
- package/src/runtime/request-telemetry.ts +2 -1
- package/src/runtime/resolver-runtime-options.ts +50 -0
- package/src/runtime/resolver-shared.ts +9 -4
- package/src/runtime/resolver-telemetry.ts +1 -1
- package/src/runtime/resolver-vendors/browser.ts +65 -7
- package/src/runtime/resolver-vendors/hosts.ts +43 -0
- package/src/runtime/resolver-vendors/hypersolutions.ts +2 -2
- package/src/runtime/resolver-vendors/types.ts +5 -4
- package/src/runtime/resolver.ts +64 -21
- package/src/runtime/state-telemetry.ts +298 -0
- package/src/runtime/state.ts +46 -45
- package/src/runtime/stealth-cookies.ts +24 -1
- package/src/runtime/stealth-owned-headers.ts +41 -0
- package/src/runtime/stealth-telemetry.ts +304 -0
- package/src/runtime/stealth.ts +355 -150
- package/src/runtime/stt-telemetry.ts +282 -0
- package/src/runtime/stt.ts +93 -71
- package/src/server/error-stack-frames.ts +214 -0
- package/src/server/index.ts +53 -0
- package/src/server/sdk-version.ts +22 -0
- package/src/server/self-test.ts +1 -21
- package/src/server/sensitive-values.ts +14 -0
- package/src/server/serve-implementation.ts +569 -108
- package/src/server/types.ts +7 -0
- package/src/stateful/stateful-provider-owner-forwarder.ts +23 -0
- package/src/stateful/stateful-provider-runtime-context.ts +4 -0
- package/src/types.ts +99 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/approval-override.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/codemod-syntax.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/connection-precedence.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-a.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-b.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-ambiguous-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-computed.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-a.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-b.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-cycle-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-barrel.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-catalog.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-docs.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-daiso-stores.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-indirect-config.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-nonstatic.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-leaf.ts.txt +0 -10
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-one.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-reexport-two.ts.txt +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-one.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-composed-two.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-mixed-index.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-runtime-registry.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-barrel.ts.txt +0 -2
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-index.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/discovery-star-package-leaf.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/docs-conflict.ts.txt +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-hoisted-array-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-imported-array-spread.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-kebab-operation-id.ts.txt +0 -17
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-map.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-mixed-array-spread.ts.txt +0 -24
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-operation.ts.txt +0 -16
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/examples-snake-operation-id.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-duplicate-provider.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-id-unresolved.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-map.ts.txt +0 -3
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-many.ts.txt +0 -18
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/factory-one-to-one.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoist-all.ts.txt +0 -31
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/hoisted-const.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/imported-spread.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-map.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-cast-tail.ts.txt +0 -21
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-ekitan.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/inline-spread-override.ts.txt +0 -14
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-en.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ja.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-canonical-ko.json +0 -1
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/locale-existing-operation-namespace-en.json +0 -8
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/missing-english-locale.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/no-safety.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/non-literal.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/redundant-approval.ts.txt +0 -6
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-binding-ambiguous.ts.txt +0 -12
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported-other.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-imported.ts.txt +0 -5
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-key-ambiguous.ts.txt +0 -19
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-shorthand.ts.txt +0 -9
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-typed.ts.txt +0 -11
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/registry-unrelated.ts.txt +0 -13
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/safety-conflict.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/stream.ts.txt +0 -7
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/tool-router-spread.ts.txt +0 -15
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/unparseable.ts.txt +0 -4
- package/src/cli/__tests__/fixtures/migrate-operation-declaration/verbatim-template.ts.txt +0 -12
package/src/runtime/stealth.ts
CHANGED
|
@@ -37,6 +37,8 @@ import type {
|
|
|
37
37
|
StealthSession,
|
|
38
38
|
} from "../types.js";
|
|
39
39
|
import { chrome149HeaderOrder } from "./chrome149-header-order.js";
|
|
40
|
+
import { registerDiagnosticValue } from "./diagnostic-env.js";
|
|
41
|
+
import { isStealthOwnedHeaderName } from "./stealth-owned-headers.js";
|
|
40
42
|
import {
|
|
41
43
|
ENGINE_CEREMONY_EGRESS_LEASE,
|
|
42
44
|
type CeremonyEgressBinding,
|
|
@@ -90,6 +92,22 @@ import {
|
|
|
90
92
|
} from "./stealth-akamai-sbsd.js";
|
|
91
93
|
import { StealthCookieJar } from "./stealth-cookies.js";
|
|
92
94
|
|
|
95
|
+
export type {
|
|
96
|
+
StealthTelemetryAttemptEvent,
|
|
97
|
+
StealthTelemetryAttemptKind,
|
|
98
|
+
StealthTelemetryDiagnostics,
|
|
99
|
+
StealthTelemetryErrorCode,
|
|
100
|
+
StealthTelemetryRequestClass,
|
|
101
|
+
StealthTelemetrySbsdEvent,
|
|
102
|
+
StealthTelemetrySbsdOutcome,
|
|
103
|
+
StealthTelemetrySink,
|
|
104
|
+
} from "./stealth-telemetry.js";
|
|
105
|
+
import type {
|
|
106
|
+
StealthTelemetryAttemptKind,
|
|
107
|
+
StealthTelemetryErrorCode,
|
|
108
|
+
StealthTelemetrySink,
|
|
109
|
+
} from "./stealth-telemetry.js";
|
|
110
|
+
|
|
93
111
|
export const DEFAULT_STEALTH_PROFILE: StealthProfileDescriptor = Object.freeze({
|
|
94
112
|
browser: DEFAULT_STEALTH_BROWSER,
|
|
95
113
|
os: DEFAULT_STEALTH_OS,
|
|
@@ -141,6 +159,8 @@ function sensitiveQueryParamNames(url: string): string[] {
|
|
|
141
159
|
}
|
|
142
160
|
|
|
143
161
|
export type StealthClientOptions = ProxyResolutionOptions & {
|
|
162
|
+
/** Request-scoped stealth transport observations. */
|
|
163
|
+
stealthTelemetry?: StealthTelemetrySink;
|
|
144
164
|
warn?: (message: string) => void;
|
|
145
165
|
/** Abort all requests issued by this client. */
|
|
146
166
|
signal?: AbortSignal;
|
|
@@ -373,16 +393,6 @@ function normalizedHeaderEntries(
|
|
|
373
393
|
return entries;
|
|
374
394
|
}
|
|
375
395
|
|
|
376
|
-
const SDK_OWNED_EXACT_CHROME_HEADERS = new Set([
|
|
377
|
-
"host",
|
|
378
|
-
"connection",
|
|
379
|
-
"user-agent",
|
|
380
|
-
"sec-ch-ua",
|
|
381
|
-
"sec-ch-ua-mobile",
|
|
382
|
-
"sec-ch-ua-platform",
|
|
383
|
-
"accept-encoding",
|
|
384
|
-
]);
|
|
385
|
-
|
|
386
396
|
// Non-pseudo-header order of real Chrome 149. The fixture captures
|
|
387
397
|
// (chrome-ground-truth-capture.json, chrome-extended-capture.json,
|
|
388
398
|
// h1-casing-capture.json) were taken through Playwright's `locale` option, which
|
|
@@ -558,7 +568,7 @@ function normalizedCallerHeaderEntriesFromRecord(headers: Record<string, string>
|
|
|
558
568
|
|
|
559
569
|
function assertCallerHeadersSupported(entries: readonly HeaderTuple[]): void {
|
|
560
570
|
for (const [name] of entries) {
|
|
561
|
-
if (
|
|
571
|
+
if (isStealthOwnedHeaderName(name)) {
|
|
562
572
|
throw new SDKError(`Stealth transport owns the "${name}" header; remove it from headers.`, {
|
|
563
573
|
code: "STEALTH_HEADER_OVERRIDE_UNSUPPORTED",
|
|
564
574
|
});
|
|
@@ -1210,6 +1220,123 @@ function discardStealthRedirectBody(response: StealthTransportResponse): void {
|
|
|
1210
1220
|
}
|
|
1211
1221
|
}
|
|
1212
1222
|
|
|
1223
|
+
/** Telemetry must never replace a transport result, including with caller-provided sinks. */
|
|
1224
|
+
function emitStealthTelemetry(
|
|
1225
|
+
sink: StealthTelemetrySink | undefined,
|
|
1226
|
+
record: (sink: StealthTelemetrySink) => void,
|
|
1227
|
+
): void {
|
|
1228
|
+
if (!sink) return;
|
|
1229
|
+
try {
|
|
1230
|
+
record(sink);
|
|
1231
|
+
} catch {
|
|
1232
|
+
/* The request owns its result. */
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
type StealthExchangeTelemetry = {
|
|
1237
|
+
sink: StealthTelemetrySink;
|
|
1238
|
+
profileId: StealthProfileDescriptor;
|
|
1239
|
+
proxyUsed: boolean;
|
|
1240
|
+
kind: StealthTelemetryAttemptKind;
|
|
1241
|
+
cookieJar?: StealthCookieJar;
|
|
1242
|
+
};
|
|
1243
|
+
|
|
1244
|
+
function stripStealthCookieMaterial(text: string, cookieNames: readonly string[]): string {
|
|
1245
|
+
// Header-shaped Cookie/Set-Cookie material is redacted wholesale, including
|
|
1246
|
+
// foreign names. Bare pairs outside a header are limited to jar-known names:
|
|
1247
|
+
// a foreign bare name is indistinguishable from benign key=value prose and is
|
|
1248
|
+
// therefore covered only when layer 1 registered its value.
|
|
1249
|
+
let result = text.replace(
|
|
1250
|
+
/(^|[^\p{L}\p{N}_-])[\t ]*(?:cookie|set-cookie)[\t ]*(?::|=)[^\r\n]*/giu,
|
|
1251
|
+
"$1[REDACTED]",
|
|
1252
|
+
);
|
|
1253
|
+
result = result.replace(
|
|
1254
|
+
/"(?:cookie|set-cookie)"[\t ]*:[\t ]*"(?:\\.|[^"\\])*"/giu,
|
|
1255
|
+
"[REDACTED]",
|
|
1256
|
+
);
|
|
1257
|
+
for (const name of cookieNames) {
|
|
1258
|
+
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1259
|
+
result = result.replace(
|
|
1260
|
+
new RegExp(`(^|[;,&?\\s])${escaped}\\s*=\\s*[^;,\\s&\\r\\n]+`, "giu"),
|
|
1261
|
+
"$1[REDACTED]",
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
return result;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
function startStealthExchange(
|
|
1268
|
+
telemetry: StealthExchangeTelemetry | undefined,
|
|
1269
|
+
method: StealthMethod,
|
|
1270
|
+
options: StealthFetchOptions,
|
|
1271
|
+
signal?: AbortSignal,
|
|
1272
|
+
): (status?: number, error?: unknown) => void {
|
|
1273
|
+
if (!telemetry) return () => {};
|
|
1274
|
+
const startedAt = Date.now();
|
|
1275
|
+
const requestClass = chromeRequestClass(method, options.stealth?.requestClass);
|
|
1276
|
+
let recorded = false;
|
|
1277
|
+
return (status, error) => {
|
|
1278
|
+
if (recorded) return;
|
|
1279
|
+
recorded = true;
|
|
1280
|
+
emitStealthTelemetry(telemetry?.sink, (sink) => {
|
|
1281
|
+
let code: string | undefined;
|
|
1282
|
+
if (error !== undefined) {
|
|
1283
|
+
try {
|
|
1284
|
+
code = signal?.aborted
|
|
1285
|
+
? "transport_cancelled"
|
|
1286
|
+
: normalizeStealthTransportError(error).code;
|
|
1287
|
+
} catch {
|
|
1288
|
+
code = "other";
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
const knownCodes: readonly string[] = [
|
|
1292
|
+
"transport_network_error",
|
|
1293
|
+
"transport_timeout",
|
|
1294
|
+
"transport_cancelled",
|
|
1295
|
+
"upstream_http_error",
|
|
1296
|
+
"response_too_large",
|
|
1297
|
+
"proxy_connect_failed",
|
|
1298
|
+
"PROXY_POOL_STALE",
|
|
1299
|
+
"PROXY_EDGE_AUTH_REJECTED",
|
|
1300
|
+
"PROXY_AUTH_IP_DENIED",
|
|
1301
|
+
"PROXY_EDGE_TLS_REJECTED",
|
|
1302
|
+
"PROXY_REQUIRED",
|
|
1303
|
+
];
|
|
1304
|
+
const errorCode = code
|
|
1305
|
+
? knownCodes.includes(code)
|
|
1306
|
+
? (code as StealthTelemetryErrorCode)
|
|
1307
|
+
: "other"
|
|
1308
|
+
: status !== undefined && status >= 400
|
|
1309
|
+
? "upstream_http_error"
|
|
1310
|
+
: undefined;
|
|
1311
|
+
const strip = (text: string) =>
|
|
1312
|
+
stripStealthCookieMaterial(text, telemetry.cookieJar?.names() ?? []);
|
|
1313
|
+
sink.recordAttempt({
|
|
1314
|
+
ms: Date.now() - startedAt,
|
|
1315
|
+
profileId: telemetry.profileId,
|
|
1316
|
+
proxyUsed: telemetry.proxyUsed,
|
|
1317
|
+
kind: telemetry.kind,
|
|
1318
|
+
requestClass:
|
|
1319
|
+
requestClass === "navigation" && options.stealth?.userActivation === false
|
|
1320
|
+
? "script_navigation"
|
|
1321
|
+
: requestClass,
|
|
1322
|
+
...(status === undefined ? {} : { status }),
|
|
1323
|
+
...(errorCode ? { errorCode } : {}),
|
|
1324
|
+
...(error === undefined
|
|
1325
|
+
? {}
|
|
1326
|
+
: {
|
|
1327
|
+
diagnostics: {
|
|
1328
|
+
name: strip(error instanceof Error ? error.name : "Error"),
|
|
1329
|
+
message: strip(error instanceof Error ? error.message : String(error)),
|
|
1330
|
+
...(error instanceof Error && "code" in error && typeof error.code === "string"
|
|
1331
|
+
? { code: strip(error.code) }
|
|
1332
|
+
: {}),
|
|
1333
|
+
},
|
|
1334
|
+
}),
|
|
1335
|
+
});
|
|
1336
|
+
});
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1213
1340
|
async function fetchStealthRedirectChain(
|
|
1214
1341
|
transport: WreqSession,
|
|
1215
1342
|
cookieJar: StealthCookieJar,
|
|
@@ -1223,6 +1350,7 @@ async function fetchStealthRedirectChain(
|
|
|
1223
1350
|
body: string | Buffer | undefined,
|
|
1224
1351
|
headers: Record<string, string>,
|
|
1225
1352
|
) => HeaderTuple[],
|
|
1353
|
+
telemetry?: StealthExchangeTelemetry,
|
|
1226
1354
|
): Promise<{ normalized: StealthResponse; response: StealthTransportResponse }> {
|
|
1227
1355
|
let currentUrl = requestUrl;
|
|
1228
1356
|
let currentMethod = method;
|
|
@@ -1232,86 +1360,102 @@ async function fetchStealthRedirectChain(
|
|
|
1232
1360
|
let response: StealthTransportResponse;
|
|
1233
1361
|
const deadline = options.timeout ? performance.now() + options.timeout : undefined;
|
|
1234
1362
|
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1363
|
+
let finishExchange: ReturnType<typeof startStealthExchange> | undefined;
|
|
1364
|
+
let status: number | undefined;
|
|
1365
|
+
let exchangeError: unknown;
|
|
1366
|
+
try {
|
|
1367
|
+
while (true) {
|
|
1368
|
+
throwIfAmbientAborted(signal);
|
|
1369
|
+
const headers = { ...currentHeaders };
|
|
1370
|
+
if (!hasHeader(headers, "cookie")) {
|
|
1371
|
+
const cookieHeader = cookieJar.toHeader(currentUrl);
|
|
1372
|
+
if (cookieHeader) headers.cookie = cookieHeader;
|
|
1373
|
+
}
|
|
1374
|
+
const requestInit: StealthRequestInit = {
|
|
1375
|
+
headers: buildHeaders
|
|
1376
|
+
? buildHeaders(currentUrl, currentMethod, currentBody, headers)
|
|
1377
|
+
: headers,
|
|
1378
|
+
method: currentMethod,
|
|
1379
|
+
redirect: "manual",
|
|
1380
|
+
...(new URL(currentUrl).protocol === "http:" ? { disableDefaultHeaders: true } : {}),
|
|
1381
|
+
...(signal ? { signal } : {}),
|
|
1382
|
+
};
|
|
1383
|
+
if (currentBody !== undefined) requestInit.body = currentBody;
|
|
1252
1384
|
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1385
|
+
await transport.clearCookies();
|
|
1386
|
+
throwIfAmbientAborted(signal);
|
|
1387
|
+
const remainingTimeout =
|
|
1388
|
+
deadline === undefined ? undefined : Math.ceil(deadline - performance.now());
|
|
1389
|
+
if (remainingTimeout !== undefined && remainingTimeout <= 0) {
|
|
1390
|
+
throw new TransportError("Request timed out", {
|
|
1391
|
+
code: "transport_timeout",
|
|
1392
|
+
status: 0,
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
if (remainingTimeout !== undefined) requestInit.timeout = remainingTimeout;
|
|
1396
|
+
status = undefined;
|
|
1397
|
+
finishExchange = startStealthExchange(telemetry, currentMethod, options, signal);
|
|
1398
|
+
response = await transport.fetch(currentUrl, requestInit);
|
|
1399
|
+
status = response.status;
|
|
1400
|
+
if (signal?.aborted) {
|
|
1401
|
+
discardStealthRedirectBody(response);
|
|
1402
|
+
throw toAmbientCancellationError(signal);
|
|
1403
|
+
}
|
|
1404
|
+
cookieJar.setFromCookieStrings(
|
|
1405
|
+
setCookieHeadersFromResponse(response.headers),
|
|
1406
|
+
response.url ?? currentUrl,
|
|
1407
|
+
);
|
|
1408
|
+
|
|
1409
|
+
if (!isRedirectStatus(response.status) || options.redirect === "manual") break;
|
|
1410
|
+
if (options.redirect === "error") {
|
|
1411
|
+
discardStealthRedirectBody(response);
|
|
1412
|
+
throw new TransportError("Stealth request encountered a redirect", {
|
|
1413
|
+
code: "transport_network_error",
|
|
1414
|
+
status: 0,
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1273
1417
|
|
|
1274
|
-
|
|
1275
|
-
|
|
1418
|
+
const nextUrl = resolveRedirectUrl(
|
|
1419
|
+
response.headers.get("location") ?? undefined,
|
|
1420
|
+
response.url ?? currentUrl,
|
|
1421
|
+
);
|
|
1422
|
+
if (!nextUrl) break;
|
|
1423
|
+
if (followedHops >= MAX_STEALTH_REDIRECT_HOPS) {
|
|
1424
|
+
discardStealthRedirectBody(response);
|
|
1425
|
+
throw new TransportError(
|
|
1426
|
+
`Stealth request exceeded the ${MAX_STEALTH_REDIRECT_HOPS}-redirect limit`,
|
|
1427
|
+
{ code: "transport_network_error", status: 0 },
|
|
1428
|
+
);
|
|
1429
|
+
}
|
|
1430
|
+
assertStealthRedirectUrl(nextUrl);
|
|
1276
1431
|
discardStealthRedirectBody(response);
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1432
|
+
const nextMethod = nextRedirectMethod(response.status, currentMethod);
|
|
1433
|
+
if (nextMethod !== currentMethod) {
|
|
1434
|
+
currentBody = undefined;
|
|
1435
|
+
currentHeaders = withoutRedirectBodyHeaders(currentHeaders);
|
|
1436
|
+
}
|
|
1437
|
+
currentMethod = nextMethod;
|
|
1438
|
+
currentUrl = nextUrl;
|
|
1439
|
+
followedHops += 1;
|
|
1440
|
+
emitStealthTelemetry(telemetry?.sink, (sink) => sink.recordRedirectHop());
|
|
1441
|
+
finishExchange(status);
|
|
1442
|
+
finishExchange = undefined;
|
|
1281
1443
|
}
|
|
1282
1444
|
|
|
1283
|
-
const
|
|
1284
|
-
response
|
|
1285
|
-
|
|
1445
|
+
const normalized = await normalizeResponseWithSignal(
|
|
1446
|
+
response,
|
|
1447
|
+
currentUrl,
|
|
1448
|
+
options.maxBodyBytes,
|
|
1449
|
+
signal,
|
|
1286
1450
|
);
|
|
1287
|
-
if (
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
}
|
|
1295
|
-
assertStealthRedirectUrl(nextUrl);
|
|
1296
|
-
discardStealthRedirectBody(response);
|
|
1297
|
-
const nextMethod = nextRedirectMethod(response.status, currentMethod);
|
|
1298
|
-
if (nextMethod !== currentMethod) {
|
|
1299
|
-
currentBody = undefined;
|
|
1300
|
-
currentHeaders = withoutRedirectBodyHeaders(currentHeaders);
|
|
1301
|
-
}
|
|
1302
|
-
currentMethod = nextMethod;
|
|
1303
|
-
currentUrl = nextUrl;
|
|
1304
|
-
followedHops += 1;
|
|
1451
|
+
if (followedHops > 0) normalized.redirected = true;
|
|
1452
|
+
return { normalized, response };
|
|
1453
|
+
} catch (error) {
|
|
1454
|
+
exchangeError = error;
|
|
1455
|
+
throw error;
|
|
1456
|
+
} finally {
|
|
1457
|
+
finishExchange?.(status, exchangeError);
|
|
1305
1458
|
}
|
|
1306
|
-
|
|
1307
|
-
const normalized = await normalizeResponseWithSignal(
|
|
1308
|
-
response,
|
|
1309
|
-
currentUrl,
|
|
1310
|
-
options.maxBodyBytes,
|
|
1311
|
-
signal,
|
|
1312
|
-
);
|
|
1313
|
-
if (followedHops > 0) normalized.redirected = true;
|
|
1314
|
-
return { normalized, response };
|
|
1315
1459
|
}
|
|
1316
1460
|
|
|
1317
1461
|
function createSessionFetcher(
|
|
@@ -1323,7 +1467,7 @@ function createSessionFetcher(
|
|
|
1323
1467
|
let closed = false;
|
|
1324
1468
|
let hasWarnedMissingProxy = false;
|
|
1325
1469
|
const warn = clientOptions.warn ?? console.warn;
|
|
1326
|
-
const cookieJar = new StealthCookieJar([], baseUrl);
|
|
1470
|
+
const cookieJar = new StealthCookieJar([], baseUrl, registerDiagnosticValue);
|
|
1327
1471
|
const akamaiSbsdState: AkamaiSbsdSessionState = { transactions: new Map() };
|
|
1328
1472
|
const challengedReplays = new WeakMap<StealthResponse, ChallengedReplayRecord>();
|
|
1329
1473
|
const ceremonyEgressLease = clientOptions[ENGINE_CEREMONY_EGRESS_LEASE];
|
|
@@ -1558,9 +1702,12 @@ function createSessionFetcher(
|
|
|
1558
1702
|
// rotation after a transport failure). Its response reached the origin from an
|
|
1559
1703
|
// egress the handle does not name; accepting it would split the ceremony identity.
|
|
1560
1704
|
if (attemptProxy.url !== lease.binding.proxyUrl) {
|
|
1561
|
-
throw new SDKError(
|
|
1562
|
-
|
|
1563
|
-
|
|
1705
|
+
throw new SDKError(
|
|
1706
|
+
"The response arrived on an egress other than the ceremony's bound endpoint",
|
|
1707
|
+
{
|
|
1708
|
+
code: "EGRESS_LEASE_BINDING_INVALID",
|
|
1709
|
+
},
|
|
1710
|
+
);
|
|
1564
1711
|
}
|
|
1565
1712
|
return;
|
|
1566
1713
|
}
|
|
@@ -1718,6 +1865,10 @@ function createSessionFetcher(
|
|
|
1718
1865
|
attemptResponse: StealthTransportResponse,
|
|
1719
1866
|
attemptNormalized: StealthResponse,
|
|
1720
1867
|
): StealthResponse => {
|
|
1868
|
+
if (attemptNormalized.challenge)
|
|
1869
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) =>
|
|
1870
|
+
sink.recordSbsd(attemptNormalized.challenge!.outcome),
|
|
1871
|
+
);
|
|
1721
1872
|
if (
|
|
1722
1873
|
!attemptNormalized.challenge &&
|
|
1723
1874
|
attemptResponse.status >= 400 &&
|
|
@@ -1854,6 +2005,7 @@ function createSessionFetcher(
|
|
|
1854
2005
|
fetchSignal: AbortSignal | undefined,
|
|
1855
2006
|
orderedHeaders = buildOrderedHeaders,
|
|
1856
2007
|
sessionDefaultHeaders = defaultHeaders,
|
|
2008
|
+
kind: StealthTelemetryAttemptKind = "request",
|
|
1857
2009
|
) =>
|
|
1858
2010
|
withClient(
|
|
1859
2011
|
requestProfile,
|
|
@@ -1868,6 +2020,15 @@ function createSessionFetcher(
|
|
|
1868
2020
|
fetchOptions,
|
|
1869
2021
|
fetchSignal,
|
|
1870
2022
|
orderedHeaders,
|
|
2023
|
+
clientOptions.stealthTelemetry
|
|
2024
|
+
? {
|
|
2025
|
+
sink: clientOptions.stealthTelemetry,
|
|
2026
|
+
profileId: requestProfile,
|
|
2027
|
+
proxyUsed: Boolean(proxy),
|
|
2028
|
+
kind,
|
|
2029
|
+
cookieJar,
|
|
2030
|
+
}
|
|
2031
|
+
: undefined,
|
|
1871
2032
|
),
|
|
1872
2033
|
fetchSignal,
|
|
1873
2034
|
sessionDefaultHeaders,
|
|
@@ -1928,7 +2089,14 @@ function createSessionFetcher(
|
|
|
1928
2089
|
akamaiSbsdState,
|
|
1929
2090
|
)
|
|
1930
2091
|
: undefined;
|
|
2092
|
+
if (akamaiSbsd && !detected)
|
|
2093
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) =>
|
|
2094
|
+
sink.recordSbsd({ detected: false }),
|
|
2095
|
+
);
|
|
1931
2096
|
if (detected && akamaiSbsd) {
|
|
2097
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) =>
|
|
2098
|
+
sink.recordSbsd("detected"),
|
|
2099
|
+
);
|
|
1932
2100
|
if (challengeSolveAttempted || challengeRefetchAttempted) {
|
|
1933
2101
|
normalized.challenge = {
|
|
1934
2102
|
challenge: detected,
|
|
@@ -2020,6 +2188,7 @@ function createSessionFetcher(
|
|
|
2020
2188
|
init.body,
|
|
2021
2189
|
normalizeHeaders(transportHeaders),
|
|
2022
2190
|
),
|
|
2191
|
+
"resolver",
|
|
2023
2192
|
);
|
|
2024
2193
|
return {
|
|
2025
2194
|
status: result.normalized.status,
|
|
@@ -2057,54 +2226,57 @@ function createSessionFetcher(
|
|
|
2057
2226
|
const reuseCompletedSuccess =
|
|
2058
2227
|
explicitReplay && akamaiSbsdState.completedSuccessKey === transactionKey;
|
|
2059
2228
|
if (reuseCompletedSuccess) akamaiSbsdState.completedSuccessKey = undefined;
|
|
2060
|
-
|
|
2229
|
+
let ownsTransaction = false;
|
|
2061
2230
|
if (!reuseCompletedSuccess) {
|
|
2062
2231
|
let transaction = akamaiSbsdState.transactions.get(transactionKey);
|
|
2063
|
-
|
|
2232
|
+
if (!transaction) {
|
|
2064
2233
|
akamaiSbsdState.completedSuccessKey = undefined;
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2234
|
+
challengeSolveAttempted = true;
|
|
2235
|
+
ownsTransaction = true;
|
|
2236
|
+
// The solve spans several round trips, so it runs under the client's ambient
|
|
2237
|
+
// signal and the resolver's own timeouts, not this fetch's per-request `timeout`.
|
|
2238
|
+
transaction = {
|
|
2239
|
+
result: akamaiSbsd
|
|
2240
|
+
.solve(
|
|
2241
|
+
detected,
|
|
2242
|
+
resolverTransport,
|
|
2243
|
+
clientOptions.signal ?? new AbortController().signal,
|
|
2244
|
+
)
|
|
2245
|
+
.then(
|
|
2246
|
+
() => ({ solved: true }) as const,
|
|
2247
|
+
(error: unknown) => ({ solved: false, error }) as const,
|
|
2248
|
+
)
|
|
2249
|
+
.finally(() => {
|
|
2250
|
+
akamaiSbsdState.transactions.delete(transactionKey);
|
|
2251
|
+
}),
|
|
2252
|
+
};
|
|
2253
|
+
akamaiSbsdState.transactions.set(transactionKey, transaction);
|
|
2254
|
+
}
|
|
2255
|
+
const transactionResult = await transaction.result;
|
|
2256
|
+
if (!transactionResult.solved) {
|
|
2257
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) =>
|
|
2258
|
+
sink.recordSbsd("solve_failed"),
|
|
2259
|
+
);
|
|
2260
|
+
if (ownsTransaction) {
|
|
2261
|
+
// The proxy delivered the challenged response; the resolver failed.
|
|
2262
|
+
// Surface that failure as-is: it is not a transport fault to normalize
|
|
2263
|
+
// or retry.
|
|
2092
2264
|
if (!explicitReplay) {
|
|
2093
2265
|
recordProxyAttempt("ok", undefined, challenged.response.status);
|
|
2094
2266
|
}
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2267
|
+
challengeSolveFailure = { error: transactionResult.error };
|
|
2268
|
+
throw challengeSolveFailure;
|
|
2269
|
+
}
|
|
2098
2270
|
return {
|
|
2099
2271
|
normalized: {
|
|
2100
2272
|
...challenged.normalized,
|
|
2101
2273
|
challenge: { challenge: detected, outcome: "solve_failed" },
|
|
2102
2274
|
},
|
|
2103
2275
|
response: challenged.response,
|
|
2104
|
-
|
|
2276
|
+
};
|
|
2105
2277
|
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2278
|
+
}
|
|
2279
|
+
challengeRefetchAttempted = true;
|
|
2108
2280
|
// An explicit replay is a new transport exchange on the bound endpoint and
|
|
2109
2281
|
// gets its own proxy-attempt record timed from here, not from the initiating
|
|
2110
2282
|
// fetch (the caller's think time in between is not transport duration); the
|
|
@@ -2122,28 +2294,35 @@ function createSessionFetcher(
|
|
|
2122
2294
|
attemptRecorded = false;
|
|
2123
2295
|
attemptStartedAt = Date.now();
|
|
2124
2296
|
}
|
|
2297
|
+
if (!explicitReplay)
|
|
2298
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) =>
|
|
2299
|
+
sink.recordSafeRefetch(),
|
|
2300
|
+
);
|
|
2125
2301
|
const replayed = await fetchOnBoundSession(
|
|
2126
|
-
|
|
2127
|
-
|
|
2302
|
+
requestUrl,
|
|
2303
|
+
method,
|
|
2128
2304
|
replayOptions,
|
|
2129
|
-
|
|
2305
|
+
clientOptions.signal,
|
|
2130
2306
|
);
|
|
2131
2307
|
throwProxyTransportFault(replayed.response, replayed.normalized.body);
|
|
2132
|
-
|
|
2308
|
+
const persisted = detectAkamaiSbsdChallenge(
|
|
2133
2309
|
replayed.normalized,
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2310
|
+
requestUrl,
|
|
2311
|
+
cookieJar,
|
|
2312
|
+
akamaiSbsd.allowedHosts,
|
|
2313
|
+
akamaiSbsdState,
|
|
2314
|
+
);
|
|
2315
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) =>
|
|
2316
|
+
sink.recordSbsd(persisted ? "challenge_persisted" : "refetch_clear"),
|
|
2317
|
+
);
|
|
2318
|
+
if (persisted) {
|
|
2140
2319
|
replayed.normalized.challenge = {
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2320
|
+
challenge: persisted,
|
|
2321
|
+
outcome: "challenge_persisted",
|
|
2322
|
+
};
|
|
2144
2323
|
} else if (ownsTransaction && !explicitReplay) {
|
|
2145
2324
|
akamaiSbsdState.completedSuccessKey = transactionKey;
|
|
2146
|
-
|
|
2325
|
+
}
|
|
2147
2326
|
return replayed;
|
|
2148
2327
|
};
|
|
2149
2328
|
|
|
@@ -2156,18 +2335,18 @@ function createSessionFetcher(
|
|
|
2156
2335
|
consumed: false,
|
|
2157
2336
|
generation: attemptEgressGeneration,
|
|
2158
2337
|
async replay() {
|
|
2159
|
-
|
|
2338
|
+
try {
|
|
2160
2339
|
const replayed = await solveAndReplay(true);
|
|
2161
2340
|
return finalizeAttempt(replayed.response, replayed.normalized);
|
|
2162
2341
|
} catch (error) {
|
|
2163
2342
|
const normalizedError = normalizeAttemptError(error);
|
|
2164
2343
|
releaseFailedCeremonyEgress(proxy, normalizedError);
|
|
2165
2344
|
throw recordAttemptFailure(normalizedError);
|
|
2166
|
-
|
|
2345
|
+
}
|
|
2167
2346
|
},
|
|
2168
2347
|
});
|
|
2169
2348
|
return finalizeAttempt(response, normalized);
|
|
2170
|
-
|
|
2349
|
+
}
|
|
2171
2350
|
({ normalized, response } = await solveAndReplay(false));
|
|
2172
2351
|
}
|
|
2173
2352
|
|
|
@@ -2264,6 +2443,7 @@ function createSessionFetcher(
|
|
|
2264
2443
|
refreshAttempt < MAX_POLICY_PROXY_POOL_REFRESHES
|
|
2265
2444
|
) {
|
|
2266
2445
|
throwIfAmbientAborted(clientOptions.signal);
|
|
2446
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) => sink.recordPoolRefresh());
|
|
2267
2447
|
await invalidateProxyResolutionCacheAsync({
|
|
2268
2448
|
proxyPolicy: clientOptions.proxyPolicy,
|
|
2269
2449
|
upstream: clientOptions.upstream,
|
|
@@ -2512,6 +2692,7 @@ function createSessionFetcher(
|
|
|
2512
2692
|
if (decision.nextMethod !== method) {
|
|
2513
2693
|
body = undefined;
|
|
2514
2694
|
}
|
|
2695
|
+
emitStealthTelemetry(clientOptions.stealthTelemetry, (sink) => sink.recordRedirectHop());
|
|
2515
2696
|
method = decision.nextMethod;
|
|
2516
2697
|
currentUrl = decision.nextUrl;
|
|
2517
2698
|
}
|
|
@@ -2564,18 +2745,42 @@ function createSessionFetcher(
|
|
|
2564
2745
|
throwIfAmbientAborted(clientOptions.signal);
|
|
2565
2746
|
await client.clearCookies();
|
|
2566
2747
|
throwIfAmbientAborted(clientOptions.signal);
|
|
2567
|
-
const
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2748
|
+
const finishExchange = startStealthExchange(
|
|
2749
|
+
clientOptions.stealthTelemetry
|
|
2750
|
+
? {
|
|
2751
|
+
sink: clientOptions.stealthTelemetry,
|
|
2752
|
+
profileId: profile,
|
|
2753
|
+
proxyUsed: true,
|
|
2754
|
+
kind: "proxy_diagnostic",
|
|
2755
|
+
cookieJar,
|
|
2756
|
+
}
|
|
2757
|
+
: undefined,
|
|
2758
|
+
"GET",
|
|
2759
|
+
{},
|
|
2576
2760
|
clientOptions.signal,
|
|
2577
2761
|
);
|
|
2578
|
-
|
|
2762
|
+
let status: number | undefined;
|
|
2763
|
+
let exchangeError: unknown;
|
|
2764
|
+
try {
|
|
2765
|
+
const response = await client.fetch(PROXY_AUTH_DIAGNOSTIC_URL, {
|
|
2766
|
+
method: "GET",
|
|
2767
|
+
timeout: PROXY_AUTH_DIAGNOSTIC_TIMEOUT_MS,
|
|
2768
|
+
...(clientOptions.signal ? { signal: clientOptions.signal } : {}),
|
|
2769
|
+
});
|
|
2770
|
+
status = response.status;
|
|
2771
|
+
const normalized = await normalizeResponseWithSignal(
|
|
2772
|
+
response,
|
|
2773
|
+
undefined,
|
|
2774
|
+
undefined,
|
|
2775
|
+
clientOptions.signal,
|
|
2776
|
+
);
|
|
2777
|
+
return classifyProxyAuthDiagnosticMessage(normalized.body);
|
|
2778
|
+
} catch (error) {
|
|
2779
|
+
exchangeError = error;
|
|
2780
|
+
throw error;
|
|
2781
|
+
} finally {
|
|
2782
|
+
finishExchange(status, exchangeError);
|
|
2783
|
+
}
|
|
2579
2784
|
},
|
|
2580
2785
|
clientOptions.signal,
|
|
2581
2786
|
);
|