perimeterx-js-core 0.37.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/lib/cjs/activities/utils.js +1 -1
- package/lib/cjs/impl/cipher/SubtleCryptoCipherUtils.js +3 -2
- package/lib/cjs/impl/http/{phin/PhinHttpClient.js → undici/UndiciHttpClient.js} +50 -39
- package/lib/cjs/impl/http/{phin/PhinHttpProxyClient.js → undici/UndiciHttpProxyClient.js} +12 -13
- package/lib/cjs/impl/http/{phin/PhinIncomingResponse.js → undici/UndiciIncomingResponse.js} +11 -14
- package/lib/cjs/impl/http/{phin → undici}/index.js +3 -3
- package/lib/cjs/products/account_defender/AccountDefender.js +12 -7
- package/lib/cjs/risk_api/client/abstract/RiskApiClientBase.js +12 -8
- package/lib/cjs/utils/constants.js +1 -1
- package/lib/esm/activities/utils.js +1 -1
- package/lib/esm/impl/cipher/SubtleCryptoCipherUtils.js +3 -2
- package/lib/esm/impl/http/undici/UndiciHttpClient.js +41 -0
- package/lib/esm/impl/http/undici/UndiciHttpProxyClient.js +9 -0
- package/lib/esm/impl/http/{phin/PhinIncomingResponse.js → undici/UndiciIncomingResponse.js} +2 -3
- package/lib/esm/impl/http/undici/index.js +3 -0
- package/lib/esm/products/account_defender/AccountDefender.js +11 -7
- package/lib/esm/risk_api/client/abstract/RiskApiClientBase.js +9 -5
- package/lib/esm/utils/constants.js +1 -1
- package/lib/types/impl/http/undici/UndiciHttpClient.d.ts +13 -0
- package/lib/types/impl/http/undici/UndiciHttpProxyClient.d.ts +4 -0
- package/lib/types/impl/http/{phin/PhinIncomingResponse.d.ts → undici/UndiciIncomingResponse.d.ts} +8 -3
- package/lib/types/impl/http/undici/index.d.ts +3 -0
- package/lib/types/products/account_defender/AccountDefender.d.ts +4 -0
- package/lib/types/risk_api/client/abstract/RiskApiClientBase.d.ts +2 -2
- package/lib/types/utils/constants.d.ts +1 -1
- package/package.json +11 -13
- package/lib/esm/impl/http/phin/PhinHttpClient.js +0 -42
- package/lib/esm/impl/http/phin/PhinHttpProxyClient.js +0 -10
- package/lib/esm/impl/http/phin/index.js +0 -3
- package/lib/types/impl/http/phin/PhinHttpClient.d.ts +0 -14
- package/lib/types/impl/http/phin/PhinHttpProxyClient.d.ts +0 -4
- package/lib/types/impl/http/phin/index.d.ts +0 -3
package/README.md
CHANGED
|
@@ -96,8 +96,8 @@ When developing your JavaScript/TypeScript enforcer with this library, you will
|
|
|
96
96
|
objects such that they conform to these interfaces. Of course, you are free to extend these interfaces as needed.
|
|
97
97
|
|
|
98
98
|
You will also need to implement an HTTP client. You can do this however you see fit: use the platform's built-in API
|
|
99
|
-
or use an external library if needed. This library includes implementations using `
|
|
100
|
-
for Node.js-based enforcers.
|
|
99
|
+
or use an external library if needed. This library includes implementations using `undici` (`UndiciHttpClient`,
|
|
100
|
+
`UndiciHttpProxyClient`, and `UndiciIncomingResponse`) for Node.js-based enforcers.
|
|
101
101
|
|
|
102
102
|
### Crypto
|
|
103
103
|
|
|
@@ -131,13 +131,13 @@ are provided:
|
|
|
131
131
|
All dependencies in this library have been encapsulated into specific implementations with a defined interface and therefore
|
|
132
132
|
can be swapped with other implementations. These classes are:
|
|
133
133
|
|
|
134
|
-
| **Library** | **Implementation**
|
|
135
|
-
| :---
|
|
136
|
-
| `crypto-js` | `CryptoJSHmacUtils`
|
|
137
|
-
| `js-base64` | `JSBase64Base64Utils`
|
|
138
|
-
| `uuid` | `UuidRequestIdGenerator`
|
|
139
|
-
| `ip-range-check` | `DefaultIpRangeChecker`
|
|
140
|
-
| `
|
|
134
|
+
| **Library** | **Implementation** | **Used For** |
|
|
135
|
+
| :--- |:----------------------------------------------------------------------|:-----------------------------------|
|
|
136
|
+
| `crypto-js` | `CryptoJSHmacUtils` | PXDE, telemetry, token V2/V3, etc. |
|
|
137
|
+
| `js-base64` | `JSBase64Base64Utils` | PXDE, telemetry, token V2, etc. |
|
|
138
|
+
| `uuid` | `UuidRequestIdGenerator` | `DefaultContext` |
|
|
139
|
+
| `ip-range-check` | `DefaultIpRangeChecker` | `DefaultBotDefenderFilter` |
|
|
140
|
+
| `undici` | `UndiciHttpClient`, `UndiciHttpProxyClient`, `UndiciIncomingResponse` | First party, Risk API, Activities |
|
|
141
141
|
|
|
142
142
|
## For Contributors
|
|
143
143
|
|
|
@@ -260,7 +260,7 @@ var addTokenDataToDetails = function (details, _a) {
|
|
|
260
260
|
exports.addTokenDataToDetails = addTokenDataToDetails;
|
|
261
261
|
var addRiskApiDataToAsyncActivityCommonDetails = function (details, context) {
|
|
262
262
|
var _a;
|
|
263
|
-
if (context.riskApiData.riskRtt) {
|
|
263
|
+
if (context.riskApiData.riskRtt !== undefined) {
|
|
264
264
|
details.risk_rtt = context.riskApiData.riskRtt;
|
|
265
265
|
}
|
|
266
266
|
if (context.riskApiData.s2sCallReason) {
|
|
@@ -83,11 +83,12 @@ var SubtleCryptoCipherUtils = /** @class */ (function () {
|
|
|
83
83
|
SubtleCryptoCipherUtils.prototype.base64ToArrayBuffer = function (base64String) {
|
|
84
84
|
var binaryString = this.base64Utils.base64Decode(base64String);
|
|
85
85
|
var length = binaryString.length;
|
|
86
|
-
var
|
|
86
|
+
var buffer = new ArrayBuffer(length);
|
|
87
|
+
var bytes = new Uint8Array(buffer);
|
|
87
88
|
binaryString.split('').forEach(function (char, index) {
|
|
88
89
|
bytes[index] = char.charCodeAt(0);
|
|
89
90
|
});
|
|
90
|
-
return
|
|
91
|
+
return buffer;
|
|
91
92
|
};
|
|
92
93
|
return SubtleCryptoCipherUtils;
|
|
93
94
|
}());
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
2
13
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
14
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
15
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -35,61 +46,61 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
35
46
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
47
|
}
|
|
37
48
|
};
|
|
38
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
-
};
|
|
41
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var phin_1 = __importDefault(require("phin"));
|
|
50
|
+
exports.UndiciHttpClient = void 0;
|
|
51
|
+
var undici_1 = require("undici");
|
|
52
|
+
var http_1 = require("../../../http/index.js");
|
|
46
53
|
var utils_1 = require("../../../utils/index.js");
|
|
47
|
-
var
|
|
48
|
-
var
|
|
49
|
-
|
|
50
|
-
function PhinHttpClient(options) {
|
|
54
|
+
var UndiciIncomingResponse_1 = require("./UndiciIncomingResponse.js");
|
|
55
|
+
var UndiciHttpClient = /** @class */ (function () {
|
|
56
|
+
function UndiciHttpClient(options) {
|
|
51
57
|
var _a, _b;
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
58
|
+
this.httpDispatcher = (_a = options === null || options === void 0 ? void 0 : options.httpDispatcher) !== null && _a !== void 0 ? _a : null;
|
|
59
|
+
this.httpsDispatcher = (_b = options === null || options === void 0 ? void 0 : options.httpsDispatcher) !== null && _b !== void 0 ? _b : new undici_1.Agent();
|
|
54
60
|
}
|
|
55
|
-
|
|
61
|
+
UndiciHttpClient.prototype.send = function (request, options) {
|
|
56
62
|
return __awaiter(this, void 0, void 0, function () {
|
|
57
|
-
var
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
var response, _a, _b, _c, _d, e_1, isTimeout;
|
|
64
|
+
var _e;
|
|
65
|
+
var _f, _g, _h;
|
|
66
|
+
return __generator(this, function (_j) {
|
|
67
|
+
switch (_j.label) {
|
|
60
68
|
case 0:
|
|
61
|
-
|
|
62
|
-
return [4 /*yield*/,
|
|
63
|
-
url: request.url,
|
|
69
|
+
_j.trys.push([0, 3, , 4]);
|
|
70
|
+
return [4 /*yield*/, (0, undici_1.request)(request.url, {
|
|
64
71
|
method: request.method,
|
|
65
|
-
headers: (0,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
},
|
|
72
|
+
headers: (0, http_1.joinHeaderValues)(request.headers),
|
|
73
|
+
body: request.body,
|
|
74
|
+
headersTimeout: options === null || options === void 0 ? void 0 : options.timeoutMs,
|
|
75
|
+
bodyTimeout: options === null || options === void 0 ? void 0 : options.timeoutMs,
|
|
76
|
+
dispatcher: this.getDispatcher(request),
|
|
71
77
|
})];
|
|
72
78
|
case 1:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
response = _j.sent();
|
|
80
|
+
_a = UndiciIncomingResponse_1.UndiciIncomingResponse.bind;
|
|
81
|
+
_b = [__assign({}, response)];
|
|
82
|
+
_e = {};
|
|
83
|
+
_d = (_c = Buffer).from;
|
|
84
|
+
return [4 /*yield*/, response.body.arrayBuffer()];
|
|
85
|
+
case 2: return [2 /*return*/, new (_a.apply(UndiciIncomingResponse_1.UndiciIncomingResponse, [void 0, __assign.apply(void 0, _b.concat([(_e.body = _d.apply(_c, [_j.sent()]), _e)]))]))()];
|
|
86
|
+
case 3:
|
|
87
|
+
e_1 = _j.sent();
|
|
88
|
+
isTimeout = (_h = (_g = (_f = e_1 === null || e_1 === void 0 ? void 0 : e_1.toString()) === null || _f === void 0 ? void 0 : _f.toLowerCase()) === null || _g === void 0 ? void 0 : _g.includes('timeout')) !== null && _h !== void 0 ? _h : false;
|
|
78
89
|
throw isTimeout ? new utils_1.EnforcerTimeoutError(options === null || options === void 0 ? void 0 : options.timeoutMs) : e_1;
|
|
79
|
-
case
|
|
90
|
+
case 4: return [2 /*return*/];
|
|
80
91
|
}
|
|
81
92
|
});
|
|
82
93
|
});
|
|
83
94
|
};
|
|
84
|
-
|
|
95
|
+
UndiciHttpClient.prototype.getDispatcher = function (request) {
|
|
85
96
|
if (request.url.startsWith('https://')) {
|
|
86
|
-
return this.
|
|
97
|
+
return this.httpsDispatcher;
|
|
87
98
|
}
|
|
88
|
-
if (this.
|
|
89
|
-
return this.
|
|
99
|
+
if (this.httpDispatcher) {
|
|
100
|
+
return this.httpDispatcher;
|
|
90
101
|
}
|
|
91
|
-
return new
|
|
102
|
+
return new undici_1.Agent();
|
|
92
103
|
};
|
|
93
|
-
return
|
|
104
|
+
return UndiciHttpClient;
|
|
94
105
|
}());
|
|
95
|
-
exports.
|
|
106
|
+
exports.UndiciHttpClient = UndiciHttpClient;
|
|
@@ -15,17 +15,16 @@ var __extends = (this && this.__extends) || (function () {
|
|
|
15
15
|
};
|
|
16
16
|
})();
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.
|
|
19
|
-
var
|
|
20
|
-
var
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
var
|
|
26
|
-
|
|
27
|
-
return _super.call(this, { httpsAgent: httpsAgent, httpAgent: httpAgent }) || this;
|
|
18
|
+
exports.UndiciHttpProxyClient = void 0;
|
|
19
|
+
var undici_1 = require("undici");
|
|
20
|
+
var UndiciHttpClient_1 = require("./UndiciHttpClient.js");
|
|
21
|
+
var UndiciHttpProxyClient = /** @class */ (function (_super) {
|
|
22
|
+
__extends(UndiciHttpProxyClient, _super);
|
|
23
|
+
function UndiciHttpProxyClient(proxyUrl) {
|
|
24
|
+
var httpDispatcher = new undici_1.ProxyAgent(proxyUrl);
|
|
25
|
+
var httpsDispatcher = new undici_1.ProxyAgent(proxyUrl);
|
|
26
|
+
return _super.call(this, { httpDispatcher: httpDispatcher, httpsDispatcher: httpsDispatcher }) || this;
|
|
28
27
|
}
|
|
29
|
-
return
|
|
30
|
-
}(
|
|
31
|
-
exports.
|
|
28
|
+
return UndiciHttpProxyClient;
|
|
29
|
+
}(UndiciHttpClient_1.UndiciHttpClient));
|
|
30
|
+
exports.UndiciHttpProxyClient = UndiciHttpProxyClient;
|
|
@@ -36,14 +36,13 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.
|
|
39
|
+
exports.UndiciIncomingResponse = void 0;
|
|
40
40
|
var http_1 = require("../../../http/index.js");
|
|
41
41
|
var utils_1 = require("../../../utils/index.js");
|
|
42
42
|
var DefaultUrlUtils_1 = require("../../url/DefaultUrlUtils.js");
|
|
43
|
-
var
|
|
44
|
-
function
|
|
45
|
-
|
|
46
|
-
this.status = (_a = response.statusCode) !== null && _a !== void 0 ? _a : 0;
|
|
43
|
+
var UndiciIncomingResponse = /** @class */ (function () {
|
|
44
|
+
function UndiciIncomingResponse(response) {
|
|
45
|
+
this.status = response.statusCode;
|
|
47
46
|
this.body = response.body;
|
|
48
47
|
this.headers = Object.fromEntries(Object.entries(response.headers)
|
|
49
48
|
.map(function (_a) {
|
|
@@ -55,7 +54,7 @@ var PhinIncomingResponse = /** @class */ (function () {
|
|
|
55
54
|
return !(0, utils_1.isNullOrUndefined)(value);
|
|
56
55
|
}));
|
|
57
56
|
}
|
|
58
|
-
|
|
57
|
+
UndiciIncomingResponse.prototype.formData = function () {
|
|
59
58
|
return __awaiter(this, void 0, void 0, function () {
|
|
60
59
|
var contentType, formData, _a, _b;
|
|
61
60
|
var _c;
|
|
@@ -78,7 +77,7 @@ var PhinIncomingResponse = /** @class */ (function () {
|
|
|
78
77
|
});
|
|
79
78
|
});
|
|
80
79
|
};
|
|
81
|
-
|
|
80
|
+
UndiciIncomingResponse.prototype.formUrlEncoded = function () {
|
|
82
81
|
return __awaiter(this, void 0, void 0, function () {
|
|
83
82
|
var _a, _b;
|
|
84
83
|
return __generator(this, function (_c) {
|
|
@@ -86,14 +85,12 @@ var PhinIncomingResponse = /** @class */ (function () {
|
|
|
86
85
|
case 0:
|
|
87
86
|
_b = (_a = new DefaultUrlUtils_1.DefaultUrlUtils()).createUrlSearchParams;
|
|
88
87
|
return [4 /*yield*/, this.text()];
|
|
89
|
-
case 1:
|
|
90
|
-
// Using DefaultUrlUtils since Phin safely assumes Node.js environment
|
|
91
|
-
return [2 /*return*/, _b.apply(_a, [_c.sent()])];
|
|
88
|
+
case 1: return [2 /*return*/, _b.apply(_a, [_c.sent()])];
|
|
92
89
|
}
|
|
93
90
|
});
|
|
94
91
|
});
|
|
95
92
|
};
|
|
96
|
-
|
|
93
|
+
UndiciIncomingResponse.prototype.json = function () {
|
|
97
94
|
return __awaiter(this, void 0, void 0, function () {
|
|
98
95
|
var _a, _b;
|
|
99
96
|
return __generator(this, function (_c) {
|
|
@@ -106,13 +103,13 @@ var PhinIncomingResponse = /** @class */ (function () {
|
|
|
106
103
|
});
|
|
107
104
|
});
|
|
108
105
|
};
|
|
109
|
-
|
|
106
|
+
UndiciIncomingResponse.prototype.text = function () {
|
|
110
107
|
return __awaiter(this, void 0, void 0, function () {
|
|
111
108
|
return __generator(this, function (_a) {
|
|
112
109
|
return [2 /*return*/, this.body.toString()];
|
|
113
110
|
});
|
|
114
111
|
});
|
|
115
112
|
};
|
|
116
|
-
return
|
|
113
|
+
return UndiciIncomingResponse;
|
|
117
114
|
}());
|
|
118
|
-
exports.
|
|
115
|
+
exports.UndiciIncomingResponse = UndiciIncomingResponse;
|
|
@@ -14,6 +14,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./
|
|
18
|
-
__exportStar(require("./
|
|
19
|
-
__exportStar(require("./
|
|
17
|
+
__exportStar(require("./UndiciIncomingResponse.js"), exports);
|
|
18
|
+
__exportStar(require("./UndiciHttpClient.js"), exports);
|
|
19
|
+
__exportStar(require("./UndiciHttpProxyClient.js"), exports);
|
|
@@ -127,18 +127,15 @@ var AccountDefender = /** @class */ (function () {
|
|
|
127
127
|
: null;
|
|
128
128
|
};
|
|
129
129
|
AccountDefender.prototype.extractJwtData = function (jwt, userIdFieldName, additionalFieldNames, context) {
|
|
130
|
+
var _this = this;
|
|
130
131
|
try {
|
|
131
132
|
var decodedJwt_1 = this.getDecodedJwt(jwt, context);
|
|
132
133
|
if (decodedJwt_1) {
|
|
133
|
-
var appUserId =
|
|
134
|
+
var appUserId = this.lookupJwtField(decodedJwt_1, userIdFieldName).value;
|
|
134
135
|
var additionalFields = additionalFieldNames.reduce(function (matchedFields, fieldName) {
|
|
135
|
-
var
|
|
136
|
-
var value = utils_1.getPropertyFromObject.apply(void 0, __spreadArray([decodedJwt_1], fieldNameParts, false));
|
|
136
|
+
var _a = _this.lookupJwtField(decodedJwt_1, fieldName), value = _a.value, key = _a.key;
|
|
137
137
|
if (value) {
|
|
138
|
-
|
|
139
|
-
if (key !== undefined) {
|
|
140
|
-
matchedFields[key] = value;
|
|
141
|
-
}
|
|
138
|
+
matchedFields[key] = value;
|
|
142
139
|
}
|
|
143
140
|
return matchedFields;
|
|
144
141
|
}, {});
|
|
@@ -150,6 +147,14 @@ var AccountDefender = /** @class */ (function () {
|
|
|
150
147
|
}
|
|
151
148
|
return null;
|
|
152
149
|
};
|
|
150
|
+
AccountDefender.prototype.lookupJwtField = function (decodedJwt, fieldName) {
|
|
151
|
+
if (Object.prototype.hasOwnProperty.call(decodedJwt, fieldName)) {
|
|
152
|
+
return { value: decodedJwt[fieldName], key: fieldName };
|
|
153
|
+
}
|
|
154
|
+
var parts = fieldName.split('.');
|
|
155
|
+
var value = utils_1.getPropertyFromObject.apply(void 0, __spreadArray([decodedJwt], parts, false));
|
|
156
|
+
return { value: value, key: fieldName };
|
|
157
|
+
};
|
|
153
158
|
AccountDefender.prototype.getDecodedJwt = function (jwt, context) {
|
|
154
159
|
var _a, _b;
|
|
155
160
|
try {
|
|
@@ -54,7 +54,7 @@ var RiskApiClientBase = /** @class */ (function () {
|
|
|
54
54
|
*/
|
|
55
55
|
RiskApiClientBase.prototype.executeRiskApi = function (context) {
|
|
56
56
|
return __awaiter(this, void 0, void 0, function () {
|
|
57
|
-
var response, riskResponse, riskApiData, riskRequest, err_1;
|
|
57
|
+
var response, riskResponse, riskApiData, riskRequestStartTime, riskRequest, err_1;
|
|
58
58
|
return __generator(this, function (_a) {
|
|
59
59
|
switch (_a.label) {
|
|
60
60
|
case 0:
|
|
@@ -63,7 +63,8 @@ var RiskApiClientBase = /** @class */ (function () {
|
|
|
63
63
|
case 1:
|
|
64
64
|
_a.trys.push([1, 8, , 10]);
|
|
65
65
|
riskRequest = this.createRiskRequest(context);
|
|
66
|
-
|
|
66
|
+
riskRequestStartTime = Date.now();
|
|
67
|
+
return [4 /*yield*/, this.sendRiskActivity(riskRequest, riskApiData, context, riskRequestStartTime)];
|
|
67
68
|
case 2:
|
|
68
69
|
response = _a.sent();
|
|
69
70
|
if (!((response === null || response === void 0 ? void 0 : response.status) !== 200)) return [3 /*break*/, 4];
|
|
@@ -83,7 +84,7 @@ var RiskApiClientBase = /** @class */ (function () {
|
|
|
83
84
|
case 8:
|
|
84
85
|
err_1 = _a.sent();
|
|
85
86
|
if ((0, exports.isEnforcerTimeoutError)(err_1)) {
|
|
86
|
-
return [2 /*return*/, this.handleS2STimeout(riskApiData)];
|
|
87
|
+
return [2 /*return*/, this.handleS2STimeout(riskApiData, riskRequestStartTime)];
|
|
87
88
|
}
|
|
88
89
|
context.logger.error("caught error in risk api: ".concat(err_1, " - ").concat(JSON.stringify(context.requestData.url)));
|
|
89
90
|
return [4 /*yield*/, this.handleS2SError(riskApiData, context, response, err_1)];
|
|
@@ -97,14 +98,14 @@ var RiskApiClientBase = /** @class */ (function () {
|
|
|
97
98
|
var headersWithoutSensitive = (0, utils_1.removeSensitiveHeaders)(headers, this.config.sensitiveHeaders);
|
|
98
99
|
return (0, activities_1.toHeaderEntryArray)(headersWithoutSensitive);
|
|
99
100
|
};
|
|
100
|
-
RiskApiClientBase.prototype.sendRiskActivity = function (
|
|
101
|
-
return __awaiter(this,
|
|
102
|
-
var
|
|
101
|
+
RiskApiClientBase.prototype.sendRiskActivity = function (riskRequest_1, riskApiData_1, context_1) {
|
|
102
|
+
return __awaiter(this, arguments, void 0, function (riskRequest, riskApiData, context, startTime) {
|
|
103
|
+
var response, endTime;
|
|
104
|
+
if (startTime === void 0) { startTime = Date.now(); }
|
|
103
105
|
return __generator(this, function (_a) {
|
|
104
106
|
switch (_a.label) {
|
|
105
107
|
case 0:
|
|
106
108
|
context.logger.debug("sending risk api to ".concat(riskRequest.url));
|
|
107
|
-
startTime = Date.now();
|
|
108
109
|
return [4 /*yield*/, this.httpClient.send(riskRequest, { timeoutMs: this.config.s2sTimeout })];
|
|
109
110
|
case 1:
|
|
110
111
|
response = _a.sent();
|
|
@@ -125,8 +126,11 @@ var RiskApiClientBase = /** @class */ (function () {
|
|
|
125
126
|
_a[http_1.AUTHORIZATION_HEADER_NAME] = [(0, utils_1.getAuthorizationHeader)(this.config.authToken)],
|
|
126
127
|
_a;
|
|
127
128
|
};
|
|
128
|
-
RiskApiClientBase.prototype.handleS2STimeout = function (riskApiData) {
|
|
129
|
+
RiskApiClientBase.prototype.handleS2STimeout = function (riskApiData, startTime) {
|
|
129
130
|
riskApiData.riskApiCallResult = model_1.RiskApiCallResult.TIMEOUT;
|
|
131
|
+
if (startTime !== undefined) {
|
|
132
|
+
riskApiData.riskRtt = Date.now() - startTime;
|
|
133
|
+
}
|
|
130
134
|
return riskApiData;
|
|
131
135
|
};
|
|
132
136
|
RiskApiClientBase.prototype.handleS2SError = function (riskApiData, context, response, error) {
|
|
@@ -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.
|
|
18
|
+
exports.CORE_MODULE_VERSION = 'JS Core 1.0.0';
|
|
@@ -240,7 +240,7 @@ export const addTokenDataToDetails = (details, { token, mobileData }) => {
|
|
|
240
240
|
}
|
|
241
241
|
};
|
|
242
242
|
export const addRiskApiDataToAsyncActivityCommonDetails = (details, context) => {
|
|
243
|
-
if (context.riskApiData.riskRtt) {
|
|
243
|
+
if (context.riskApiData.riskRtt !== undefined) {
|
|
244
244
|
details.risk_rtt = context.riskApiData.riskRtt;
|
|
245
245
|
}
|
|
246
246
|
if (context.riskApiData.s2sCallReason) {
|
|
@@ -29,10 +29,11 @@ export class SubtleCryptoCipherUtils {
|
|
|
29
29
|
base64ToArrayBuffer(base64String) {
|
|
30
30
|
const binaryString = this.base64Utils.base64Decode(base64String);
|
|
31
31
|
const length = binaryString.length;
|
|
32
|
-
const
|
|
32
|
+
const buffer = new ArrayBuffer(length);
|
|
33
|
+
const bytes = new Uint8Array(buffer);
|
|
33
34
|
binaryString.split('').forEach((char, index) => {
|
|
34
35
|
bytes[index] = char.charCodeAt(0);
|
|
35
36
|
});
|
|
36
|
-
return
|
|
37
|
+
return buffer;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Agent, request as undiciRequest } from 'undici';
|
|
2
|
+
import { joinHeaderValues } from '../../../http/index.js';
|
|
3
|
+
import { EnforcerTimeoutError } from '../../../utils/index.js';
|
|
4
|
+
import { UndiciIncomingResponse } from './UndiciIncomingResponse.js';
|
|
5
|
+
export class UndiciHttpClient {
|
|
6
|
+
httpDispatcher;
|
|
7
|
+
httpsDispatcher;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.httpDispatcher = options?.httpDispatcher ?? null;
|
|
10
|
+
this.httpsDispatcher = options?.httpsDispatcher ?? new Agent();
|
|
11
|
+
}
|
|
12
|
+
async send(request, options) {
|
|
13
|
+
try {
|
|
14
|
+
const response = await undiciRequest(request.url, {
|
|
15
|
+
method: request.method,
|
|
16
|
+
headers: joinHeaderValues(request.headers),
|
|
17
|
+
body: request.body,
|
|
18
|
+
headersTimeout: options?.timeoutMs,
|
|
19
|
+
bodyTimeout: options?.timeoutMs,
|
|
20
|
+
dispatcher: this.getDispatcher(request),
|
|
21
|
+
});
|
|
22
|
+
return new UndiciIncomingResponse({
|
|
23
|
+
...response,
|
|
24
|
+
body: Buffer.from(await response.body.arrayBuffer()),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
const isTimeout = e?.toString()?.toLowerCase()?.includes('timeout') ?? false;
|
|
29
|
+
throw isTimeout ? new EnforcerTimeoutError(options?.timeoutMs) : e;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
getDispatcher(request) {
|
|
33
|
+
if (request.url.startsWith('https://')) {
|
|
34
|
+
return this.httpsDispatcher;
|
|
35
|
+
}
|
|
36
|
+
if (this.httpDispatcher) {
|
|
37
|
+
return this.httpDispatcher;
|
|
38
|
+
}
|
|
39
|
+
return new Agent();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ProxyAgent } from 'undici';
|
|
2
|
+
import { UndiciHttpClient } from './UndiciHttpClient.js';
|
|
3
|
+
export class UndiciHttpProxyClient extends UndiciHttpClient {
|
|
4
|
+
constructor(proxyUrl) {
|
|
5
|
+
const httpDispatcher = new ProxyAgent(proxyUrl);
|
|
6
|
+
const httpsDispatcher = new ProxyAgent(proxyUrl);
|
|
7
|
+
super({ httpDispatcher, httpsDispatcher });
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { CONTENT_TYPE_HEADER_NAME, MultipartFormDataUtils, } from '../../../http/index.js';
|
|
2
2
|
import { EnforcerError, isNullOrUndefined } from '../../../utils/index.js';
|
|
3
3
|
import { DefaultUrlUtils } from '../../url/DefaultUrlUtils.js';
|
|
4
|
-
export class
|
|
4
|
+
export class UndiciIncomingResponse {
|
|
5
5
|
status;
|
|
6
6
|
headers;
|
|
7
7
|
body;
|
|
8
8
|
constructor(response) {
|
|
9
|
-
this.status = response.statusCode
|
|
9
|
+
this.status = response.statusCode;
|
|
10
10
|
this.body = response.body;
|
|
11
11
|
this.headers = Object.fromEntries(Object.entries(response.headers)
|
|
12
12
|
.map(([key, val]) => [key, typeof val === 'string' ? [val] : val])
|
|
@@ -24,7 +24,6 @@ export class PhinIncomingResponse {
|
|
|
24
24
|
return formData;
|
|
25
25
|
}
|
|
26
26
|
async formUrlEncoded() {
|
|
27
|
-
// Using DefaultUrlUtils since Phin safely assumes Node.js environment
|
|
28
27
|
return new DefaultUrlUtils().createUrlSearchParams(await this.text());
|
|
29
28
|
}
|
|
30
29
|
async json() {
|
|
@@ -51,15 +51,11 @@ export class AccountDefender {
|
|
|
51
51
|
try {
|
|
52
52
|
const decodedJwt = this.getDecodedJwt(jwt, context);
|
|
53
53
|
if (decodedJwt) {
|
|
54
|
-
const appUserId =
|
|
54
|
+
const { value: appUserId } = this.lookupJwtField(decodedJwt, userIdFieldName);
|
|
55
55
|
const additionalFields = additionalFieldNames.reduce((matchedFields, fieldName) => {
|
|
56
|
-
const
|
|
57
|
-
const value = getPropertyFromObject(decodedJwt, ...fieldNameParts);
|
|
56
|
+
const { value, key } = this.lookupJwtField(decodedJwt, fieldName);
|
|
58
57
|
if (value) {
|
|
59
|
-
|
|
60
|
-
if (key !== undefined) {
|
|
61
|
-
matchedFields[key] = value;
|
|
62
|
-
}
|
|
58
|
+
matchedFields[key] = value;
|
|
63
59
|
}
|
|
64
60
|
return matchedFields;
|
|
65
61
|
}, {});
|
|
@@ -71,6 +67,14 @@ export class AccountDefender {
|
|
|
71
67
|
}
|
|
72
68
|
return null;
|
|
73
69
|
}
|
|
70
|
+
lookupJwtField(decodedJwt, fieldName) {
|
|
71
|
+
if (Object.prototype.hasOwnProperty.call(decodedJwt, fieldName)) {
|
|
72
|
+
return { value: decodedJwt[fieldName], key: fieldName };
|
|
73
|
+
}
|
|
74
|
+
const parts = fieldName.split('.');
|
|
75
|
+
const value = getPropertyFromObject(decodedJwt, ...parts);
|
|
76
|
+
return { value, key: fieldName };
|
|
77
|
+
}
|
|
74
78
|
getDecodedJwt(jwt, context) {
|
|
75
79
|
try {
|
|
76
80
|
const encodedPayload = jwt.split('.')?.[1];
|
|
@@ -19,9 +19,11 @@ export class RiskApiClientBase {
|
|
|
19
19
|
let response;
|
|
20
20
|
let riskResponse;
|
|
21
21
|
const riskApiData = { riskApiCallResult: RiskApiCallResult.NONE };
|
|
22
|
+
let riskRequestStartTime;
|
|
22
23
|
try {
|
|
23
24
|
const riskRequest = this.createRiskRequest(context);
|
|
24
|
-
|
|
25
|
+
riskRequestStartTime = Date.now();
|
|
26
|
+
response = await this.sendRiskActivity(riskRequest, riskApiData, context, riskRequestStartTime);
|
|
25
27
|
if (response?.status !== 200) {
|
|
26
28
|
return await this.handleS2SError(riskApiData, context, response);
|
|
27
29
|
}
|
|
@@ -35,7 +37,7 @@ export class RiskApiClientBase {
|
|
|
35
37
|
}
|
|
36
38
|
catch (err) {
|
|
37
39
|
if (isEnforcerTimeoutError(err)) {
|
|
38
|
-
return this.handleS2STimeout(riskApiData);
|
|
40
|
+
return this.handleS2STimeout(riskApiData, riskRequestStartTime);
|
|
39
41
|
}
|
|
40
42
|
context.logger.error(`caught error in risk api: ${err} - ${JSON.stringify(context.requestData.url)}`);
|
|
41
43
|
return await this.handleS2SError(riskApiData, context, response, err);
|
|
@@ -45,9 +47,8 @@ export class RiskApiClientBase {
|
|
|
45
47
|
const headersWithoutSensitive = removeSensitiveHeaders(headers, this.config.sensitiveHeaders);
|
|
46
48
|
return toHeaderEntryArray(headersWithoutSensitive);
|
|
47
49
|
}
|
|
48
|
-
async sendRiskActivity(riskRequest, riskApiData, context) {
|
|
50
|
+
async sendRiskActivity(riskRequest, riskApiData, context, startTime = Date.now()) {
|
|
49
51
|
context.logger.debug(`sending risk api to ${riskRequest.url}`);
|
|
50
|
-
const startTime = Date.now();
|
|
51
52
|
const response = await this.httpClient.send(riskRequest, { timeoutMs: this.config.s2sTimeout });
|
|
52
53
|
const endTime = Date.now();
|
|
53
54
|
riskApiData.riskApiCallResult = RiskApiCallResult.SUCCESSFUL;
|
|
@@ -62,8 +63,11 @@ export class RiskApiClientBase {
|
|
|
62
63
|
[AUTHORIZATION_HEADER_NAME]: [getAuthorizationHeader(this.config.authToken)],
|
|
63
64
|
};
|
|
64
65
|
}
|
|
65
|
-
handleS2STimeout(riskApiData) {
|
|
66
|
+
handleS2STimeout(riskApiData, startTime) {
|
|
66
67
|
riskApiData.riskApiCallResult = RiskApiCallResult.TIMEOUT;
|
|
68
|
+
if (startTime !== undefined) {
|
|
69
|
+
riskApiData.riskRtt = Date.now() - startTime;
|
|
70
|
+
}
|
|
67
71
|
return riskApiData;
|
|
68
72
|
}
|
|
69
73
|
async handleS2SError(riskApiData, context, response, error) {
|
|
@@ -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.
|
|
15
|
+
export const CORE_MODULE_VERSION = 'JS Core 1.0.0';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Dispatcher } from 'undici';
|
|
2
|
+
import { HttpSendOptions, IHttpClient, IIncomingResponse, IOutgoingRequest } from '../../../http';
|
|
3
|
+
export type UndiciHttpClientOptions = {
|
|
4
|
+
httpDispatcher?: Dispatcher;
|
|
5
|
+
httpsDispatcher?: Dispatcher;
|
|
6
|
+
};
|
|
7
|
+
export declare class UndiciHttpClient implements IHttpClient {
|
|
8
|
+
private readonly httpDispatcher;
|
|
9
|
+
private readonly httpsDispatcher;
|
|
10
|
+
constructor(options?: UndiciHttpClientOptions);
|
|
11
|
+
send(request: IOutgoingRequest, options?: HttpSendOptions): Promise<IIncomingResponse>;
|
|
12
|
+
protected getDispatcher(request: IOutgoingRequest): Dispatcher;
|
|
13
|
+
}
|
package/lib/types/impl/http/{phin/PhinIncomingResponse.d.ts → undici/UndiciIncomingResponse.d.ts}
RENAMED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IncomingHttpHeaders } from 'undici/types/header';
|
|
2
2
|
import { IFormData, IIncomingResponse, ReadonlyHeaders } from '../../../http';
|
|
3
3
|
import { IUrlSearchParams } from '../../../utils';
|
|
4
|
-
export
|
|
4
|
+
export type UndiciIncomingResponseData = {
|
|
5
|
+
statusCode: number;
|
|
6
|
+
headers: IncomingHttpHeaders;
|
|
7
|
+
body: Buffer;
|
|
8
|
+
};
|
|
9
|
+
export declare class UndiciIncomingResponse implements IIncomingResponse {
|
|
5
10
|
readonly status: number;
|
|
6
11
|
readonly headers: ReadonlyHeaders;
|
|
7
12
|
readonly body: Buffer;
|
|
8
|
-
constructor(response:
|
|
13
|
+
constructor(response: UndiciIncomingResponseData);
|
|
9
14
|
formData(): Promise<IFormData>;
|
|
10
15
|
formUrlEncoded(): Promise<IUrlSearchParams>;
|
|
11
16
|
json(): Promise<any>;
|
|
@@ -18,5 +18,9 @@ export declare class AccountDefender<Req, Res, Supported extends string, Added>
|
|
|
18
18
|
modifyOutgoingResponse(_context: ReadonlyContext<Req, Res>): Promise<void>;
|
|
19
19
|
protected getJwtData(context: ReadonlyContext<Req, Res>): JwtData | null;
|
|
20
20
|
protected extractJwtData(jwt: string, userIdFieldName: string, additionalFieldNames: string[], context: ReadonlyContext<Req, Res>): JwtData | null;
|
|
21
|
+
protected lookupJwtField(decodedJwt: any, fieldName: string): {
|
|
22
|
+
value: any;
|
|
23
|
+
key: string;
|
|
24
|
+
};
|
|
21
25
|
protected getDecodedJwt(jwt: string, context: ReadonlyContext<Req, Res>): any | null;
|
|
22
26
|
}
|
|
@@ -17,10 +17,10 @@ export declare abstract class RiskApiClientBase<Req, Res, Supported extends stri
|
|
|
17
17
|
*/
|
|
18
18
|
executeRiskApi(context: ReadonlyContext<Req, Res>): Promise<RiskApiData>;
|
|
19
19
|
protected formatRiskHeadersField(headers: ReadonlyHeaders): HeaderEntry[];
|
|
20
|
-
protected sendRiskActivity(riskRequest: OutgoingRequestImpl, riskApiData: RiskApiData, context: ReadonlyContext<Req, Res
|
|
20
|
+
protected sendRiskActivity(riskRequest: OutgoingRequestImpl, riskApiData: RiskApiData, context: ReadonlyContext<Req, Res>, startTime?: number): Promise<IIncomingResponse>;
|
|
21
21
|
protected getRiskUrl(): string;
|
|
22
22
|
protected getRiskHeaders(): ReadonlyHeaders;
|
|
23
|
-
protected handleS2STimeout(riskApiData: RiskApiData): RiskApiData;
|
|
23
|
+
protected handleS2STimeout(riskApiData: RiskApiData, startTime?: number): RiskApiData;
|
|
24
24
|
protected handleS2SError(riskApiData: RiskApiData, context: ReadonlyContext<Req, Res>, response?: IIncomingResponse, error?: unknown): Promise<RiskApiData>;
|
|
25
25
|
}
|
|
26
26
|
export declare const isEnforcerTimeoutError: (err: unknown) => boolean;
|
|
@@ -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.
|
|
15
|
+
export declare const CORE_MODULE_VERSION = "JS Core 1.0.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "perimeterx-js-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"typesVersions": {
|
|
@@ -44,25 +44,23 @@
|
|
|
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",
|
|
49
47
|
"ip-range-check": "^0.2.0",
|
|
50
48
|
"js-base64": "^3.7.2",
|
|
51
|
-
"phin": "^3.7.0",
|
|
52
49
|
"ts-essentials": "^10.0.0",
|
|
53
|
-
"
|
|
50
|
+
"undici": "^6.26.0",
|
|
51
|
+
"uuid": "^11.1.1"
|
|
54
52
|
},
|
|
55
53
|
"devDependencies": {
|
|
56
54
|
"@types/chai": "^5.2.1",
|
|
57
55
|
"@types/chai-as-promised": "^8.0.2",
|
|
58
56
|
"@types/crypto-js": "^4.1.1",
|
|
59
|
-
"@types/mocha": "^10.0.
|
|
57
|
+
"@types/mocha": "^10.0.10",
|
|
60
58
|
"@types/node": "^18.19.50 || ^20.6.0 || ^22.0.0",
|
|
61
|
-
"@types/sinon": "^
|
|
59
|
+
"@types/sinon": "^21.0.1",
|
|
62
60
|
"@types/uuid": "^10.0.0",
|
|
63
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
64
|
-
"@typescript-eslint/parser": "^8.
|
|
65
|
-
"c8": "^
|
|
61
|
+
"@typescript-eslint/eslint-plugin": "^8.61.0",
|
|
62
|
+
"@typescript-eslint/parser": "^8.61.0",
|
|
63
|
+
"c8": "^11.0.0",
|
|
66
64
|
"chai": "^6.2.0",
|
|
67
65
|
"chai-as-promised": "^8.0.0",
|
|
68
66
|
"core-js": "^3.19.1",
|
|
@@ -71,10 +69,10 @@
|
|
|
71
69
|
"eslint-plugin-prettier": "^5.2.3",
|
|
72
70
|
"husky": "^9.1.7",
|
|
73
71
|
"lint-staged": "^16.0.0",
|
|
74
|
-
"mocha": "^11.
|
|
72
|
+
"mocha": "^11.7.6",
|
|
75
73
|
"prettier": "^3.5.3",
|
|
76
|
-
"sinon": "^
|
|
77
|
-
"ts-loader": "^9.
|
|
74
|
+
"sinon": "^22.0.0",
|
|
75
|
+
"ts-loader": "^9.6.0",
|
|
78
76
|
"ts-node": "^10.9.1",
|
|
79
77
|
"tsc-alias": "^1.8.11",
|
|
80
78
|
"typescript": "^5.1.6"
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Agent as HttpAgent } from 'http';
|
|
2
|
-
import { Agent as HttpsAgent } from 'https';
|
|
3
|
-
import phin from 'phin';
|
|
4
|
-
import { EnforcerTimeoutError } from '../../../utils/index.js';
|
|
5
|
-
import { joinHeaderValues } from '../../../http/index.js';
|
|
6
|
-
import { PhinIncomingResponse } from './PhinIncomingResponse.js';
|
|
7
|
-
export class PhinHttpClient {
|
|
8
|
-
httpAgent;
|
|
9
|
-
httpsAgent;
|
|
10
|
-
constructor(options) {
|
|
11
|
-
this.httpAgent = options?.httpAgent ?? null;
|
|
12
|
-
this.httpsAgent = options?.httpsAgent ?? new HttpsAgent({ keepAlive: true });
|
|
13
|
-
}
|
|
14
|
-
async send(request, options) {
|
|
15
|
-
try {
|
|
16
|
-
const res = await phin.promisified({
|
|
17
|
-
url: request.url,
|
|
18
|
-
method: request.method,
|
|
19
|
-
headers: joinHeaderValues(request.headers),
|
|
20
|
-
data: request.body,
|
|
21
|
-
timeout: options?.timeoutMs,
|
|
22
|
-
core: {
|
|
23
|
-
agent: this.getAgent(request),
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
return new PhinIncomingResponse(res);
|
|
27
|
-
}
|
|
28
|
-
catch (e) {
|
|
29
|
-
const isTimeout = e?.toString().toLowerCase().includes('timeout');
|
|
30
|
-
throw isTimeout ? new EnforcerTimeoutError(options?.timeoutMs) : e;
|
|
31
|
-
}
|
|
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
|
-
}
|
|
42
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
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,14 +0,0 @@
|
|
|
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
|
-
};
|
|
8
|
-
export declare class PhinHttpClient implements IHttpClient {
|
|
9
|
-
private readonly httpAgent;
|
|
10
|
-
private readonly httpsAgent;
|
|
11
|
-
constructor(options?: PhinHttpClientOptions);
|
|
12
|
-
send(request: IOutgoingRequest, options?: HttpSendOptions): Promise<IIncomingResponse>;
|
|
13
|
-
protected getAgent(request: IOutgoingRequest): HttpAgent;
|
|
14
|
-
}
|