perimeterx-js-core 0.34.0 → 0.35.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.
@@ -783,6 +783,13 @@ var ConfigurationBase = /** @class */ (function () {
783
783
  enumerable: false,
784
784
  configurable: true
785
785
  });
786
+ Object.defineProperty(ConfigurationBase.prototype, "proxyUrl", {
787
+ get: function () {
788
+ return this.configParams.px_proxy_url;
789
+ },
790
+ enumerable: false,
791
+ configurable: true
792
+ });
786
793
  Object.defineProperty(ConfigurationBase.prototype, "enableBlockedUrlOnCaptchaBlockPage", {
787
794
  get: function () {
788
795
  return true;
@@ -135,6 +135,7 @@ var defaultConfigurationParams = function () { return ({
135
135
  px_data_enrichment_header_name: '',
136
136
  px_snippet_injection_enabled: false,
137
137
  px_create_custom_snippet: null,
138
+ px_proxy_url: '',
138
139
  px_custom_is_sensitive_request: null,
139
140
  px_custom_is_monitored_request: null,
140
141
  px_custom_is_enforced_request: null,
@@ -44,11 +44,13 @@ var http_1 = require("http");
44
44
  var https_1 = require("https");
45
45
  var phin_1 = __importDefault(require("phin"));
46
46
  var utils_1 = require("../../../utils/index.js");
47
- var interfaces_1 = require("../../../http/interfaces/index.js");
47
+ var http_2 = require("../../../http/index.js");
48
48
  var PhinIncomingResponse_1 = require("./PhinIncomingResponse.js");
49
49
  var PhinHttpClient = /** @class */ (function () {
50
- function PhinHttpClient() {
51
- this.httpsKeepAliveAgent = new https_1.Agent({ keepAlive: true });
50
+ function PhinHttpClient(options) {
51
+ var _a, _b;
52
+ this.httpAgent = (_a = options === null || options === void 0 ? void 0 : options.httpAgent) !== null && _a !== void 0 ? _a : null;
53
+ this.httpsAgent = (_b = options === null || options === void 0 ? void 0 : options.httpsAgent) !== null && _b !== void 0 ? _b : new https_1.Agent({ keepAlive: true });
52
54
  }
53
55
  PhinHttpClient.prototype.send = function (request, options) {
54
56
  return __awaiter(this, void 0, void 0, function () {
@@ -60,11 +62,11 @@ var PhinHttpClient = /** @class */ (function () {
60
62
  return [4 /*yield*/, phin_1.default.promisified({
61
63
  url: request.url,
62
64
  method: request.method,
63
- headers: (0, interfaces_1.joinHeaderValues)(request.headers),
65
+ headers: (0, http_2.joinHeaderValues)(request.headers),
64
66
  data: request.body,
65
67
  timeout: options === null || options === void 0 ? void 0 : options.timeoutMs,
66
68
  core: {
67
- agent: request.url.startsWith('https://') ? this.httpsKeepAliveAgent : new http_1.Agent(),
69
+ agent: this.getAgent(request),
68
70
  },
69
71
  })];
70
72
  case 1:
@@ -79,6 +81,15 @@ var PhinHttpClient = /** @class */ (function () {
79
81
  });
80
82
  });
81
83
  };
84
+ PhinHttpClient.prototype.getAgent = function (request) {
85
+ if (request.url.startsWith('https://')) {
86
+ return this.httpsAgent;
87
+ }
88
+ if (this.httpAgent) {
89
+ return this.httpAgent;
90
+ }
91
+ return new http_1.Agent();
92
+ };
82
93
  return PhinHttpClient;
83
94
  }());
84
95
  exports.PhinHttpClient = PhinHttpClient;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.PhinHttpProxyClient = void 0;
19
+ var PhinHttpClient_1 = require("./PhinHttpClient.js");
20
+ var http_proxy_agent_1 = require("http-proxy-agent");
21
+ var https_proxy_agent_1 = require("https-proxy-agent");
22
+ var PhinHttpProxyClient = /** @class */ (function (_super) {
23
+ __extends(PhinHttpProxyClient, _super);
24
+ function PhinHttpProxyClient(proxyUrl) {
25
+ var httpAgent = new http_proxy_agent_1.HttpProxyAgent(proxyUrl, { keepAlive: true });
26
+ var httpsAgent = new https_proxy_agent_1.HttpsProxyAgent(proxyUrl, { keepAlive: true });
27
+ return _super.call(this, { httpsAgent: httpsAgent, httpAgent: httpAgent }) || this;
28
+ }
29
+ return PhinHttpProxyClient;
30
+ }(PhinHttpClient_1.PhinHttpClient));
31
+ exports.PhinHttpProxyClient = PhinHttpProxyClient;
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./PhinIncomingResponse.js"), exports);
18
18
  __exportStar(require("./PhinHttpClient.js"), exports);
19
+ __exportStar(require("./PhinHttpProxyClient.js"), exports);
@@ -15,4 +15,4 @@ exports.PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
15
15
  exports.EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
16
16
  exports.URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
17
17
  exports.REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
18
- exports.CORE_MODULE_VERSION = 'JS Core 0.34.0';
18
+ exports.CORE_MODULE_VERSION = 'JS Core 0.35.0';
@@ -409,6 +409,9 @@ export class ConfigurationBase {
409
409
  get dataEnrichmentHeaderName() {
410
410
  return this.configParams.px_data_enrichment_header_name;
411
411
  }
412
+ get proxyUrl() {
413
+ return this.configParams.px_proxy_url;
414
+ }
412
415
  get enableBlockedUrlOnCaptchaBlockPage() {
413
416
  return true;
414
417
  }
@@ -132,6 +132,7 @@ export const defaultConfigurationParams = () => ({
132
132
  px_data_enrichment_header_name: '',
133
133
  px_snippet_injection_enabled: false,
134
134
  px_create_custom_snippet: null,
135
+ px_proxy_url: '',
135
136
  px_custom_is_sensitive_request: null,
136
137
  px_custom_is_monitored_request: null,
137
138
  px_custom_is_enforced_request: null,
@@ -2,12 +2,14 @@ import { Agent as HttpAgent } from 'http';
2
2
  import { Agent as HttpsAgent } from 'https';
3
3
  import phin from 'phin';
4
4
  import { EnforcerTimeoutError } from '../../../utils/index.js';
5
- import { joinHeaderValues, } from '../../../http/interfaces/index.js';
5
+ import { joinHeaderValues } from '../../../http/index.js';
6
6
  import { PhinIncomingResponse } from './PhinIncomingResponse.js';
7
7
  export class PhinHttpClient {
8
- httpsKeepAliveAgent;
9
- constructor() {
10
- this.httpsKeepAliveAgent = new HttpsAgent({ keepAlive: true });
8
+ httpAgent;
9
+ httpsAgent;
10
+ constructor(options) {
11
+ this.httpAgent = options?.httpAgent ?? null;
12
+ this.httpsAgent = options?.httpsAgent ?? new HttpsAgent({ keepAlive: true });
11
13
  }
12
14
  async send(request, options) {
13
15
  try {
@@ -18,7 +20,7 @@ export class PhinHttpClient {
18
20
  data: request.body,
19
21
  timeout: options?.timeoutMs,
20
22
  core: {
21
- agent: request.url.startsWith('https://') ? this.httpsKeepAliveAgent : new HttpAgent(),
23
+ agent: this.getAgent(request),
22
24
  },
23
25
  });
24
26
  return new PhinIncomingResponse(res);
@@ -28,4 +30,13 @@ export class PhinHttpClient {
28
30
  throw isTimeout ? new EnforcerTimeoutError(options?.timeoutMs) : e;
29
31
  }
30
32
  }
33
+ getAgent(request) {
34
+ if (request.url.startsWith('https://')) {
35
+ return this.httpsAgent;
36
+ }
37
+ if (this.httpAgent) {
38
+ return this.httpAgent;
39
+ }
40
+ return new HttpAgent();
41
+ }
31
42
  }
@@ -0,0 +1,10 @@
1
+ import { PhinHttpClient } from './PhinHttpClient.js';
2
+ import { HttpProxyAgent } from 'http-proxy-agent';
3
+ import { HttpsProxyAgent } from 'https-proxy-agent';
4
+ export class PhinHttpProxyClient extends PhinHttpClient {
5
+ constructor(proxyUrl) {
6
+ const httpAgent = new HttpProxyAgent(proxyUrl, { keepAlive: true });
7
+ const httpsAgent = new HttpsProxyAgent(proxyUrl, { keepAlive: true });
8
+ super({ httpsAgent, httpAgent });
9
+ }
10
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './PhinIncomingResponse.js';
2
2
  export * from './PhinHttpClient.js';
3
+ export * from './PhinHttpProxyClient.js';
@@ -12,4 +12,4 @@ export const PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
12
12
  export const EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
13
13
  export const URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
14
14
  export const REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
15
- export const CORE_MODULE_VERSION = 'JS Core 0.34.0';
15
+ export const CORE_MODULE_VERSION = 'JS Core 0.35.0';
@@ -1,5 +1,5 @@
1
1
  import { IConfiguration } from './IConfiguration';
2
- import { RemoteConfigurationParams, StaticConfigurationParams, AllConfigurationParams, RequiredAllConfigurationParams, ActiveConfigurationParams, CoreConfigurationParams } from './params';
2
+ import { RemoteConfigurationParams, StaticConfigurationParams, AllConfigurationParams, RequiredAllConfigurationParams, ActiveConfigurationParams, CoreConfigurationParams, CoreConfigurationParamsKeys } from './params';
3
3
  import { CustomParametersFunction, ResponseCustomParametersFunction } from '../custom_parameters';
4
4
  import { AdditionalActivityHandler } from '../additional_activity_handler';
5
5
  import { ILogger, LoggerSeverity } from '../logger';
@@ -11,6 +11,11 @@ import { ExtractGraphQLKeywordsFunction } from '../graphql';
11
11
  import { RemoteConfigData } from './remote_config';
12
12
  import { TokenVersion } from '../risk_token';
13
13
  import { CustomSnippetFunction } from '../snippet_injection';
14
+ type EmptyObjectStrict = Record<PropertyKey, never>;
15
+ type Unsupported<Supported extends string> = Exclude<CoreConfigurationParamsKeys, Supported>;
16
+ type RemovedParams<Supported extends string> = Unsupported<Supported> extends never ? EmptyObjectStrict : {
17
+ [K in Unsupported<Supported>]: undefined;
18
+ };
14
19
  /**
15
20
  * Base class for the enforcer configuration.
16
21
  */
@@ -19,7 +24,7 @@ export declare abstract class ConfigurationBase<Req, Res, Supported extends stri
19
24
  protected readonly staticConfigParams: StaticConfigurationParams<Req, Res, Supported, Added>;
20
25
  protected remoteConfigData?: RemoteConfigData<Req, Res, Supported, Added>;
21
26
  protected readonly defaultConfigParams: RequiredAllConfigurationParams<Req, Res, Supported, Added>;
22
- protected readonly removedParams: Record<Exclude<keyof CoreConfigurationParams<Req, Res, Supported, Added>, Supported>, undefined>;
27
+ protected readonly removedParams: RemovedParams<Supported>;
23
28
  private internalLogger;
24
29
  /**
25
30
  * Returns the module version of the enforcer.
@@ -40,7 +45,7 @@ export declare abstract class ConfigurationBase<Req, Res, Supported extends stri
40
45
  * @param removedParams - A map of all removed (unsupported) configuration parameters set to undefined. This parameter can be generated automatically by your IDE.
41
46
  * @protected
42
47
  */
43
- protected constructor(params: StaticConfigurationParams<Req, Res, Supported, Added>, defaultParams: Required<Added> & Partial<CoreConfigurationParams<Req, Res, Supported, Added>>, removedParams: Record<Exclude<keyof CoreConfigurationParams<Req, Res, Supported, Added>, Supported>, undefined>);
48
+ protected constructor(params: StaticConfigurationParams<Req, Res, Supported, Added>, defaultParams: Required<Added> & Partial<CoreConfigurationParams<Req, Res, Supported, Added>>, removedParams: RemovedParams<Supported>);
44
49
  protected createActiveConfiguration(params: AllConfigurationParams<Req, Res, Supported, Added>, defaultParams: RequiredAllConfigurationParams<Req, Res, Supported, Added>): RequiredAllConfigurationParams<Req, Res, Supported, Added>;
45
50
  protected throwIfMissingRequiredField(params: AllConfigurationParams<Req, Res, Supported, Added>): void;
46
51
  protected getValidConfigValue<K extends keyof RequiredAllConfigurationParams<Req, Res, Supported, Added>, V extends RequiredAllConfigurationParams<Req, Res, Supported, Added>[K]>(params: AllConfigurationParams<Req, Res, Supported, Added>, defaultParams: RequiredAllConfigurationParams<Req, Res, Supported, Added>, key: K): V;
@@ -144,7 +149,9 @@ export declare abstract class ConfigurationBase<Req, Res, Supported extends stri
144
149
  get snippetInjectionEnabled(): boolean;
145
150
  get createCustomSnippet(): CustomSnippetFunction<Req, Res, Supported, Added> | null;
146
151
  get dataEnrichmentHeaderName(): string;
152
+ get proxyUrl(): string;
147
153
  get enableBlockedUrlOnCaptchaBlockPage(): boolean;
148
154
  get awaitAsyncHttpRequests(): boolean;
149
155
  get isPostEnforceEnabled(): boolean;
150
156
  }
157
+ export {};
@@ -408,6 +408,10 @@ export interface IConfiguration<Req, Res, Supported extends string, Added> {
408
408
  * The header name to use when adding the data enrichment value as an incoming request header.
409
409
  */
410
410
  readonly dataEnrichmentHeaderName: string;
411
+ /**
412
+ * The URL to which all HUMAN requests will be proxied as a domain or IP:port (e.g., "http://example.proxy.net", "https://1.1.1.1:8888").
413
+ */
414
+ readonly proxyUrl: string;
411
415
  /**
412
416
  * Returns an object representation of the current configuration.
413
417
  */
@@ -121,6 +121,7 @@ export type CommonConfigurationParams<Req, Res, Supported extends string, Added>
121
121
  px_url_decode_reserved_characters?: boolean;
122
122
  px_secured_pxhd_enabled?: boolean;
123
123
  px_data_enrichment_header_name?: string;
124
+ px_proxy_url?: string;
124
125
  px_additional_activity_handler?: AdditionalActivityHandler<Req, Res, Supported, Added> | null;
125
126
  px_enrich_custom_parameters?: CustomParametersFunction<Req, Res, Supported, Added> | null;
126
127
  px_enrich_response_custom_parameters?: ResponseCustomParametersFunction<Req, Res, Supported, Added> | null;
@@ -1,6 +1,14 @@
1
- import { HttpSendOptions, IHttpClient, IIncomingResponse, IOutgoingRequest } from '../../../http/interfaces';
1
+ import { Agent as HttpAgent } from 'http';
2
+ import { Agent as HttpsAgent } from 'https';
3
+ import { HttpSendOptions, IHttpClient, IIncomingResponse, IOutgoingRequest } from '../../../http';
4
+ export type PhinHttpClientOptions = {
5
+ httpAgent?: HttpAgent;
6
+ httpsAgent?: HttpsAgent;
7
+ };
2
8
  export declare class PhinHttpClient implements IHttpClient {
3
- private readonly httpsKeepAliveAgent;
4
- constructor();
9
+ private readonly httpAgent;
10
+ private readonly httpsAgent;
11
+ constructor(options?: PhinHttpClientOptions);
5
12
  send(request: IOutgoingRequest, options?: HttpSendOptions): Promise<IIncomingResponse>;
13
+ protected getAgent(request: IOutgoingRequest): HttpAgent;
6
14
  }
@@ -0,0 +1,4 @@
1
+ import { PhinHttpClient } from './PhinHttpClient';
2
+ export declare class PhinHttpProxyClient extends PhinHttpClient {
3
+ constructor(proxyUrl: string);
4
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './PhinIncomingResponse';
2
2
  export * from './PhinHttpClient';
3
+ export * from './PhinHttpProxyClient';
@@ -12,4 +12,4 @@ export declare const PUSH_DATA_FEATURE_HEADER_NAME = "x-px-feature";
12
12
  export declare const EMAIL_ADDRESS_REGEX: RegExp;
13
13
  export declare const URL_REGEX: RegExp;
14
14
  export declare const REGEX_STRUCTURE: RegExp;
15
- export declare const CORE_MODULE_VERSION = "JS Core 0.34.0";
15
+ export declare const CORE_MODULE_VERSION = "JS Core 0.35.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "perimeterx-js-core",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "typesVersions": {
@@ -44,6 +44,8 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "crypto-js": "^4.1.1",
47
+ "http-proxy-agent": "^7.0.2",
48
+ "https-proxy-agent": "^7.0.6",
47
49
  "ip-range-check": "^0.2.0",
48
50
  "js-base64": "^3.7.2",
49
51
  "phin": "^3.7.0",
@@ -61,7 +63,7 @@
61
63
  "@typescript-eslint/eslint-plugin": "^8.38.0",
62
64
  "@typescript-eslint/parser": "^8.26.0",
63
65
  "c8": "^10.1.3",
64
- "chai": "^5.2.0",
66
+ "chai": "^6.2.0",
65
67
  "chai-as-promised": "^8.0.0",
66
68
  "core-js": "^3.19.1",
67
69
  "eslint": "^9.21.0",