perimeterx-js-core 0.28.0 → 0.30.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/lib/cjs/activities/HttpActivityClient.js +21 -18
- package/lib/cjs/config/ConfigurationBase.js +16 -0
- package/lib/cjs/config/defaults/DefaultConfigurationParams.js +1 -0
- package/lib/cjs/config/remote_config/service_client/HttpRemoteConfigServiceClient.js +1 -1
- package/lib/cjs/flow/EndEnforcerFlow.js +2 -2
- package/lib/cjs/logger/HttpLogServiceClient.js +1 -1
- package/lib/cjs/phase/impl/SendAsyncActivitiesPhase.js +6 -2
- package/lib/cjs/phase/impl/SendLogsPhase.js +6 -2
- package/lib/cjs/phase/impl/SendTelemetryActivityPhase.js +6 -2
- package/lib/cjs/telemetry/DefaultTelemetry.js +1 -1
- package/lib/cjs/utils/constants.js +3 -2
- package/lib/esm/activities/HttpActivityClient.js +18 -12
- package/lib/esm/config/ConfigurationBase.js +9 -1
- package/lib/esm/config/defaults/DefaultConfigurationParams.js +2 -1
- package/lib/esm/config/remote_config/service_client/HttpRemoteConfigServiceClient.js +1 -1
- package/lib/esm/flow/EndEnforcerFlow.js +2 -2
- package/lib/esm/logger/HttpLogServiceClient.js +1 -1
- package/lib/esm/phase/impl/SendAsyncActivitiesPhase.js +8 -2
- package/lib/esm/phase/impl/SendLogsPhase.js +8 -2
- package/lib/esm/phase/impl/SendTelemetryActivityPhase.js +8 -2
- package/lib/esm/telemetry/DefaultTelemetry.js +1 -1
- package/lib/esm/utils/constants.js +2 -1
- package/lib/types/config/ConfigurationBase.d.ts +2 -0
- package/lib/types/config/IConfiguration.d.ts +8 -0
- package/lib/types/config/params/CoreConfigurationParams.d.ts +1 -0
- package/lib/types/phase/impl/SendAsyncActivitiesPhase.d.ts +4 -2
- package/lib/types/phase/impl/SendLogsPhase.d.ts +2 -1
- package/lib/types/phase/impl/SendTelemetryActivityPhase.d.ts +4 -2
- package/lib/types/utils/constants.d.ts +2 -1
- package/package.json +2 -2
|
@@ -63,24 +63,21 @@ var HttpActivityClient = /** @class */ (function () {
|
|
|
63
63
|
*/
|
|
64
64
|
HttpActivityClient.prototype.sendActivities = function (context) {
|
|
65
65
|
return __awaiter(this, void 0, void 0, function () {
|
|
66
|
-
var activities
|
|
66
|
+
var activities;
|
|
67
67
|
return __generator(this, function (_a) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
activities
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return [4 /*yield*/, this.postActivities(activities, context.logger)];
|
|
77
|
-
case 1: return [2 /*return*/, _a.sent()];
|
|
78
|
-
case 2:
|
|
79
|
-
e_1 = _a.sent();
|
|
80
|
-
context.logger.error("unable to send activities - ".concat(e_1));
|
|
81
|
-
return [2 /*return*/, false];
|
|
82
|
-
case 3: return [2 /*return*/];
|
|
68
|
+
try {
|
|
69
|
+
activities = this.createActivities(context);
|
|
70
|
+
if (!activities || activities.length === 0) {
|
|
71
|
+
context.logger.debug('no activities to send');
|
|
72
|
+
return [2 /*return*/, true];
|
|
73
|
+
}
|
|
74
|
+
return [2 /*return*/, this.postActivities(activities, context.logger)];
|
|
83
75
|
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
context.logger.error("unable to send activities - ".concat(e));
|
|
78
|
+
return [2 /*return*/, false];
|
|
79
|
+
}
|
|
80
|
+
return [2 /*return*/];
|
|
84
81
|
});
|
|
85
82
|
});
|
|
86
83
|
};
|
|
@@ -171,11 +168,12 @@ var HttpActivityClient = /** @class */ (function () {
|
|
|
171
168
|
*/
|
|
172
169
|
HttpActivityClient.prototype.postActivities = function (activities, logger) {
|
|
173
170
|
return __awaiter(this, void 0, void 0, function () {
|
|
174
|
-
var url, method, headers, body, req, res;
|
|
171
|
+
var url, method, headers, body, req, res, e_1;
|
|
175
172
|
var _a;
|
|
176
173
|
return __generator(this, function (_b) {
|
|
177
174
|
switch (_b.label) {
|
|
178
175
|
case 0:
|
|
176
|
+
_b.trys.push([0, 2, , 3]);
|
|
179
177
|
url = "".concat(this.config.backendCollectorUrl).concat(constants_1.ACTIVITIES_ENDPOINT);
|
|
180
178
|
method = http_1.HttpMethod.POST;
|
|
181
179
|
headers = (_a = {},
|
|
@@ -188,10 +186,15 @@ var HttpActivityClient = /** @class */ (function () {
|
|
|
188
186
|
return "".concat(type, " activity");
|
|
189
187
|
}).join(', '), " to ").concat(url));
|
|
190
188
|
req = new http_1.OutgoingRequestImpl({ url: url, method: method, headers: headers, body: body });
|
|
191
|
-
return [4 /*yield*/, this.httpClient.send(req)];
|
|
189
|
+
return [4 /*yield*/, this.httpClient.send(req, { timeoutMs: this.config.asyncTimeout })];
|
|
192
190
|
case 1:
|
|
193
191
|
res = _b.sent();
|
|
194
192
|
return [2 /*return*/, (res === null || res === void 0 ? void 0 : res.status) === 200];
|
|
193
|
+
case 2:
|
|
194
|
+
e_1 = _b.sent();
|
|
195
|
+
logger.error("failed to post activities - ".concat(e_1));
|
|
196
|
+
return [2 /*return*/, false];
|
|
197
|
+
case 3: return [2 /*return*/];
|
|
195
198
|
}
|
|
196
199
|
});
|
|
197
200
|
});
|
|
@@ -339,6 +339,15 @@ var ConfigurationBase = /** @class */ (function () {
|
|
|
339
339
|
enumerable: false,
|
|
340
340
|
configurable: true
|
|
341
341
|
});
|
|
342
|
+
Object.defineProperty(ConfigurationBase.prototype, "asyncTimeout", {
|
|
343
|
+
get: function () {
|
|
344
|
+
return this.configParams.px_async_timeout === utils_1.UNLIMITED_TIMEOUT
|
|
345
|
+
? undefined
|
|
346
|
+
: this.configParams.px_async_timeout;
|
|
347
|
+
},
|
|
348
|
+
enumerable: false,
|
|
349
|
+
configurable: true
|
|
350
|
+
});
|
|
342
351
|
Object.defineProperty(ConfigurationBase.prototype, "sensitiveHeaders", {
|
|
343
352
|
get: function () {
|
|
344
353
|
return this.configParams.px_sensitive_headers;
|
|
@@ -773,6 +782,13 @@ var ConfigurationBase = /** @class */ (function () {
|
|
|
773
782
|
enumerable: false,
|
|
774
783
|
configurable: true
|
|
775
784
|
});
|
|
785
|
+
Object.defineProperty(ConfigurationBase.prototype, "awaitAsyncHttpRequests", {
|
|
786
|
+
get: function () {
|
|
787
|
+
return true;
|
|
788
|
+
},
|
|
789
|
+
enumerable: false,
|
|
790
|
+
configurable: true
|
|
791
|
+
});
|
|
776
792
|
Object.defineProperty(ConfigurationBase.prototype, "isPostEnforceEnabled", {
|
|
777
793
|
get: function () {
|
|
778
794
|
return true;
|
|
@@ -21,6 +21,7 @@ var defaultConfigurationParams = function () { return ({
|
|
|
21
21
|
px_graphql_routes_regex: [],
|
|
22
22
|
px_sensitive_routes_regex: [],
|
|
23
23
|
px_s2s_timeout: 1000,
|
|
24
|
+
px_async_timeout: utils_1.UNLIMITED_TIMEOUT,
|
|
24
25
|
px_blocking_score: 100,
|
|
25
26
|
px_user_agent_max_length: 8528,
|
|
26
27
|
px_risk_cookie_max_length: 2048,
|
|
@@ -51,7 +51,7 @@ var HttpRemoteConfigServiceClient = /** @class */ (function () {
|
|
|
51
51
|
switch (_a.label) {
|
|
52
52
|
case 0:
|
|
53
53
|
request = this.createFetchRemoteConfigRequest();
|
|
54
|
-
return [4 /*yield*/, this.httpClient.send(request)];
|
|
54
|
+
return [4 /*yield*/, this.httpClient.send(request, { timeoutMs: this.config.asyncTimeout })];
|
|
55
55
|
case 1:
|
|
56
56
|
response = _a.sent();
|
|
57
57
|
return [2 /*return*/, this.extractConfigFromResponse(response)];
|
|
@@ -23,8 +23,8 @@ var EndEnforcerFlow = /** @class */ (function (_super) {
|
|
|
23
23
|
function EndEnforcerFlow(config, _a) {
|
|
24
24
|
var logServiceClient = _a.logServiceClient, telemetry = _a.telemetry, remoteConfigManager = _a.remoteConfigManager, activityClient = _a.activityClient;
|
|
25
25
|
var phases = [
|
|
26
|
-
new phase_1.SendAsyncActivitiesPhase(activityClient),
|
|
27
|
-
new phase_1.SendTelemetryActivityPhase(telemetry),
|
|
26
|
+
new phase_1.SendAsyncActivitiesPhase(config, activityClient),
|
|
27
|
+
new phase_1.SendTelemetryActivityPhase(config, telemetry),
|
|
28
28
|
];
|
|
29
29
|
if (remoteConfigManager) {
|
|
30
30
|
phases.push(new phase_1.UpdateRemoteConfigPhase(config, remoteConfigManager));
|
|
@@ -120,7 +120,7 @@ var HttpLogServiceClient = /** @class */ (function () {
|
|
|
120
120
|
_a);
|
|
121
121
|
body = JSON.stringify(logRecords);
|
|
122
122
|
req = new http_1.OutgoingRequestImpl({ url: url, method: method, headers: headers, body: body });
|
|
123
|
-
return [4 /*yield*/, this.httpClient.send(req)];
|
|
123
|
+
return [4 /*yield*/, this.httpClient.send(req, { timeoutMs: this.config.asyncTimeout })];
|
|
124
124
|
case 1:
|
|
125
125
|
res = _b.sent();
|
|
126
126
|
return [2 /*return*/, (res === null || res === void 0 ? void 0 : res.status) === 200];
|
|
@@ -42,16 +42,20 @@ var action_1 = require("../../action/index.js");
|
|
|
42
42
|
* The `SendAsyncActivitiesPhase` class is responsible for sending all necessary asynchronous activities based on the context.
|
|
43
43
|
*/
|
|
44
44
|
var SendAsyncActivitiesPhase = /** @class */ (function () {
|
|
45
|
-
function SendAsyncActivitiesPhase(activityClient) {
|
|
45
|
+
function SendAsyncActivitiesPhase(config, activityClient) {
|
|
46
|
+
this.config = config;
|
|
46
47
|
this.activityClient = activityClient;
|
|
47
48
|
}
|
|
48
49
|
SendAsyncActivitiesPhase.prototype.execute = function (context) {
|
|
49
50
|
return __awaiter(this, void 0, void 0, function () {
|
|
51
|
+
var promise;
|
|
50
52
|
return __generator(this, function (_a) {
|
|
51
53
|
switch (_a.label) {
|
|
52
54
|
case 0:
|
|
53
55
|
if (![action_1.Action.PASS_REQUEST, action_1.Action.BLOCK, action_1.Action.SIMULATED_BLOCK].includes(context.action)) return [3 /*break*/, 2];
|
|
54
|
-
|
|
56
|
+
promise = this.activityClient.sendActivities(context);
|
|
57
|
+
if (!this.config.awaitAsyncHttpRequests) return [3 /*break*/, 2];
|
|
58
|
+
return [4 /*yield*/, promise];
|
|
55
59
|
case 1:
|
|
56
60
|
_a.sent();
|
|
57
61
|
_a.label = 2;
|
|
@@ -41,16 +41,20 @@ exports.SendLogsPhase = void 0;
|
|
|
41
41
|
* The `SendLogsPhase` class is responsible for sending logs to the HUMAN logging service.
|
|
42
42
|
*/
|
|
43
43
|
var SendLogsPhase = /** @class */ (function () {
|
|
44
|
-
function SendLogsPhase(
|
|
44
|
+
function SendLogsPhase(config, logServiceClient) {
|
|
45
|
+
this.config = config;
|
|
45
46
|
this.logServiceClient = logServiceClient;
|
|
46
47
|
}
|
|
47
48
|
SendLogsPhase.prototype.execute = function (context) {
|
|
48
49
|
return __awaiter(this, void 0, void 0, function () {
|
|
50
|
+
var promise;
|
|
49
51
|
return __generator(this, function (_a) {
|
|
50
52
|
switch (_a.label) {
|
|
51
53
|
case 0:
|
|
52
54
|
if (!context.shouldSendLogs) return [3 /*break*/, 2];
|
|
53
|
-
|
|
55
|
+
promise = this.logServiceClient.sendLogs(context);
|
|
56
|
+
if (!this.config.awaitAsyncHttpRequests) return [3 /*break*/, 2];
|
|
57
|
+
return [4 /*yield*/, promise];
|
|
54
58
|
case 1:
|
|
55
59
|
_a.sent();
|
|
56
60
|
_a.label = 2;
|
|
@@ -41,16 +41,20 @@ exports.SendTelemetryActivityPhase = void 0;
|
|
|
41
41
|
* The `SendTelemetryActivityPhase` class is responsible for sending the telemetry activity if necessary.
|
|
42
42
|
*/
|
|
43
43
|
var SendTelemetryActivityPhase = /** @class */ (function () {
|
|
44
|
-
function SendTelemetryActivityPhase(telemetry) {
|
|
44
|
+
function SendTelemetryActivityPhase(config, telemetry) {
|
|
45
|
+
this.config = config;
|
|
45
46
|
this.telemetry = telemetry;
|
|
46
47
|
}
|
|
47
48
|
SendTelemetryActivityPhase.prototype.execute = function (context) {
|
|
48
49
|
return __awaiter(this, void 0, void 0, function () {
|
|
50
|
+
var promise;
|
|
49
51
|
return __generator(this, function (_a) {
|
|
50
52
|
switch (_a.label) {
|
|
51
53
|
case 0:
|
|
52
54
|
if (!context.shouldSendTelemetry) return [3 /*break*/, 2];
|
|
53
|
-
|
|
55
|
+
promise = this.telemetry.sendTelemetry(context);
|
|
56
|
+
if (!this.config.awaitAsyncHttpRequests) return [3 /*break*/, 2];
|
|
57
|
+
return [4 /*yield*/, promise];
|
|
54
58
|
case 1:
|
|
55
59
|
_a.sent();
|
|
56
60
|
_a.label = 2;
|
|
@@ -110,7 +110,7 @@ var DefaultTelemetry = /** @class */ (function () {
|
|
|
110
110
|
case 0:
|
|
111
111
|
telemetryRequest = this.createTelemetryRequest(context);
|
|
112
112
|
context.logger.debug("sending telemetry to ".concat(telemetryRequest.url));
|
|
113
|
-
return [4 /*yield*/, this.httpClient.send(telemetryRequest)];
|
|
113
|
+
return [4 /*yield*/, this.httpClient.send(telemetryRequest, { timeoutMs: this.config.asyncTimeout })];
|
|
114
114
|
case 1:
|
|
115
115
|
_a.sent();
|
|
116
116
|
return [2 /*return*/];
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CORE_MODULE_VERSION = exports.REGEX_STRUCTURE = exports.URL_REGEX = exports.EMAIL_ADDRESS_REGEX = exports.PUSH_DATA_FEATURE_HEADER_NAME = exports.PUSH_DATA_HMAC_HEADER_NAME = exports.X_PX_BYPASS_REASON_HEADER_NAME = exports.X_PX_ORIGINAL_TOKEN_HEADER_NAME = exports.X_PX_AUTHORIZATION_HEADER_NAME = exports.BYPASS_MONITOR_HEADER_VALUE = exports.CD_PXVID_COOKIE_NAME = exports.PXDE_COOKIE_NAME = exports.PXHD_COOKIE_NAME = exports.PXVID_COOKIE_NAME = void 0;
|
|
3
|
+
exports.CORE_MODULE_VERSION = exports.REGEX_STRUCTURE = exports.URL_REGEX = exports.EMAIL_ADDRESS_REGEX = exports.PUSH_DATA_FEATURE_HEADER_NAME = exports.PUSH_DATA_HMAC_HEADER_NAME = exports.X_PX_BYPASS_REASON_HEADER_NAME = exports.X_PX_ORIGINAL_TOKEN_HEADER_NAME = exports.X_PX_AUTHORIZATION_HEADER_NAME = exports.UNLIMITED_TIMEOUT = exports.BYPASS_MONITOR_HEADER_VALUE = exports.CD_PXVID_COOKIE_NAME = exports.PXDE_COOKIE_NAME = exports.PXHD_COOKIE_NAME = exports.PXVID_COOKIE_NAME = void 0;
|
|
4
4
|
exports.PXVID_COOKIE_NAME = '_pxvid';
|
|
5
5
|
exports.PXHD_COOKIE_NAME = '_pxhd';
|
|
6
6
|
exports.PXDE_COOKIE_NAME = '_pxde';
|
|
7
7
|
exports.CD_PXVID_COOKIE_NAME = '__pxvid';
|
|
8
8
|
exports.BYPASS_MONITOR_HEADER_VALUE = '1';
|
|
9
|
+
exports.UNLIMITED_TIMEOUT = 0;
|
|
9
10
|
exports.X_PX_AUTHORIZATION_HEADER_NAME = 'x-px-authorization';
|
|
10
11
|
exports.X_PX_ORIGINAL_TOKEN_HEADER_NAME = 'x-px-original-token';
|
|
11
12
|
exports.X_PX_BYPASS_REASON_HEADER_NAME = 'x-px-bypass-reason';
|
|
@@ -14,4 +15,4 @@ exports.PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
|
|
|
14
15
|
exports.EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
|
|
15
16
|
exports.URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
|
|
16
17
|
exports.REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
|
|
17
|
-
exports.CORE_MODULE_VERSION = 'JS Core 0.
|
|
18
|
+
exports.CORE_MODULE_VERSION = 'JS Core 0.30.0';
|
|
@@ -31,7 +31,7 @@ export class HttpActivityClient {
|
|
|
31
31
|
context.logger.debug('no activities to send');
|
|
32
32
|
return true;
|
|
33
33
|
}
|
|
34
|
-
return
|
|
34
|
+
return this.postActivities(activities, context.logger);
|
|
35
35
|
}
|
|
36
36
|
catch (e) {
|
|
37
37
|
context.logger.error(`unable to send activities - ${e}`);
|
|
@@ -124,16 +124,22 @@ export class HttpActivityClient {
|
|
|
124
124
|
* @protected
|
|
125
125
|
*/
|
|
126
126
|
async postActivities(activities, logger) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
127
|
+
try {
|
|
128
|
+
const url = `${this.config.backendCollectorUrl}${ACTIVITIES_ENDPOINT}`;
|
|
129
|
+
const method = HttpMethod.POST;
|
|
130
|
+
const headers = {
|
|
131
|
+
[CONTENT_TYPE_HEADER_NAME]: [ContentType.APPLICATION_JSON],
|
|
132
|
+
[AUTHORIZATION_HEADER_NAME]: [getAuthorizationHeader(this.config.authToken)],
|
|
133
|
+
};
|
|
134
|
+
const body = activities.length === 1 ? JSON.stringify(activities[0]) : JSON.stringify(activities);
|
|
135
|
+
logger.debug(`sending ${activities.map(({ type }) => `${type} activity`).join(', ')} to ${url}`);
|
|
136
|
+
const req = new OutgoingRequestImpl({ url, method, headers, body });
|
|
137
|
+
const res = await this.httpClient.send(req, { timeoutMs: this.config.asyncTimeout });
|
|
138
|
+
return res?.status === 200;
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
logger.error(`failed to post activities - ${e}`);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
138
144
|
}
|
|
139
145
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defaultConfigurationParams } from './defaults/index.js';
|
|
2
2
|
import { DefaultLogger, LoggerSeverity } from '../logger/index.js';
|
|
3
|
-
import { convertRegexStringToRegex, CORE_MODULE_VERSION, EnforcerConfigurationError, getCollectorDomain, getScoreApiDomain, isNullOrUndefined, isValidEnumValue, ModuleMode, } from '../utils/index.js';
|
|
3
|
+
import { convertRegexStringToRegex, CORE_MODULE_VERSION, EnforcerConfigurationError, getCollectorDomain, getScoreApiDomain, isNullOrUndefined, isValidEnumValue, ModuleMode, UNLIMITED_TIMEOUT, } from '../utils/index.js';
|
|
4
4
|
import { RemoteConfigUtils } from './remote_config/index.js';
|
|
5
5
|
import { TokenVersion } from '../risk_token/index.js';
|
|
6
6
|
/**
|
|
@@ -217,6 +217,11 @@ export class ConfigurationBase {
|
|
|
217
217
|
get s2sTimeout() {
|
|
218
218
|
return this.configParams.px_s2s_timeout;
|
|
219
219
|
}
|
|
220
|
+
get asyncTimeout() {
|
|
221
|
+
return this.configParams.px_async_timeout === UNLIMITED_TIMEOUT
|
|
222
|
+
? undefined
|
|
223
|
+
: this.configParams.px_async_timeout;
|
|
224
|
+
}
|
|
220
225
|
get sensitiveHeaders() {
|
|
221
226
|
return this.configParams.px_sensitive_headers;
|
|
222
227
|
}
|
|
@@ -403,6 +408,9 @@ export class ConfigurationBase {
|
|
|
403
408
|
get enableBlockedUrlOnCaptchaBlockPage() {
|
|
404
409
|
return true;
|
|
405
410
|
}
|
|
411
|
+
get awaitAsyncHttpRequests() {
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
406
414
|
get isPostEnforceEnabled() {
|
|
407
415
|
return true;
|
|
408
416
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LoggerSeverity } from '../../logger/index.js';
|
|
2
|
-
import { ModuleMode } from '../../utils/index.js';
|
|
2
|
+
import { ModuleMode, UNLIMITED_TIMEOUT } from '../../utils/index.js';
|
|
3
3
|
import { CredentialIntelligenceVersion, DEFAULT_COMPROMISED_CREDENTIALS_HEADER_NAME, LoginSuccessfulReportingMethod, } from '../../products/index.js';
|
|
4
4
|
import { TokenVersion } from '../../risk_token/index.js';
|
|
5
5
|
export const defaultConfigurationParams = () => ({
|
|
@@ -18,6 +18,7 @@ export const defaultConfigurationParams = () => ({
|
|
|
18
18
|
px_graphql_routes_regex: [],
|
|
19
19
|
px_sensitive_routes_regex: [],
|
|
20
20
|
px_s2s_timeout: 1000,
|
|
21
|
+
px_async_timeout: UNLIMITED_TIMEOUT,
|
|
21
22
|
px_blocking_score: 100,
|
|
22
23
|
px_user_agent_max_length: 8528,
|
|
23
24
|
px_risk_cookie_max_length: 2048,
|
|
@@ -9,7 +9,7 @@ export class HttpRemoteConfigServiceClient {
|
|
|
9
9
|
}
|
|
10
10
|
async fetch(_updateRequestData) {
|
|
11
11
|
const request = this.createFetchRemoteConfigRequest();
|
|
12
|
-
const response = await this.httpClient.send(request);
|
|
12
|
+
const response = await this.httpClient.send(request, { timeoutMs: this.config.asyncTimeout });
|
|
13
13
|
return this.extractConfigFromResponse(response);
|
|
14
14
|
}
|
|
15
15
|
createFetchRemoteConfigRequest() {
|
|
@@ -3,8 +3,8 @@ import { Flow } from './Flow.js';
|
|
|
3
3
|
export class EndEnforcerFlow extends Flow {
|
|
4
4
|
constructor(config, { logServiceClient, telemetry, remoteConfigManager, activityClient, }) {
|
|
5
5
|
const phases = [
|
|
6
|
-
new SendAsyncActivitiesPhase(activityClient),
|
|
7
|
-
new SendTelemetryActivityPhase(telemetry),
|
|
6
|
+
new SendAsyncActivitiesPhase(config, activityClient),
|
|
7
|
+
new SendTelemetryActivityPhase(config, telemetry),
|
|
8
8
|
];
|
|
9
9
|
if (remoteConfigManager) {
|
|
10
10
|
phases.push(new UpdateRemoteConfigPhase(config, remoteConfigManager));
|
|
@@ -51,7 +51,7 @@ export class HttpLogServiceClient {
|
|
|
51
51
|
};
|
|
52
52
|
const body = JSON.stringify(logRecords);
|
|
53
53
|
const req = new OutgoingRequestImpl({ url, method, headers, body });
|
|
54
|
-
const res = await this.httpClient.send(req);
|
|
54
|
+
const res = await this.httpClient.send(req, { timeoutMs: this.config.asyncTimeout });
|
|
55
55
|
return res?.status === 200;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -3,13 +3,19 @@ import { Action } from '../../action/index.js';
|
|
|
3
3
|
* The `SendAsyncActivitiesPhase` class is responsible for sending all necessary asynchronous activities based on the context.
|
|
4
4
|
*/
|
|
5
5
|
export class SendAsyncActivitiesPhase {
|
|
6
|
+
config;
|
|
6
7
|
activityClient;
|
|
7
|
-
constructor(activityClient) {
|
|
8
|
+
constructor(config, activityClient) {
|
|
9
|
+
this.config = config;
|
|
8
10
|
this.activityClient = activityClient;
|
|
9
11
|
}
|
|
10
12
|
async execute(context) {
|
|
11
13
|
if ([Action.PASS_REQUEST, Action.BLOCK, Action.SIMULATED_BLOCK].includes(context.action)) {
|
|
12
|
-
|
|
14
|
+
// ensure error handling is done in the sendActivities method
|
|
15
|
+
const promise = this.activityClient.sendActivities(context);
|
|
16
|
+
if (this.config.awaitAsyncHttpRequests) {
|
|
17
|
+
await promise;
|
|
18
|
+
}
|
|
13
19
|
}
|
|
14
20
|
return { done: false };
|
|
15
21
|
}
|
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
* The `SendLogsPhase` class is responsible for sending logs to the HUMAN logging service.
|
|
3
3
|
*/
|
|
4
4
|
export class SendLogsPhase {
|
|
5
|
+
config;
|
|
5
6
|
logServiceClient;
|
|
6
|
-
constructor(
|
|
7
|
+
constructor(config, logServiceClient) {
|
|
8
|
+
this.config = config;
|
|
7
9
|
this.logServiceClient = logServiceClient;
|
|
8
10
|
}
|
|
9
11
|
async execute(context) {
|
|
10
12
|
if (context.shouldSendLogs) {
|
|
11
|
-
|
|
13
|
+
// ensure error handling is done in the sendLogs method
|
|
14
|
+
const promise = this.logServiceClient.sendLogs(context);
|
|
15
|
+
if (this.config.awaitAsyncHttpRequests) {
|
|
16
|
+
await promise;
|
|
17
|
+
}
|
|
12
18
|
}
|
|
13
19
|
return { done: false };
|
|
14
20
|
}
|
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
* The `SendTelemetryActivityPhase` class is responsible for sending the telemetry activity if necessary.
|
|
3
3
|
*/
|
|
4
4
|
export class SendTelemetryActivityPhase {
|
|
5
|
+
config;
|
|
5
6
|
telemetry;
|
|
6
|
-
constructor(telemetry) {
|
|
7
|
+
constructor(config, telemetry) {
|
|
8
|
+
this.config = config;
|
|
7
9
|
this.telemetry = telemetry;
|
|
8
10
|
}
|
|
9
11
|
async execute(context) {
|
|
10
12
|
if (context.shouldSendTelemetry) {
|
|
11
|
-
|
|
13
|
+
// ensure error handling is done in the sendTelemetry method
|
|
14
|
+
const promise = this.telemetry.sendTelemetry(context);
|
|
15
|
+
if (this.config.awaitAsyncHttpRequests) {
|
|
16
|
+
await promise;
|
|
17
|
+
}
|
|
12
18
|
}
|
|
13
19
|
return { done: false };
|
|
14
20
|
}
|
|
@@ -39,7 +39,7 @@ export class DefaultTelemetry {
|
|
|
39
39
|
async sendTelemetryActivity(context) {
|
|
40
40
|
const telemetryRequest = this.createTelemetryRequest(context);
|
|
41
41
|
context.logger.debug(`sending telemetry to ${telemetryRequest.url}`);
|
|
42
|
-
await this.httpClient.send(telemetryRequest);
|
|
42
|
+
await this.httpClient.send(telemetryRequest, { timeoutMs: this.config.asyncTimeout });
|
|
43
43
|
}
|
|
44
44
|
createTelemetryRequest(context) {
|
|
45
45
|
const url = `${this.config.backendScoreApiUrl}${TELEMETRY_ENDPOINT}`;
|
|
@@ -3,6 +3,7 @@ export const PXHD_COOKIE_NAME = '_pxhd';
|
|
|
3
3
|
export const PXDE_COOKIE_NAME = '_pxde';
|
|
4
4
|
export const CD_PXVID_COOKIE_NAME = '__pxvid';
|
|
5
5
|
export const BYPASS_MONITOR_HEADER_VALUE = '1';
|
|
6
|
+
export const UNLIMITED_TIMEOUT = 0;
|
|
6
7
|
export const X_PX_AUTHORIZATION_HEADER_NAME = 'x-px-authorization';
|
|
7
8
|
export const X_PX_ORIGINAL_TOKEN_HEADER_NAME = 'x-px-original-token';
|
|
8
9
|
export const X_PX_BYPASS_REASON_HEADER_NAME = 'x-px-bypass-reason';
|
|
@@ -11,4 +12,4 @@ export const PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
|
|
|
11
12
|
export const EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
|
|
12
13
|
export const URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
|
|
13
14
|
export const REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
|
|
14
|
-
export const CORE_MODULE_VERSION = 'JS Core 0.
|
|
15
|
+
export const CORE_MODULE_VERSION = 'JS Core 0.30.0';
|
|
@@ -81,6 +81,7 @@ export declare abstract class ConfigurationBase<Req, Res, Added, Removed extends
|
|
|
81
81
|
get monitoredRoutes(): Array<string | RegExp>;
|
|
82
82
|
get customIsMonitoredRequest(): CustomRequestFunction<Req> | null;
|
|
83
83
|
get s2sTimeout(): number;
|
|
84
|
+
get asyncTimeout(): number | undefined;
|
|
84
85
|
get sensitiveHeaders(): string[];
|
|
85
86
|
get sensitiveRoutes(): Array<string | RegExp>;
|
|
86
87
|
get customIsSensitiveRequest(): CustomRequestFunction<Req> | null;
|
|
@@ -143,5 +144,6 @@ export declare abstract class ConfigurationBase<Req, Res, Added, Removed extends
|
|
|
143
144
|
get snippetInjectionEnabled(): boolean;
|
|
144
145
|
get createCustomSnippet(): CustomSnippetFunction<Req, Res, Added, Removed> | null;
|
|
145
146
|
get enableBlockedUrlOnCaptchaBlockPage(): boolean;
|
|
147
|
+
get awaitAsyncHttpRequests(): boolean;
|
|
146
148
|
get isPostEnforceEnabled(): boolean;
|
|
147
149
|
}
|
|
@@ -31,6 +31,10 @@ export interface IConfiguration<Req, Res, Added, Removed> {
|
|
|
31
31
|
* The timeout for risk API calls, in milliseconds.
|
|
32
32
|
*/
|
|
33
33
|
readonly s2sTimeout: number;
|
|
34
|
+
/**
|
|
35
|
+
* The timeout for async HTTP requests, in milliseconds. A value of undefined means an unlimited timeout.
|
|
36
|
+
*/
|
|
37
|
+
readonly asyncTimeout: number | undefined;
|
|
34
38
|
/**
|
|
35
39
|
* An interface used to log enforcer debug and error messages.
|
|
36
40
|
*/
|
|
@@ -392,6 +396,10 @@ export interface IConfiguration<Req, Res, Added, Removed> {
|
|
|
392
396
|
* Whether the enforcer has access to the HTTP response, which is required for the postEnforce function call
|
|
393
397
|
*/
|
|
394
398
|
readonly isPostEnforceEnabled: boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Whether to await asynchronous HTTP requests (e.g., async activities, remote logger, telemetry)
|
|
401
|
+
*/
|
|
402
|
+
readonly awaitAsyncHttpRequests: boolean;
|
|
395
403
|
/**
|
|
396
404
|
* The version of the token the enforcer is able to parse.
|
|
397
405
|
*/
|
|
@@ -59,6 +59,7 @@ export type SnippetInjectionParamsOnly<Req, Res, Added, Removed> = {
|
|
|
59
59
|
*/
|
|
60
60
|
export type CommonConfigurationParams<Req, Res, Added, Removed> = TokenV3ConfigurationParamsOnly & BatchedActivitiesConfigParamsOnly & SnippetInjectionParamsOnly<Req, Res, Added, Removed> & {
|
|
61
61
|
px_s2s_timeout?: number;
|
|
62
|
+
px_async_timeout?: number;
|
|
62
63
|
px_backend_url?: string;
|
|
63
64
|
px_user_agent_max_length?: number;
|
|
64
65
|
px_logger_severity?: `${LoggerSeverity}`;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IConfiguration } from '../../config';
|
|
1
2
|
import { IContext } from '../../context';
|
|
2
3
|
import { IActivityClient } from '../../activities';
|
|
3
4
|
import { PhaseResult } from '../PhaseResult';
|
|
@@ -5,8 +6,9 @@ import { IPhase } from '../IPhase';
|
|
|
5
6
|
/**
|
|
6
7
|
* The `SendAsyncActivitiesPhase` class is responsible for sending all necessary asynchronous activities based on the context.
|
|
7
8
|
*/
|
|
8
|
-
export declare class SendAsyncActivitiesPhase<Req, Res> implements IPhase<Req, Res> {
|
|
9
|
+
export declare class SendAsyncActivitiesPhase<Req, Res, Added, Removed> implements IPhase<Req, Res> {
|
|
10
|
+
protected readonly config: IConfiguration<Req, Res, Added, Removed>;
|
|
9
11
|
protected readonly activityClient: IActivityClient<Req, Res>;
|
|
10
|
-
constructor(activityClient: IActivityClient<Req, Res>);
|
|
12
|
+
constructor(config: IConfiguration<Req, Res, Added, Removed>, activityClient: IActivityClient<Req, Res>);
|
|
11
13
|
execute(context: IContext<Req, Res>): Promise<PhaseResult>;
|
|
12
14
|
}
|
|
@@ -7,7 +7,8 @@ import { ILogServiceClient } from '../../logger';
|
|
|
7
7
|
* The `SendLogsPhase` class is responsible for sending logs to the HUMAN logging service.
|
|
8
8
|
*/
|
|
9
9
|
export declare class SendLogsPhase<Req, Res, Added, Removed> implements IPhase<Req, Res> {
|
|
10
|
+
private readonly config;
|
|
10
11
|
private readonly logServiceClient;
|
|
11
|
-
constructor(
|
|
12
|
+
constructor(config: IConfiguration<Req, Res, Added, Removed>, logServiceClient: ILogServiceClient<Req, Res>);
|
|
12
13
|
execute(context: IContext<Req, Res>): Promise<PhaseResult>;
|
|
13
14
|
}
|
|
@@ -2,12 +2,14 @@ import { IPhase } from '../IPhase';
|
|
|
2
2
|
import { PhaseResult } from '../PhaseResult';
|
|
3
3
|
import { IContext } from '../../context';
|
|
4
4
|
import { ITelemetry } from '../../telemetry';
|
|
5
|
+
import { IConfiguration } from '../../config';
|
|
5
6
|
/**
|
|
6
7
|
* The `SendTelemetryActivityPhase` class is responsible for sending the telemetry activity if necessary.
|
|
7
8
|
*/
|
|
8
|
-
export declare class SendTelemetryActivityPhase<Req, Res> implements IPhase<Req, Res> {
|
|
9
|
+
export declare class SendTelemetryActivityPhase<Req, Res, Added, Removed> implements IPhase<Req, Res> {
|
|
10
|
+
protected readonly config: IConfiguration<Req, Res, Added, Removed>;
|
|
9
11
|
protected readonly telemetry: ITelemetry<Req, Res>;
|
|
10
|
-
constructor(telemetry: ITelemetry<Req, Res>);
|
|
12
|
+
constructor(config: IConfiguration<Req, Res, Added, Removed>, telemetry: ITelemetry<Req, Res>);
|
|
11
13
|
execute(context: IContext<Req, Res>): Promise<PhaseResult>;
|
|
12
14
|
protected sendTelemetry(context: IContext<Req, Res>): Promise<void>;
|
|
13
15
|
}
|
|
@@ -3,6 +3,7 @@ export declare const PXHD_COOKIE_NAME = "_pxhd";
|
|
|
3
3
|
export declare const PXDE_COOKIE_NAME = "_pxde";
|
|
4
4
|
export declare const CD_PXVID_COOKIE_NAME = "__pxvid";
|
|
5
5
|
export declare const BYPASS_MONITOR_HEADER_VALUE = "1";
|
|
6
|
+
export declare const UNLIMITED_TIMEOUT = 0;
|
|
6
7
|
export declare const X_PX_AUTHORIZATION_HEADER_NAME = "x-px-authorization";
|
|
7
8
|
export declare const X_PX_ORIGINAL_TOKEN_HEADER_NAME = "x-px-original-token";
|
|
8
9
|
export declare const X_PX_BYPASS_REASON_HEADER_NAME = "x-px-bypass-reason";
|
|
@@ -11,4 +12,4 @@ export declare const PUSH_DATA_FEATURE_HEADER_NAME = "x-px-feature";
|
|
|
11
12
|
export declare const EMAIL_ADDRESS_REGEX: RegExp;
|
|
12
13
|
export declare const URL_REGEX: RegExp;
|
|
13
14
|
export declare const REGEX_STRUCTURE: RegExp;
|
|
14
|
-
export declare const CORE_MODULE_VERSION = "JS Core 0.
|
|
15
|
+
export declare const CORE_MODULE_VERSION = "JS Core 0.30.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "perimeterx-js-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"typesVersions": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"eslint-plugin-prettier": "^5.2.3",
|
|
69
69
|
"husky": "^9.1.7",
|
|
70
70
|
"lint-staged": "^16.0.0",
|
|
71
|
-
"mocha": "^
|
|
71
|
+
"mocha": "^11.4.0",
|
|
72
72
|
"nyc": "^17.0.0",
|
|
73
73
|
"prettier": "^3.5.3",
|
|
74
74
|
"sinon": "^20.0.0",
|