@apifuse/provider-sdk 2.2.0-beta.16 → 2.2.0-beta.18
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 +40 -0
- package/CHANGELOG.md +9 -0
- package/dist/config/loader.d.ts +19 -0
- package/dist/config/loader.js +59 -28
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/native-address.d.ts +43 -0
- package/dist/native-address.js +281 -0
- package/dist/native-egress-policy.d.ts +4 -0
- package/dist/native-egress-policy.js +86 -23
- package/dist/provider.d.ts +1 -1
- package/dist/provider.js +1 -1
- package/dist/runtime/native-network.d.ts +46 -7
- package/dist/runtime/native-network.js +590 -114
- package/dist/runtime/proxy-nodemaven.d.ts +7 -0
- package/dist/runtime/proxy-nodemaven.js +5 -5
- package/dist/server/serve.js +3 -1
- package/dist/types.d.ts +10 -1
- package/package.json +1 -1
- package/src/config/loader.ts +110 -18
- package/src/index.ts +5 -0
- package/src/native-address.ts +340 -0
- package/src/native-egress-policy.ts +105 -32
- package/src/provider.ts +5 -0
- package/src/runtime/native-network.ts +770 -136
- package/src/runtime/proxy-nodemaven.ts +13 -5
- package/src/server/serve.ts +8 -1
- package/src/types.ts +10 -1
|
@@ -3,6 +3,11 @@ export declare const NODEMAVEN_USERNAME_ENV = "APIFUSE__PROXY__NODEMAVEN_USERNAM
|
|
|
3
3
|
export declare const NODEMAVEN_PASSWORD_ENV = "APIFUSE__PROXY__NODEMAVEN_PASSWORD";
|
|
4
4
|
export declare const NODEMAVEN_FILTER_ENV = "APIFUSE__PROXY__NODEMAVEN_FILTER";
|
|
5
5
|
export declare const NODEMAVEN_GATEWAY_HOST = "gate.nodemaven.com";
|
|
6
|
+
export type NodemavenCredentials = {
|
|
7
|
+
readonly username: string;
|
|
8
|
+
readonly password: string;
|
|
9
|
+
readonly filter?: string;
|
|
10
|
+
};
|
|
6
11
|
/** Both schemes tunnel bytes end-to-end, preserving the client TLS handshake. */
|
|
7
12
|
export type ProxyProtocol = "http" | "socks5";
|
|
8
13
|
/**
|
|
@@ -23,6 +28,8 @@ export type NodemavenSessionWindow = {
|
|
|
23
28
|
export declare function nodemavenSessionWindow(policy: ProviderProxyPolicy, now?: number): NodemavenSessionWindow;
|
|
24
29
|
export type NodemavenSynthesisInput = {
|
|
25
30
|
policy: ProviderProxyPolicy;
|
|
31
|
+
/** Explicit credentials; synthesis never reads process-global state. */
|
|
32
|
+
credentials: NodemavenCredentials;
|
|
26
33
|
affinityKey: string | undefined;
|
|
27
34
|
protocol: ProxyProtocol;
|
|
28
35
|
poolIndex: number;
|
|
@@ -30,8 +30,8 @@ function readNodemavenUsername() {
|
|
|
30
30
|
function readNodemavenPassword() {
|
|
31
31
|
return process.env[NODEMAVEN_PASSWORD_ENV]?.trim() || undefined;
|
|
32
32
|
}
|
|
33
|
-
function resolveNodemavenFilter() {
|
|
34
|
-
const raw =
|
|
33
|
+
function resolveNodemavenFilter(value) {
|
|
34
|
+
const raw = value?.trim().toLowerCase();
|
|
35
35
|
if (!raw)
|
|
36
36
|
return DEFAULT_NODEMAVEN_FILTER;
|
|
37
37
|
if (!NODEMAVEN_FILTERS.has(raw)) {
|
|
@@ -97,12 +97,12 @@ function selectPort(protocol, sid, poolIndex) {
|
|
|
97
97
|
* There is no allocation API — geo/session are encoded in the username.
|
|
98
98
|
*/
|
|
99
99
|
export function synthesizeNodemavenProxy(input) {
|
|
100
|
-
const username =
|
|
101
|
-
const password =
|
|
100
|
+
const username = input.credentials.username.trim();
|
|
101
|
+
const password = input.credentials.password.trim();
|
|
102
102
|
if (!username || !password) {
|
|
103
103
|
throw new Error(`NodeMaven credentials missing: set ${NODEMAVEN_USERNAME_ENV} and ${NODEMAVEN_PASSWORD_ENV}.`);
|
|
104
104
|
}
|
|
105
|
-
const filter = resolveNodemavenFilter();
|
|
105
|
+
const filter = resolveNodemavenFilter(input.credentials.filter);
|
|
106
106
|
const sid = deriveSid(input.policy, input.affinityKey, input.poolIndex, input.refreshEpoch);
|
|
107
107
|
const port = selectPort(input.protocol, sid, input.poolIndex);
|
|
108
108
|
const lifetimeMinutes = nodemavenLifetimeMinutes(input.policy);
|
package/dist/server/serve.js
CHANGED
|
@@ -16,7 +16,7 @@ import { createEnvContext } from "../runtime/env.js";
|
|
|
16
16
|
import { executeOperation } from "../runtime/executor.js";
|
|
17
17
|
import { createHttpClient } from "../runtime/http.js";
|
|
18
18
|
import { wrapWithInstrumentation } from "../runtime/instrumentation.js";
|
|
19
|
-
import { createNativeNetworkClient } from "../runtime/native-network.js";
|
|
19
|
+
import { createEnvVendorCredentialResolver, createNativeNetworkClient, } from "../runtime/native-network.js";
|
|
20
20
|
import { getProviderBaseUrl } from "../runtime/provider.js";
|
|
21
21
|
import { PROXY_AUTH_IP_DENIED_CODE, PROXY_EDGE_AUTH_REJECTED_CODE, PROXY_POOL_EXHAUSTED_CODE, } from "../runtime/proxy-errors.js";
|
|
22
22
|
import { PROVIDER_TELEMETRY_HEADER, ProxyTelemetryCollector } from "../runtime/proxy-telemetry.js";
|
|
@@ -225,6 +225,7 @@ function createProviderContext(provider, request, operationId, options = {}, sta
|
|
|
225
225
|
egress: provider.native.network,
|
|
226
226
|
proxyPolicy: resolveNativeProxyPolicy(provider),
|
|
227
227
|
affinityKey: proxyClientOptions.affinityKey,
|
|
228
|
+
credentials: createEnvVendorCredentialResolver(env),
|
|
228
229
|
}),
|
|
229
230
|
},
|
|
230
231
|
}
|
|
@@ -312,6 +313,7 @@ function createAuthFlowContext(provider, request, options = {}, signal) {
|
|
|
312
313
|
egress: provider.native.network,
|
|
313
314
|
proxyPolicy: resolveNativeProxyPolicy(provider),
|
|
314
315
|
affinityKey: proxyClientOptions.affinityKey,
|
|
316
|
+
credentials: createEnvVendorCredentialResolver(createEnvContext(provider.secrets?.map((secret) => secret.name))),
|
|
315
317
|
}),
|
|
316
318
|
},
|
|
317
319
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1089,6 +1089,11 @@ export interface NativeTcpEgressRule {
|
|
|
1089
1089
|
/**
|
|
1090
1090
|
* Bounded native TCP egress discovered through a declared bootstrap endpoint.
|
|
1091
1091
|
* Host suffixes are exact DNS suffixes, not wildcard patterns.
|
|
1092
|
+
* Dynamic rules must declare at least one target host selector through
|
|
1093
|
+
* targetHostSuffixes, targetIpv4Cidrs, and/or targetIpv6Cidrs. Literal grant
|
|
1094
|
+
* sources and targets match only same-family selectors (except exact
|
|
1095
|
+
* sourceHost); DNS names match only host/suffix selectors. IPv4-mapped and
|
|
1096
|
+
* IPv4-compatible IPv6 literals are authorized only by IPv4 CIDRs.
|
|
1092
1097
|
*
|
|
1093
1098
|
* Dynamic rules are ordered. The first rule whose source, target, port, and TLS
|
|
1094
1099
|
* selectors match exclusively owns the grant; its ttlMs and maxGrants bounds
|
|
@@ -1099,9 +1104,13 @@ export interface NativeTcpEgressRule {
|
|
|
1099
1104
|
export interface NativeTcpDynamicEgressRule {
|
|
1100
1105
|
readonly sourceHost?: string;
|
|
1101
1106
|
readonly sourceHostSuffixes?: readonly string[];
|
|
1107
|
+
readonly sourceIpv4Cidrs?: readonly string[];
|
|
1108
|
+
readonly sourceIpv6Cidrs?: readonly string[];
|
|
1102
1109
|
readonly sourcePorts?: readonly number[];
|
|
1103
1110
|
readonly sourcePortRanges?: readonly NativeTcpPortRange[];
|
|
1104
|
-
readonly targetHostSuffixes
|
|
1111
|
+
readonly targetHostSuffixes?: readonly string[];
|
|
1112
|
+
readonly targetIpv4Cidrs?: readonly string[];
|
|
1113
|
+
readonly targetIpv6Cidrs?: readonly string[];
|
|
1105
1114
|
readonly targetPorts?: readonly number[];
|
|
1106
1115
|
readonly targetPortRanges?: readonly NativeTcpPortRange[];
|
|
1107
1116
|
readonly tls: NativeTcpTlsMode;
|
package/package.json
CHANGED
package/src/config/loader.ts
CHANGED
|
@@ -7,7 +7,10 @@ import { Redis } from "ioredis";
|
|
|
7
7
|
import type { ProviderProxyPolicy, ProviderProxyProvider, TraceConfig } from "../types.js";
|
|
8
8
|
import {
|
|
9
9
|
NODEMAVEN_DEFAULT_PROTOCOL,
|
|
10
|
+
NODEMAVEN_FILTER_ENV,
|
|
10
11
|
NODEMAVEN_MAX_POOL_SIZE,
|
|
12
|
+
NODEMAVEN_PASSWORD_ENV,
|
|
13
|
+
NODEMAVEN_USERNAME_ENV,
|
|
11
14
|
type ProxyProtocol,
|
|
12
15
|
hasNodemavenCredentials,
|
|
13
16
|
nodemavenPoolSize,
|
|
@@ -683,7 +686,7 @@ export async function resolveProxy(
|
|
|
683
686
|
* for smartproxy, and is the only protocol ctx.http (Bun native fetch) supports.
|
|
684
687
|
* Override per call via ProxyResolutionOptions.protocol (harness/tests).
|
|
685
688
|
*/
|
|
686
|
-
const VENDOR_DEFAULT_PROTOCOL: Record<ProxyVendorName, ProxyProtocol
|
|
689
|
+
export const VENDOR_DEFAULT_PROTOCOL: Readonly<Record<ProxyVendorName, ProxyProtocol>> = {
|
|
687
690
|
smartproxy: "http",
|
|
688
691
|
nodemaven: NODEMAVEN_DEFAULT_PROTOCOL,
|
|
689
692
|
};
|
|
@@ -708,21 +711,59 @@ export function assertTunnelingScheme(url: string): void {
|
|
|
708
711
|
}
|
|
709
712
|
}
|
|
710
713
|
|
|
711
|
-
|
|
714
|
+
export type ProxyVendorResolutionContext = {
|
|
715
|
+
readonly protocol: ProxyProtocol;
|
|
716
|
+
readonly poolIndex: number;
|
|
717
|
+
readonly refreshEpoch: number;
|
|
718
|
+
/** Explicit vendor credentials. Omit only on the legacy ambient-env path. */
|
|
719
|
+
readonly credentials?: Readonly<Record<string, string>>;
|
|
720
|
+
/** Disable non-policy env defaults for deterministic injected adapters. */
|
|
721
|
+
readonly ambientDefaults?: boolean;
|
|
722
|
+
/** Disable env-discovered Redis sharing for deterministic injected adapters. */
|
|
723
|
+
readonly sharedCache?: boolean;
|
|
724
|
+
};
|
|
725
|
+
|
|
726
|
+
export async function resolveWithVendor(
|
|
712
727
|
vendor: ProxyVendorName,
|
|
713
728
|
policy: ProviderProxyPolicy,
|
|
714
729
|
options: ProxyResolutionOptions,
|
|
715
|
-
context:
|
|
730
|
+
context: ProxyVendorResolutionContext,
|
|
716
731
|
): Promise<ResolvedProxyConfig> {
|
|
717
732
|
if (vendor === "nodemaven") {
|
|
718
733
|
const startedAt = Date.now();
|
|
734
|
+
const username = (
|
|
735
|
+
context.credentials === undefined
|
|
736
|
+
? process.env[NODEMAVEN_USERNAME_ENV]
|
|
737
|
+
: context.credentials[NODEMAVEN_USERNAME_ENV]
|
|
738
|
+
)?.trim();
|
|
739
|
+
const password = (
|
|
740
|
+
context.credentials === undefined
|
|
741
|
+
? process.env[NODEMAVEN_PASSWORD_ENV]
|
|
742
|
+
: context.credentials[NODEMAVEN_PASSWORD_ENV]
|
|
743
|
+
)?.trim();
|
|
744
|
+
const filter =
|
|
745
|
+
context.credentials === undefined
|
|
746
|
+
? process.env[NODEMAVEN_FILTER_ENV]
|
|
747
|
+
: context.credentials[NODEMAVEN_FILTER_ENV];
|
|
748
|
+
if (!username || !password) {
|
|
749
|
+
throw new ProxyResolutionError(
|
|
750
|
+
"PROXY_ALLOCATION_FAILED",
|
|
751
|
+
`NodeMaven credentials missing: set ${NODEMAVEN_USERNAME_ENV} and ${NODEMAVEN_PASSWORD_ENV}.`,
|
|
752
|
+
{ vendor: "nodemaven" },
|
|
753
|
+
);
|
|
754
|
+
}
|
|
719
755
|
const synthesized = synthesizeNodemavenProxy({
|
|
720
756
|
policy,
|
|
757
|
+
credentials: {
|
|
758
|
+
username,
|
|
759
|
+
password,
|
|
760
|
+
...(filter ? { filter } : {}),
|
|
761
|
+
},
|
|
721
762
|
affinityKey: options.affinityKey,
|
|
722
763
|
protocol: context.protocol,
|
|
723
764
|
poolIndex: context.poolIndex,
|
|
724
765
|
refreshEpoch: context.refreshEpoch,
|
|
725
|
-
country: resolveSmartproxyCountry(policy),
|
|
766
|
+
country: resolveSmartproxyCountry(policy, context.ambientDefaults !== false),
|
|
726
767
|
});
|
|
727
768
|
options.telemetry?.recordProxyResolution({
|
|
728
769
|
provider: "nodemaven",
|
|
@@ -746,7 +787,11 @@ async function resolveWithVendor(
|
|
|
746
787
|
}
|
|
747
788
|
|
|
748
789
|
// smartproxy allocation-style vendor.
|
|
749
|
-
const appKey =
|
|
790
|
+
const appKey = (
|
|
791
|
+
context.credentials === undefined
|
|
792
|
+
? process.env[SMARTPROXY_APP_KEY_ENV]
|
|
793
|
+
: context.credentials[SMARTPROXY_APP_KEY_ENV]
|
|
794
|
+
)?.trim();
|
|
750
795
|
if (!appKey) {
|
|
751
796
|
// Guarded by vendorHasCredentials; treated as a vendor-internal failure.
|
|
752
797
|
throw new ProxyResolutionError(
|
|
@@ -755,13 +800,15 @@ async function resolveWithVendor(
|
|
|
755
800
|
{ vendor: "smartproxy" },
|
|
756
801
|
);
|
|
757
802
|
}
|
|
758
|
-
const lifetimeMinutes = resolveSmartproxyLifetime(policy);
|
|
803
|
+
const lifetimeMinutes = resolveSmartproxyLifetime(policy, context.ambientDefaults !== false);
|
|
759
804
|
const allocated = await allocateSmartproxy(
|
|
760
805
|
policy,
|
|
761
806
|
appKey,
|
|
762
807
|
lifetimeMinutes,
|
|
763
808
|
options.affinityKey,
|
|
764
809
|
context.protocol,
|
|
810
|
+
context.ambientDefaults !== false,
|
|
811
|
+
context.sharedCache !== false,
|
|
765
812
|
);
|
|
766
813
|
options.telemetry?.recordProxyResolution({ ...allocated.telemetry, protocol: context.protocol });
|
|
767
814
|
const poolIndex = selectProxyPoolIndex(allocated.pool.urls.length, context.poolIndex);
|
|
@@ -985,15 +1032,22 @@ export function mapFlatAttempt(
|
|
|
985
1032
|
return { vendorIndex: 0, poolIndex: 0 };
|
|
986
1033
|
}
|
|
987
1034
|
|
|
988
|
-
function resolveSmartproxyCountry(
|
|
1035
|
+
function resolveSmartproxyCountry(
|
|
1036
|
+
policy: ProviderProxyPolicy,
|
|
1037
|
+
ambientDefaults = true,
|
|
1038
|
+
): string | undefined {
|
|
989
1039
|
return (
|
|
990
|
-
policy.geo?.country ??
|
|
1040
|
+
policy.geo?.country ??
|
|
1041
|
+
(ambientDefaults
|
|
1042
|
+
? process.env[DEFAULT_PROXY_COUNTRY_ENV]?.trim().toUpperCase() || undefined
|
|
1043
|
+
: undefined)
|
|
991
1044
|
);
|
|
992
1045
|
}
|
|
993
1046
|
|
|
994
|
-
function resolveSmartproxyLifetime(policy: ProviderProxyPolicy): number {
|
|
1047
|
+
function resolveSmartproxyLifetime(policy: ProviderProxyPolicy, ambientDefaults = true): number {
|
|
995
1048
|
const configuredLifetime =
|
|
996
|
-
policy.session?.lifetimeMinutes ??
|
|
1049
|
+
policy.session?.lifetimeMinutes ??
|
|
1050
|
+
(ambientDefaults ? readPositiveNumberEnv(DEFAULT_PROXY_LIFETIME_ENV, 30) : 30);
|
|
997
1051
|
return Math.min(SMARTPROXY_MAX_LIFETIME_MINUTES, Math.max(1, Math.floor(configuredLifetime)));
|
|
998
1052
|
}
|
|
999
1053
|
|
|
@@ -1024,15 +1078,21 @@ function selectProxyPoolIndex(poolSize: number, attempt = 0): number {
|
|
|
1024
1078
|
|
|
1025
1079
|
function buildSmartproxyCacheKey(
|
|
1026
1080
|
policy: ProviderProxyPolicy,
|
|
1081
|
+
appKey: string,
|
|
1027
1082
|
affinityKey: string | undefined,
|
|
1028
1083
|
lifetimeMinutes: number,
|
|
1029
1084
|
protocol: ProxyProtocol,
|
|
1085
|
+
ambientDefaults = true,
|
|
1030
1086
|
): string {
|
|
1031
1087
|
const poolSize = resolveSmartproxyPoolSize(policy);
|
|
1032
1088
|
return JSON.stringify({
|
|
1033
1089
|
provider: "smartproxy",
|
|
1090
|
+
credentialHash: createHash("sha256")
|
|
1091
|
+
.update("apifuse-smartproxy-credential:v1\0")
|
|
1092
|
+
.update(appKey)
|
|
1093
|
+
.digest("hex"),
|
|
1034
1094
|
protocol,
|
|
1035
|
-
country: resolveSmartproxyCountry(policy),
|
|
1095
|
+
country: resolveSmartproxyCountry(policy, ambientDefaults),
|
|
1036
1096
|
affinity: policy.session?.affinity ?? "request",
|
|
1037
1097
|
affinityKey: (policy.session?.affinity ?? "request") === "request" ? undefined : affinityKey,
|
|
1038
1098
|
lifetimeMinutes,
|
|
@@ -1046,8 +1106,17 @@ async function allocateSmartproxy(
|
|
|
1046
1106
|
lifetimeMinutes: number,
|
|
1047
1107
|
affinityKey: string | undefined,
|
|
1048
1108
|
protocol: ProxyProtocol,
|
|
1109
|
+
ambientDefaults = true,
|
|
1110
|
+
sharedCache = true,
|
|
1049
1111
|
): Promise<SmartproxyAllocationResult> {
|
|
1050
|
-
const cacheKey = buildSmartproxyCacheKey(
|
|
1112
|
+
const cacheKey = buildSmartproxyCacheKey(
|
|
1113
|
+
policy,
|
|
1114
|
+
appKey,
|
|
1115
|
+
affinityKey,
|
|
1116
|
+
lifetimeMinutes,
|
|
1117
|
+
protocol,
|
|
1118
|
+
ambientDefaults,
|
|
1119
|
+
);
|
|
1051
1120
|
const startedAt = Date.now();
|
|
1052
1121
|
const now = startedAt;
|
|
1053
1122
|
const invalidatedUntil = invalidatedProxyKeys.get(cacheKey) ?? 0;
|
|
@@ -1055,7 +1124,15 @@ async function allocateSmartproxy(
|
|
|
1055
1124
|
const cached = proxyCache.get(cacheKey);
|
|
1056
1125
|
if (!skipCached && cached && isFresh(cached, now)) {
|
|
1057
1126
|
if (shouldSoftRefresh(cached, now)) {
|
|
1058
|
-
void refreshSmartproxyPool(
|
|
1127
|
+
void refreshSmartproxyPool(
|
|
1128
|
+
cacheKey,
|
|
1129
|
+
policy,
|
|
1130
|
+
appKey,
|
|
1131
|
+
lifetimeMinutes,
|
|
1132
|
+
protocol,
|
|
1133
|
+
ambientDefaults,
|
|
1134
|
+
sharedCache,
|
|
1135
|
+
);
|
|
1059
1136
|
return {
|
|
1060
1137
|
pool: cached,
|
|
1061
1138
|
telemetry: telemetryForPool(cached, "soft_stale_refresh", startedAt, {
|
|
@@ -1069,7 +1146,7 @@ async function allocateSmartproxy(
|
|
|
1069
1146
|
};
|
|
1070
1147
|
}
|
|
1071
1148
|
|
|
1072
|
-
if (!skipCached) {
|
|
1149
|
+
if (!skipCached && sharedCache) {
|
|
1073
1150
|
const redisResult = await readSmartproxyRedisPool(cacheKey, startedAt);
|
|
1074
1151
|
if (redisResult) return redisResult;
|
|
1075
1152
|
}
|
|
@@ -1092,6 +1169,8 @@ async function allocateSmartproxy(
|
|
|
1092
1169
|
lifetimeMinutes,
|
|
1093
1170
|
startedAt,
|
|
1094
1171
|
protocol,
|
|
1172
|
+
ambientDefaults,
|
|
1173
|
+
sharedCache,
|
|
1095
1174
|
).finally(() => {
|
|
1096
1175
|
proxyInflight.delete(cacheKey);
|
|
1097
1176
|
});
|
|
@@ -1131,6 +1210,8 @@ async function refreshSmartproxyPool(
|
|
|
1131
1210
|
appKey: string,
|
|
1132
1211
|
lifetimeMinutes: number,
|
|
1133
1212
|
protocol: ProxyProtocol,
|
|
1213
|
+
ambientDefaults: boolean,
|
|
1214
|
+
sharedCache: boolean,
|
|
1134
1215
|
): Promise<void> {
|
|
1135
1216
|
try {
|
|
1136
1217
|
await allocateSmartproxyShared(
|
|
@@ -1140,6 +1221,8 @@ async function refreshSmartproxyPool(
|
|
|
1140
1221
|
lifetimeMinutes,
|
|
1141
1222
|
Date.now(),
|
|
1142
1223
|
protocol,
|
|
1224
|
+
ambientDefaults,
|
|
1225
|
+
sharedCache,
|
|
1143
1226
|
{
|
|
1144
1227
|
background: true,
|
|
1145
1228
|
},
|
|
@@ -1156,9 +1239,11 @@ async function allocateSmartproxyShared(
|
|
|
1156
1239
|
lifetimeMinutes: number,
|
|
1157
1240
|
startedAt: number,
|
|
1158
1241
|
protocol: ProxyProtocol,
|
|
1242
|
+
ambientDefaults: boolean,
|
|
1243
|
+
sharedCache: boolean,
|
|
1159
1244
|
options: { background?: boolean } = {},
|
|
1160
1245
|
): Promise<SmartproxyAllocationResult> {
|
|
1161
|
-
const redis = getProxyRedis();
|
|
1246
|
+
const redis = sharedCache ? getProxyRedis() : undefined;
|
|
1162
1247
|
if (!redis || !(await ensureRedisReady(redis))) {
|
|
1163
1248
|
return await allocateAndStoreSmartproxyPool(
|
|
1164
1249
|
cacheKey,
|
|
@@ -1166,7 +1251,7 @@ async function allocateSmartproxyShared(
|
|
|
1166
1251
|
appKey,
|
|
1167
1252
|
lifetimeMinutes,
|
|
1168
1253
|
startedAt,
|
|
1169
|
-
{ cacheStatus: "allocator", protocol },
|
|
1254
|
+
{ cacheStatus: "allocator", protocol, ambientDefaults },
|
|
1170
1255
|
);
|
|
1171
1256
|
}
|
|
1172
1257
|
|
|
@@ -1192,6 +1277,7 @@ async function allocateSmartproxyShared(
|
|
|
1192
1277
|
redis,
|
|
1193
1278
|
poolKey,
|
|
1194
1279
|
protocol,
|
|
1280
|
+
ambientDefaults,
|
|
1195
1281
|
},
|
|
1196
1282
|
);
|
|
1197
1283
|
} finally {
|
|
@@ -1348,6 +1434,7 @@ async function allocateAndStoreSmartproxyPool(
|
|
|
1348
1434
|
redis?: ProxyRedisClient;
|
|
1349
1435
|
poolKey?: string;
|
|
1350
1436
|
protocol: ProxyProtocol;
|
|
1437
|
+
ambientDefaults: boolean;
|
|
1351
1438
|
},
|
|
1352
1439
|
): Promise<SmartproxyAllocationResult> {
|
|
1353
1440
|
const poolSize = resolveSmartproxyPoolSize(policy);
|
|
@@ -1357,6 +1444,7 @@ async function allocateAndStoreSmartproxyPool(
|
|
|
1357
1444
|
lifetimeMinutes,
|
|
1358
1445
|
poolSize,
|
|
1359
1446
|
options.protocol,
|
|
1447
|
+
options.ambientDefaults,
|
|
1360
1448
|
);
|
|
1361
1449
|
const allocatorStartedAt = Date.now();
|
|
1362
1450
|
const allocatorDeadlineAt = allocatorStartedAt + smartproxyAllocatorDeadlineMs();
|
|
@@ -1427,7 +1515,7 @@ async function allocateAndStoreSmartproxyPool(
|
|
|
1427
1515
|
expiresAt: allocatedAt + ttlMs,
|
|
1428
1516
|
diagnostics: {
|
|
1429
1517
|
provider: "smartproxy",
|
|
1430
|
-
country: resolveSmartproxyCountry(policy) ?? "default",
|
|
1518
|
+
country: resolveSmartproxyCountry(policy, options.ambientDefaults) ?? "default",
|
|
1431
1519
|
lifetimeMinutes,
|
|
1432
1520
|
affinity: policy.session?.affinity ?? "request",
|
|
1433
1521
|
rawConnect: true,
|
|
@@ -1590,6 +1678,7 @@ function buildSmartproxyAllocatorUrl(
|
|
|
1590
1678
|
lifetimeMinutes: number,
|
|
1591
1679
|
poolSize: number,
|
|
1592
1680
|
protocol: ProxyProtocol,
|
|
1681
|
+
ambientDefaults = true,
|
|
1593
1682
|
): string {
|
|
1594
1683
|
const params = new URLSearchParams({
|
|
1595
1684
|
app_key: appKey,
|
|
@@ -1600,7 +1689,7 @@ function buildSmartproxyAllocatorUrl(
|
|
|
1600
1689
|
format: "txt",
|
|
1601
1690
|
lb: "\\n",
|
|
1602
1691
|
});
|
|
1603
|
-
const country = resolveSmartproxyCountry(policy);
|
|
1692
|
+
const country = resolveSmartproxyCountry(policy, ambientDefaults);
|
|
1604
1693
|
if (country) {
|
|
1605
1694
|
params.set("cc", country);
|
|
1606
1695
|
}
|
|
@@ -1681,8 +1770,11 @@ function markSmartproxyCacheInvalidated(options: ProxyResolutionOptions = {}): s
|
|
|
1681
1770
|
}
|
|
1682
1771
|
|
|
1683
1772
|
const lifetimeMinutes = resolveSmartproxyLifetime(policy);
|
|
1773
|
+
const appKey = process.env[SMARTPROXY_APP_KEY_ENV]?.trim();
|
|
1774
|
+
if (!appKey) return undefined;
|
|
1684
1775
|
const cacheKey = buildSmartproxyCacheKey(
|
|
1685
1776
|
policy,
|
|
1777
|
+
appKey,
|
|
1686
1778
|
options.affinityKey,
|
|
1687
1779
|
lifetimeMinutes,
|
|
1688
1780
|
options.protocol ?? VENDOR_DEFAULT_PROTOCOL.smartproxy,
|
package/src/index.ts
CHANGED
|
@@ -72,6 +72,7 @@ export { executeOperation } from "./runtime/executor.js";
|
|
|
72
72
|
export { createHttpClient } from "./runtime/http.js";
|
|
73
73
|
export {
|
|
74
74
|
createNativeNetworkClient,
|
|
75
|
+
createEnvVendorCredentialResolver,
|
|
75
76
|
deriveNativeCredentialAffinityKey,
|
|
76
77
|
NativeEgressGrantExpiredError,
|
|
77
78
|
NativeEgressNotDeclaredError,
|
|
@@ -81,10 +82,14 @@ export {
|
|
|
81
82
|
resolveNativeGatewayProxy,
|
|
82
83
|
type NativeGatewayProxy,
|
|
83
84
|
type NativeGatewayProxyResolutionInput,
|
|
85
|
+
type NativeGatewayProxySkipReason,
|
|
84
86
|
type NativeGatewayProxySynthesizer,
|
|
87
|
+
type NativeGatewayProxySynthesisResult,
|
|
85
88
|
type NativeGatewayProxySynthesisInput,
|
|
86
89
|
type NativeNetworkClientOptions,
|
|
87
90
|
type NativeNetworkErrorCode,
|
|
91
|
+
type VendorCredentialLookup,
|
|
92
|
+
type VendorCredentialResolver,
|
|
88
93
|
} from "./runtime/native-network.js";
|
|
89
94
|
export type { Insight, InsightSeverity } from "./runtime/insights.js";
|
|
90
95
|
export { generateInsights } from "./runtime/insights.js";
|