httpcloak 1.5.0 → 1.5.1
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/index.js +471 -55
- package/lib/index.mjs +35 -0
- package/npm/darwin-arm64/lib.mjs +6 -0
- package/npm/darwin-arm64/package.json +8 -1
- package/npm/darwin-x64/lib.mjs +6 -0
- package/npm/darwin-x64/package.json +8 -1
- package/npm/linux-arm64/lib.mjs +6 -0
- package/npm/linux-arm64/package.json +8 -1
- package/npm/linux-x64/lib.mjs +6 -0
- package/npm/linux-x64/package.json +8 -1
- package/npm/win32-arm64/lib.mjs +6 -0
- package/npm/win32-arm64/package.json +8 -1
- package/npm/win32-x64/lib.mjs +6 -0
- package/npm/win32-x64/package.json +8 -1
- package/package.json +21 -7
package/lib/index.js
CHANGED
|
@@ -69,17 +69,105 @@ const Preset = {
|
|
|
69
69
|
},
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* HTTP status reason phrases
|
|
74
|
+
*/
|
|
75
|
+
const HTTP_STATUS_PHRASES = {
|
|
76
|
+
100: "Continue", 101: "Switching Protocols", 102: "Processing",
|
|
77
|
+
200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information",
|
|
78
|
+
204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status",
|
|
79
|
+
300: "Multiple Choices", 301: "Moved Permanently", 302: "Found", 303: "See Other",
|
|
80
|
+
304: "Not Modified", 305: "Use Proxy", 307: "Temporary Redirect", 308: "Permanent Redirect",
|
|
81
|
+
400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden",
|
|
82
|
+
404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable",
|
|
83
|
+
407: "Proxy Authentication Required", 408: "Request Timeout", 409: "Conflict",
|
|
84
|
+
410: "Gone", 411: "Length Required", 412: "Precondition Failed",
|
|
85
|
+
413: "Payload Too Large", 414: "URI Too Long", 415: "Unsupported Media Type",
|
|
86
|
+
416: "Range Not Satisfiable", 417: "Expectation Failed", 418: "I'm a teapot",
|
|
87
|
+
421: "Misdirected Request", 422: "Unprocessable Entity", 423: "Locked",
|
|
88
|
+
424: "Failed Dependency", 425: "Too Early", 426: "Upgrade Required",
|
|
89
|
+
428: "Precondition Required", 429: "Too Many Requests",
|
|
90
|
+
431: "Request Header Fields Too Large", 451: "Unavailable For Legal Reasons",
|
|
91
|
+
500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway",
|
|
92
|
+
503: "Service Unavailable", 504: "Gateway Timeout", 505: "HTTP Version Not Supported",
|
|
93
|
+
506: "Variant Also Negotiates", 507: "Insufficient Storage", 508: "Loop Detected",
|
|
94
|
+
510: "Not Extended", 511: "Network Authentication Required",
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Cookie object from Set-Cookie header
|
|
99
|
+
*/
|
|
100
|
+
class Cookie {
|
|
101
|
+
/**
|
|
102
|
+
* @param {string} name - Cookie name
|
|
103
|
+
* @param {string} value - Cookie value
|
|
104
|
+
*/
|
|
105
|
+
constructor(name, value) {
|
|
106
|
+
this.name = name;
|
|
107
|
+
this.value = value;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
toString() {
|
|
111
|
+
return `Cookie(name=${this.name}, value=${this.value})`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Redirect info from history
|
|
117
|
+
*/
|
|
118
|
+
class RedirectInfo {
|
|
119
|
+
/**
|
|
120
|
+
* @param {number} statusCode - HTTP status code
|
|
121
|
+
* @param {string} url - Request URL
|
|
122
|
+
* @param {Object} headers - Response headers
|
|
123
|
+
*/
|
|
124
|
+
constructor(statusCode, url, headers) {
|
|
125
|
+
this.statusCode = statusCode;
|
|
126
|
+
this.url = url;
|
|
127
|
+
this.headers = headers || {};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
toString() {
|
|
131
|
+
return `RedirectInfo(statusCode=${this.statusCode}, url=${this.url})`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
72
135
|
/**
|
|
73
136
|
* Response object returned from HTTP requests
|
|
74
137
|
*/
|
|
75
138
|
class Response {
|
|
76
|
-
|
|
139
|
+
/**
|
|
140
|
+
* @param {Object} data - Response data from native library
|
|
141
|
+
* @param {number} [elapsed=0] - Elapsed time in milliseconds
|
|
142
|
+
*/
|
|
143
|
+
constructor(data, elapsed = 0) {
|
|
77
144
|
this.statusCode = data.status_code || 0;
|
|
78
145
|
this.headers = data.headers || {};
|
|
79
146
|
this._body = Buffer.from(data.body || "", "utf8");
|
|
80
147
|
this._text = data.body || "";
|
|
81
148
|
this.finalUrl = data.final_url || "";
|
|
82
149
|
this.protocol = data.protocol || "";
|
|
150
|
+
this.elapsed = elapsed; // milliseconds
|
|
151
|
+
|
|
152
|
+
// Parse cookies from response
|
|
153
|
+
this._cookies = (data.cookies || []).map(c => new Cookie(c.name || "", c.value || ""));
|
|
154
|
+
|
|
155
|
+
// Parse redirect history
|
|
156
|
+
this._history = (data.history || []).map(h => new RedirectInfo(
|
|
157
|
+
h.status_code || 0,
|
|
158
|
+
h.url || "",
|
|
159
|
+
h.headers || {}
|
|
160
|
+
));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Cookies set by this response */
|
|
164
|
+
get cookies() {
|
|
165
|
+
return this._cookies;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Redirect history (list of RedirectInfo objects) */
|
|
169
|
+
get history() {
|
|
170
|
+
return this._history;
|
|
83
171
|
}
|
|
84
172
|
|
|
85
173
|
/** Response body as string */
|
|
@@ -107,6 +195,29 @@ class Response {
|
|
|
107
195
|
return this.statusCode < 400;
|
|
108
196
|
}
|
|
109
197
|
|
|
198
|
+
/** HTTP status reason phrase (e.g., 'OK', 'Not Found') */
|
|
199
|
+
get reason() {
|
|
200
|
+
return HTTP_STATUS_PHRASES[this.statusCode] || "Unknown";
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Response encoding from Content-Type header.
|
|
205
|
+
* Returns null if not specified.
|
|
206
|
+
*/
|
|
207
|
+
get encoding() {
|
|
208
|
+
let contentType = this.headers["content-type"] || this.headers["Content-Type"] || "";
|
|
209
|
+
if (contentType.includes("charset=")) {
|
|
210
|
+
const parts = contentType.split(";");
|
|
211
|
+
for (const part of parts) {
|
|
212
|
+
const trimmed = part.trim();
|
|
213
|
+
if (trimmed.toLowerCase().startsWith("charset=")) {
|
|
214
|
+
return trimmed.split("=")[1].trim().replace(/['"]/g, "");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
|
|
110
221
|
/**
|
|
111
222
|
* Parse response body as JSON
|
|
112
223
|
*/
|
|
@@ -119,7 +230,7 @@ class Response {
|
|
|
119
230
|
*/
|
|
120
231
|
raiseForStatus() {
|
|
121
232
|
if (!this.ok) {
|
|
122
|
-
throw new HTTPCloakError(`HTTP ${this.statusCode}`);
|
|
233
|
+
throw new HTTPCloakError(`HTTP ${this.statusCode}: ${this.reason}`);
|
|
123
234
|
}
|
|
124
235
|
}
|
|
125
236
|
}
|
|
@@ -215,32 +326,158 @@ function getLibPath() {
|
|
|
215
326
|
);
|
|
216
327
|
}
|
|
217
328
|
|
|
329
|
+
// Define callback proto globally for koffi (must be before getLib)
|
|
330
|
+
const AsyncCallbackProto = koffi.proto("void AsyncCallback(int64 callbackId, str responseJson, str error)");
|
|
331
|
+
|
|
218
332
|
// Load the native library
|
|
219
333
|
let lib = null;
|
|
334
|
+
let nativeLibHandle = null;
|
|
220
335
|
|
|
221
336
|
function getLib() {
|
|
222
337
|
if (lib === null) {
|
|
223
338
|
const libPath = getLibPath();
|
|
224
|
-
|
|
339
|
+
nativeLibHandle = koffi.load(libPath);
|
|
225
340
|
|
|
226
341
|
// Use str for string returns - koffi handles the string copy automatically
|
|
227
342
|
// Note: The C strings allocated by Go are not freed, but Go's GC handles them
|
|
228
343
|
lib = {
|
|
229
|
-
httpcloak_session_new:
|
|
230
|
-
httpcloak_session_free:
|
|
231
|
-
httpcloak_get:
|
|
232
|
-
httpcloak_post:
|
|
233
|
-
httpcloak_request:
|
|
234
|
-
httpcloak_get_cookies:
|
|
235
|
-
httpcloak_set_cookie:
|
|
236
|
-
httpcloak_free_string:
|
|
237
|
-
httpcloak_version:
|
|
238
|
-
httpcloak_available_presets:
|
|
344
|
+
httpcloak_session_new: nativeLibHandle.func("httpcloak_session_new", "int64", ["str"]),
|
|
345
|
+
httpcloak_session_free: nativeLibHandle.func("httpcloak_session_free", "void", ["int64"]),
|
|
346
|
+
httpcloak_get: nativeLibHandle.func("httpcloak_get", "str", ["int64", "str", "str"]),
|
|
347
|
+
httpcloak_post: nativeLibHandle.func("httpcloak_post", "str", ["int64", "str", "str", "str"]),
|
|
348
|
+
httpcloak_request: nativeLibHandle.func("httpcloak_request", "str", ["int64", "str"]),
|
|
349
|
+
httpcloak_get_cookies: nativeLibHandle.func("httpcloak_get_cookies", "str", ["int64"]),
|
|
350
|
+
httpcloak_set_cookie: nativeLibHandle.func("httpcloak_set_cookie", "void", ["int64", "str", "str"]),
|
|
351
|
+
httpcloak_free_string: nativeLibHandle.func("httpcloak_free_string", "void", ["void*"]),
|
|
352
|
+
httpcloak_version: nativeLibHandle.func("httpcloak_version", "str", []),
|
|
353
|
+
httpcloak_available_presets: nativeLibHandle.func("httpcloak_available_presets", "str", []),
|
|
354
|
+
// Async functions
|
|
355
|
+
httpcloak_register_callback: nativeLibHandle.func("httpcloak_register_callback", "int64", [koffi.pointer(AsyncCallbackProto)]),
|
|
356
|
+
httpcloak_unregister_callback: nativeLibHandle.func("httpcloak_unregister_callback", "void", ["int64"]),
|
|
357
|
+
httpcloak_get_async: nativeLibHandle.func("httpcloak_get_async", "void", ["int64", "str", "str", "int64"]),
|
|
358
|
+
httpcloak_post_async: nativeLibHandle.func("httpcloak_post_async", "void", ["int64", "str", "str", "str", "int64"]),
|
|
359
|
+
httpcloak_request_async: nativeLibHandle.func("httpcloak_request_async", "void", ["int64", "str", "int64"]),
|
|
239
360
|
};
|
|
240
361
|
}
|
|
241
362
|
return lib;
|
|
242
363
|
}
|
|
243
364
|
|
|
365
|
+
/**
|
|
366
|
+
* Async callback manager for native Go goroutine-based async
|
|
367
|
+
*
|
|
368
|
+
* Each async request registers a callback with Go and receives a unique ID.
|
|
369
|
+
* When Go completes the request, it invokes the callback with that ID.
|
|
370
|
+
*/
|
|
371
|
+
class AsyncCallbackManager {
|
|
372
|
+
constructor() {
|
|
373
|
+
// callbackId -> { resolve, reject, startTime }
|
|
374
|
+
this._pendingRequests = new Map();
|
|
375
|
+
this._callbackPtr = null;
|
|
376
|
+
this._refTimer = null; // Timer to keep event loop alive
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Ref the event loop to prevent Node.js from exiting while requests are pending
|
|
381
|
+
*/
|
|
382
|
+
_ref() {
|
|
383
|
+
if (this._refTimer === null) {
|
|
384
|
+
// Create a timer that keeps the event loop alive
|
|
385
|
+
this._refTimer = setInterval(() => {}, 2147483647); // Max interval
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Unref the event loop when no more pending requests
|
|
391
|
+
*/
|
|
392
|
+
_unref() {
|
|
393
|
+
if (this._pendingRequests.size === 0 && this._refTimer !== null) {
|
|
394
|
+
clearInterval(this._refTimer);
|
|
395
|
+
this._refTimer = null;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Ensure the callback is set up with koffi
|
|
401
|
+
*/
|
|
402
|
+
_ensureCallback() {
|
|
403
|
+
if (this._callbackPtr !== null) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Create callback function that will be invoked by Go
|
|
408
|
+
// koffi.register expects koffi.pointer(proto) as the type
|
|
409
|
+
this._callbackPtr = koffi.register((callbackId, responseJson, error) => {
|
|
410
|
+
const pending = this._pendingRequests.get(Number(callbackId));
|
|
411
|
+
if (!pending) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
this._pendingRequests.delete(Number(callbackId));
|
|
415
|
+
this._unref(); // Check if we can release the event loop
|
|
416
|
+
|
|
417
|
+
const { resolve, reject, startTime } = pending;
|
|
418
|
+
const elapsed = Date.now() - startTime;
|
|
419
|
+
|
|
420
|
+
if (error && error !== "") {
|
|
421
|
+
let errMsg = error;
|
|
422
|
+
try {
|
|
423
|
+
const errData = JSON.parse(error);
|
|
424
|
+
errMsg = errData.error || error;
|
|
425
|
+
} catch (e) {
|
|
426
|
+
// Use raw error string
|
|
427
|
+
}
|
|
428
|
+
reject(new HTTPCloakError(errMsg));
|
|
429
|
+
} else if (responseJson) {
|
|
430
|
+
try {
|
|
431
|
+
const data = JSON.parse(responseJson);
|
|
432
|
+
if (data.error) {
|
|
433
|
+
reject(new HTTPCloakError(data.error));
|
|
434
|
+
} else {
|
|
435
|
+
resolve(new Response(data, elapsed));
|
|
436
|
+
}
|
|
437
|
+
} catch (e) {
|
|
438
|
+
reject(new HTTPCloakError(`Failed to parse response: ${e.message}`));
|
|
439
|
+
}
|
|
440
|
+
} else {
|
|
441
|
+
reject(new HTTPCloakError("No response received"));
|
|
442
|
+
}
|
|
443
|
+
}, koffi.pointer(AsyncCallbackProto));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Register a new async request
|
|
448
|
+
* @returns {{ callbackId: number, promise: Promise<Response> }}
|
|
449
|
+
*/
|
|
450
|
+
registerRequest(nativeLib) {
|
|
451
|
+
this._ensureCallback();
|
|
452
|
+
|
|
453
|
+
// Register callback with Go (each request gets unique ID)
|
|
454
|
+
const callbackId = nativeLib.httpcloak_register_callback(this._callbackPtr);
|
|
455
|
+
|
|
456
|
+
// Create promise for this request with start time
|
|
457
|
+
let resolve, reject;
|
|
458
|
+
const promise = new Promise((res, rej) => {
|
|
459
|
+
resolve = res;
|
|
460
|
+
reject = rej;
|
|
461
|
+
});
|
|
462
|
+
const startTime = Date.now();
|
|
463
|
+
|
|
464
|
+
this._pendingRequests.set(Number(callbackId), { resolve, reject, startTime });
|
|
465
|
+
this._ref(); // Keep event loop alive
|
|
466
|
+
|
|
467
|
+
return { callbackId, promise };
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Global async callback manager
|
|
472
|
+
let asyncManager = null;
|
|
473
|
+
|
|
474
|
+
function getAsyncManager() {
|
|
475
|
+
if (asyncManager === null) {
|
|
476
|
+
asyncManager = new AsyncCallbackManager();
|
|
477
|
+
}
|
|
478
|
+
return asyncManager;
|
|
479
|
+
}
|
|
480
|
+
|
|
244
481
|
/**
|
|
245
482
|
* Convert result to string (handles both direct strings and null)
|
|
246
483
|
* With "str" return type, koffi automatically handles the conversion
|
|
@@ -254,8 +491,11 @@ function resultToString(result) {
|
|
|
254
491
|
|
|
255
492
|
/**
|
|
256
493
|
* Parse response from the native library
|
|
494
|
+
* @param {string} resultPtr - Result pointer from native function
|
|
495
|
+
* @param {number} [elapsed=0] - Elapsed time in milliseconds
|
|
496
|
+
* @returns {Response}
|
|
257
497
|
*/
|
|
258
|
-
function parseResponse(resultPtr) {
|
|
498
|
+
function parseResponse(resultPtr, elapsed = 0) {
|
|
259
499
|
const result = resultToString(resultPtr);
|
|
260
500
|
if (!result) {
|
|
261
501
|
throw new HTTPCloakError("No response received");
|
|
@@ -267,7 +507,7 @@ function parseResponse(resultPtr) {
|
|
|
267
507
|
throw new HTTPCloakError(data.error);
|
|
268
508
|
}
|
|
269
509
|
|
|
270
|
-
return new Response(data);
|
|
510
|
+
return new Response(data, elapsed);
|
|
271
511
|
}
|
|
272
512
|
|
|
273
513
|
/**
|
|
@@ -442,6 +682,7 @@ class Session {
|
|
|
442
682
|
* @param {number} [options.maxRedirects=10] - Maximum number of redirects to follow
|
|
443
683
|
* @param {number} [options.retry=3] - Number of retries on failure (set to 0 to disable)
|
|
444
684
|
* @param {number[]} [options.retryOnStatus] - Status codes to retry on
|
|
685
|
+
* @param {Array} [options.auth] - Default auth [username, password] for all requests
|
|
445
686
|
*/
|
|
446
687
|
constructor(options = {}) {
|
|
447
688
|
const {
|
|
@@ -455,10 +696,12 @@ class Session {
|
|
|
455
696
|
retry = 3,
|
|
456
697
|
retryOnStatus = null,
|
|
457
698
|
preferIpv4 = false,
|
|
699
|
+
auth = null,
|
|
458
700
|
} = options;
|
|
459
701
|
|
|
460
702
|
this._lib = getLib();
|
|
461
703
|
this.headers = {}; // Default headers
|
|
704
|
+
this.auth = auth; // Default auth for all requests
|
|
462
705
|
|
|
463
706
|
const config = {
|
|
464
707
|
preset,
|
|
@@ -512,6 +755,31 @@ class Session {
|
|
|
512
755
|
return { ...this.headers, ...headers };
|
|
513
756
|
}
|
|
514
757
|
|
|
758
|
+
/**
|
|
759
|
+
* Apply cookies to headers
|
|
760
|
+
* @param {Object} headers - Existing headers
|
|
761
|
+
* @param {Object} cookies - Cookies to apply as key-value pairs
|
|
762
|
+
* @returns {Object} Headers with cookies applied
|
|
763
|
+
*/
|
|
764
|
+
_applyCookies(headers, cookies) {
|
|
765
|
+
if (!cookies || Object.keys(cookies).length === 0) {
|
|
766
|
+
return headers;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
const cookieStr = Object.entries(cookies)
|
|
770
|
+
.map(([k, v]) => `${k}=${v}`)
|
|
771
|
+
.join("; ");
|
|
772
|
+
|
|
773
|
+
headers = headers ? { ...headers } : {};
|
|
774
|
+
const existing = headers["Cookie"] || "";
|
|
775
|
+
if (existing) {
|
|
776
|
+
headers["Cookie"] = `${existing}; ${cookieStr}`;
|
|
777
|
+
} else {
|
|
778
|
+
headers["Cookie"] = cookieStr;
|
|
779
|
+
}
|
|
780
|
+
return headers;
|
|
781
|
+
}
|
|
782
|
+
|
|
515
783
|
// ===========================================================================
|
|
516
784
|
// Synchronous Methods
|
|
517
785
|
// ===========================================================================
|
|
@@ -522,19 +790,25 @@ class Session {
|
|
|
522
790
|
* @param {Object} [options] - Request options
|
|
523
791
|
* @param {Object} [options.headers] - Custom headers
|
|
524
792
|
* @param {Object} [options.params] - Query parameters
|
|
793
|
+
* @param {Object} [options.cookies] - Cookies to send with this request
|
|
525
794
|
* @param {Array} [options.auth] - Basic auth [username, password]
|
|
526
795
|
* @returns {Response} Response object
|
|
527
796
|
*/
|
|
528
797
|
getSync(url, options = {}) {
|
|
529
|
-
const { headers = null, params = null, auth = null } = options;
|
|
798
|
+
const { headers = null, params = null, cookies = null, auth = null } = options;
|
|
530
799
|
|
|
531
800
|
url = addParamsToUrl(url, params);
|
|
532
801
|
let mergedHeaders = this._mergeHeaders(headers);
|
|
533
|
-
|
|
802
|
+
// Use request auth if provided, otherwise fall back to session auth
|
|
803
|
+
const effectiveAuth = auth !== null ? auth : this.auth;
|
|
804
|
+
mergedHeaders = applyAuth(mergedHeaders, effectiveAuth);
|
|
805
|
+
mergedHeaders = this._applyCookies(mergedHeaders, cookies);
|
|
534
806
|
|
|
535
807
|
const headersJson = mergedHeaders ? JSON.stringify(mergedHeaders) : null;
|
|
808
|
+
const startTime = Date.now();
|
|
536
809
|
const result = this._lib.httpcloak_get(this._handle, url, headersJson);
|
|
537
|
-
|
|
810
|
+
const elapsed = Date.now() - startTime;
|
|
811
|
+
return parseResponse(result, elapsed);
|
|
538
812
|
}
|
|
539
813
|
|
|
540
814
|
/**
|
|
@@ -550,11 +824,12 @@ class Session {
|
|
|
550
824
|
* - { filename, content, contentType? }: file with metadata
|
|
551
825
|
* @param {Object} [options.headers] - Custom headers
|
|
552
826
|
* @param {Object} [options.params] - Query parameters
|
|
827
|
+
* @param {Object} [options.cookies] - Cookies to send with this request
|
|
553
828
|
* @param {Array} [options.auth] - Basic auth [username, password]
|
|
554
829
|
* @returns {Response} Response object
|
|
555
830
|
*/
|
|
556
831
|
postSync(url, options = {}) {
|
|
557
|
-
let { body = null, json = null, data = null, files = null, headers = null, params = null, auth = null } = options;
|
|
832
|
+
let { body = null, json = null, data = null, files = null, headers = null, params = null, cookies = null, auth = null } = options;
|
|
558
833
|
|
|
559
834
|
url = addParamsToUrl(url, params);
|
|
560
835
|
let mergedHeaders = this._mergeHeaders(headers);
|
|
@@ -588,11 +863,16 @@ class Session {
|
|
|
588
863
|
body = body.toString("utf8");
|
|
589
864
|
}
|
|
590
865
|
|
|
591
|
-
|
|
866
|
+
// Use request auth if provided, otherwise fall back to session auth
|
|
867
|
+
const effectiveAuth = auth !== null ? auth : this.auth;
|
|
868
|
+
mergedHeaders = applyAuth(mergedHeaders, effectiveAuth);
|
|
869
|
+
mergedHeaders = this._applyCookies(mergedHeaders, cookies);
|
|
592
870
|
|
|
593
871
|
const headersJson = mergedHeaders ? JSON.stringify(mergedHeaders) : null;
|
|
872
|
+
const startTime = Date.now();
|
|
594
873
|
const result = this._lib.httpcloak_post(this._handle, url, body, headersJson);
|
|
595
|
-
|
|
874
|
+
const elapsed = Date.now() - startTime;
|
|
875
|
+
return parseResponse(result, elapsed);
|
|
596
876
|
}
|
|
597
877
|
|
|
598
878
|
/**
|
|
@@ -600,11 +880,12 @@ class Session {
|
|
|
600
880
|
* @param {string} method - HTTP method
|
|
601
881
|
* @param {string} url - Request URL
|
|
602
882
|
* @param {Object} [options] - Request options
|
|
883
|
+
* @param {Object} [options.cookies] - Cookies to send with this request
|
|
603
884
|
* @param {Object} [options.files] - Files to upload as multipart/form-data
|
|
604
885
|
* @returns {Response} Response object
|
|
605
886
|
*/
|
|
606
887
|
requestSync(method, url, options = {}) {
|
|
607
|
-
let { body = null, json = null, data = null, files = null, headers = null, params = null, auth = null, timeout = null } = options;
|
|
888
|
+
let { body = null, json = null, data = null, files = null, headers = null, params = null, cookies = null, auth = null, timeout = null } = options;
|
|
608
889
|
|
|
609
890
|
url = addParamsToUrl(url, params);
|
|
610
891
|
let mergedHeaders = this._mergeHeaders(headers);
|
|
@@ -638,7 +919,10 @@ class Session {
|
|
|
638
919
|
body = body.toString("utf8");
|
|
639
920
|
}
|
|
640
921
|
|
|
641
|
-
|
|
922
|
+
// Use request auth if provided, otherwise fall back to session auth
|
|
923
|
+
const effectiveAuth = auth !== null ? auth : this.auth;
|
|
924
|
+
mergedHeaders = applyAuth(mergedHeaders, effectiveAuth);
|
|
925
|
+
mergedHeaders = this._applyCookies(mergedHeaders, cookies);
|
|
642
926
|
|
|
643
927
|
const requestConfig = {
|
|
644
928
|
method: method.toUpperCase(),
|
|
@@ -648,70 +932,171 @@ class Session {
|
|
|
648
932
|
if (body) requestConfig.body = body;
|
|
649
933
|
if (timeout) requestConfig.timeout = timeout;
|
|
650
934
|
|
|
935
|
+
const startTime = Date.now();
|
|
651
936
|
const result = this._lib.httpcloak_request(
|
|
652
937
|
this._handle,
|
|
653
938
|
JSON.stringify(requestConfig)
|
|
654
939
|
);
|
|
655
|
-
|
|
940
|
+
const elapsed = Date.now() - startTime;
|
|
941
|
+
return parseResponse(result, elapsed);
|
|
656
942
|
}
|
|
657
943
|
|
|
658
944
|
// ===========================================================================
|
|
659
|
-
// Promise-based Methods
|
|
945
|
+
// Promise-based Methods (Native async using Go goroutines)
|
|
660
946
|
// ===========================================================================
|
|
661
947
|
|
|
662
948
|
/**
|
|
663
|
-
* Perform an async GET request
|
|
949
|
+
* Perform an async GET request using native Go goroutines
|
|
664
950
|
* @param {string} url - Request URL
|
|
665
951
|
* @param {Object} [options] - Request options
|
|
952
|
+
* @param {Object} [options.cookies] - Cookies to send with this request
|
|
666
953
|
* @returns {Promise<Response>} Response object
|
|
667
954
|
*/
|
|
668
955
|
get(url, options = {}) {
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
956
|
+
const { headers = null, params = null, cookies = null, auth = null } = options;
|
|
957
|
+
|
|
958
|
+
url = addParamsToUrl(url, params);
|
|
959
|
+
let mergedHeaders = this._mergeHeaders(headers);
|
|
960
|
+
// Use request auth if provided, otherwise fall back to session auth
|
|
961
|
+
const effectiveAuth = auth !== null ? auth : this.auth;
|
|
962
|
+
mergedHeaders = applyAuth(mergedHeaders, effectiveAuth);
|
|
963
|
+
mergedHeaders = this._applyCookies(mergedHeaders, cookies);
|
|
964
|
+
|
|
965
|
+
const headersJson = mergedHeaders ? JSON.stringify(mergedHeaders) : null;
|
|
966
|
+
|
|
967
|
+
// Register async request with callback manager
|
|
968
|
+
const manager = getAsyncManager();
|
|
969
|
+
const { callbackId, promise } = manager.registerRequest(this._lib);
|
|
970
|
+
|
|
971
|
+
// Start async request
|
|
972
|
+
this._lib.httpcloak_get_async(this._handle, url, headersJson, callbackId);
|
|
973
|
+
|
|
974
|
+
return promise;
|
|
678
975
|
}
|
|
679
976
|
|
|
680
977
|
/**
|
|
681
|
-
* Perform an async POST request
|
|
978
|
+
* Perform an async POST request using native Go goroutines
|
|
682
979
|
* @param {string} url - Request URL
|
|
683
980
|
* @param {Object} [options] - Request options
|
|
981
|
+
* @param {Object} [options.cookies] - Cookies to send with this request
|
|
684
982
|
* @returns {Promise<Response>} Response object
|
|
685
983
|
*/
|
|
686
984
|
post(url, options = {}) {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
985
|
+
let { body = null, json = null, data = null, files = null, headers = null, params = null, cookies = null, auth = null } = options;
|
|
986
|
+
|
|
987
|
+
url = addParamsToUrl(url, params);
|
|
988
|
+
let mergedHeaders = this._mergeHeaders(headers);
|
|
989
|
+
|
|
990
|
+
// Handle multipart file upload
|
|
991
|
+
if (files !== null) {
|
|
992
|
+
const formData = (data !== null && typeof data === "object") ? data : null;
|
|
993
|
+
const multipart = encodeMultipart(formData, files);
|
|
994
|
+
body = multipart.body.toString("latin1");
|
|
995
|
+
mergedHeaders = mergedHeaders || {};
|
|
996
|
+
mergedHeaders["Content-Type"] = multipart.contentType;
|
|
997
|
+
}
|
|
998
|
+
// Handle JSON body
|
|
999
|
+
else if (json !== null) {
|
|
1000
|
+
body = JSON.stringify(json);
|
|
1001
|
+
mergedHeaders = mergedHeaders || {};
|
|
1002
|
+
if (!mergedHeaders["Content-Type"]) {
|
|
1003
|
+
mergedHeaders["Content-Type"] = "application/json";
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
// Handle form data
|
|
1007
|
+
else if (data !== null && typeof data === "object") {
|
|
1008
|
+
body = new URLSearchParams(data).toString();
|
|
1009
|
+
mergedHeaders = mergedHeaders || {};
|
|
1010
|
+
if (!mergedHeaders["Content-Type"]) {
|
|
1011
|
+
mergedHeaders["Content-Type"] = "application/x-www-form-urlencoded";
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
// Handle Buffer body
|
|
1015
|
+
else if (Buffer.isBuffer(body)) {
|
|
1016
|
+
body = body.toString("utf8");
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// Use request auth if provided, otherwise fall back to session auth
|
|
1020
|
+
const effectiveAuth = auth !== null ? auth : this.auth;
|
|
1021
|
+
mergedHeaders = applyAuth(mergedHeaders, effectiveAuth);
|
|
1022
|
+
mergedHeaders = this._applyCookies(mergedHeaders, cookies);
|
|
1023
|
+
|
|
1024
|
+
const headersJson = mergedHeaders ? JSON.stringify(mergedHeaders) : null;
|
|
1025
|
+
|
|
1026
|
+
// Register async request with callback manager
|
|
1027
|
+
const manager = getAsyncManager();
|
|
1028
|
+
const { callbackId, promise } = manager.registerRequest(this._lib);
|
|
1029
|
+
|
|
1030
|
+
// Start async request
|
|
1031
|
+
this._lib.httpcloak_post_async(this._handle, url, body, headersJson, callbackId);
|
|
1032
|
+
|
|
1033
|
+
return promise;
|
|
696
1034
|
}
|
|
697
1035
|
|
|
698
1036
|
/**
|
|
699
|
-
* Perform an async custom HTTP request
|
|
1037
|
+
* Perform an async custom HTTP request using native Go goroutines
|
|
700
1038
|
* @param {string} method - HTTP method
|
|
701
1039
|
* @param {string} url - Request URL
|
|
702
1040
|
* @param {Object} [options] - Request options
|
|
1041
|
+
* @param {Object} [options.cookies] - Cookies to send with this request
|
|
703
1042
|
* @returns {Promise<Response>} Response object
|
|
704
1043
|
*/
|
|
705
1044
|
request(method, url, options = {}) {
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
1045
|
+
let { body = null, json = null, data = null, files = null, headers = null, params = null, cookies = null, auth = null, timeout = null } = options;
|
|
1046
|
+
|
|
1047
|
+
url = addParamsToUrl(url, params);
|
|
1048
|
+
let mergedHeaders = this._mergeHeaders(headers);
|
|
1049
|
+
|
|
1050
|
+
// Handle multipart file upload
|
|
1051
|
+
if (files !== null) {
|
|
1052
|
+
const formData = (data !== null && typeof data === "object") ? data : null;
|
|
1053
|
+
const multipart = encodeMultipart(formData, files);
|
|
1054
|
+
body = multipart.body.toString("latin1");
|
|
1055
|
+
mergedHeaders = mergedHeaders || {};
|
|
1056
|
+
mergedHeaders["Content-Type"] = multipart.contentType;
|
|
1057
|
+
}
|
|
1058
|
+
// Handle JSON body
|
|
1059
|
+
else if (json !== null) {
|
|
1060
|
+
body = JSON.stringify(json);
|
|
1061
|
+
mergedHeaders = mergedHeaders || {};
|
|
1062
|
+
if (!mergedHeaders["Content-Type"]) {
|
|
1063
|
+
mergedHeaders["Content-Type"] = "application/json";
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
// Handle form data
|
|
1067
|
+
else if (data !== null && typeof data === "object") {
|
|
1068
|
+
body = new URLSearchParams(data).toString();
|
|
1069
|
+
mergedHeaders = mergedHeaders || {};
|
|
1070
|
+
if (!mergedHeaders["Content-Type"]) {
|
|
1071
|
+
mergedHeaders["Content-Type"] = "application/x-www-form-urlencoded";
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
// Handle Buffer body
|
|
1075
|
+
else if (Buffer.isBuffer(body)) {
|
|
1076
|
+
body = body.toString("utf8");
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// Use request auth if provided, otherwise fall back to session auth
|
|
1080
|
+
const effectiveAuth = auth !== null ? auth : this.auth;
|
|
1081
|
+
mergedHeaders = applyAuth(mergedHeaders, effectiveAuth);
|
|
1082
|
+
mergedHeaders = this._applyCookies(mergedHeaders, cookies);
|
|
1083
|
+
|
|
1084
|
+
const requestConfig = {
|
|
1085
|
+
method: method.toUpperCase(),
|
|
1086
|
+
url,
|
|
1087
|
+
};
|
|
1088
|
+
if (mergedHeaders) requestConfig.headers = mergedHeaders;
|
|
1089
|
+
if (body) requestConfig.body = body;
|
|
1090
|
+
if (timeout) requestConfig.timeout = timeout;
|
|
1091
|
+
|
|
1092
|
+
// Register async request with callback manager
|
|
1093
|
+
const manager = getAsyncManager();
|
|
1094
|
+
const { callbackId, promise } = manager.registerRequest(this._lib);
|
|
1095
|
+
|
|
1096
|
+
// Start async request
|
|
1097
|
+
this._lib.httpcloak_request_async(this._handle, JSON.stringify(requestConfig), callbackId);
|
|
1098
|
+
|
|
1099
|
+
return promise;
|
|
715
1100
|
}
|
|
716
1101
|
|
|
717
1102
|
/**
|
|
@@ -766,6 +1151,16 @@ class Session {
|
|
|
766
1151
|
return {};
|
|
767
1152
|
}
|
|
768
1153
|
|
|
1154
|
+
/**
|
|
1155
|
+
* Get a specific cookie by name
|
|
1156
|
+
* @param {string} name - Cookie name
|
|
1157
|
+
* @returns {string|null} Cookie value or null if not found
|
|
1158
|
+
*/
|
|
1159
|
+
getCookie(name) {
|
|
1160
|
+
const cookies = this.getCookies();
|
|
1161
|
+
return cookies[name] || null;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
769
1164
|
/**
|
|
770
1165
|
* Set a cookie in the session
|
|
771
1166
|
* @param {string} name - Cookie name
|
|
@@ -775,6 +1170,25 @@ class Session {
|
|
|
775
1170
|
this._lib.httpcloak_set_cookie(this._handle, name, value);
|
|
776
1171
|
}
|
|
777
1172
|
|
|
1173
|
+
/**
|
|
1174
|
+
* Delete a specific cookie by name
|
|
1175
|
+
* @param {string} name - Cookie name to delete
|
|
1176
|
+
*/
|
|
1177
|
+
deleteCookie(name) {
|
|
1178
|
+
// Set cookie to empty value - effectively deletes it
|
|
1179
|
+
this._lib.httpcloak_set_cookie(this._handle, name, "");
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
/**
|
|
1183
|
+
* Clear all cookies from the session
|
|
1184
|
+
*/
|
|
1185
|
+
clearCookies() {
|
|
1186
|
+
const cookies = this.getCookies();
|
|
1187
|
+
for (const name of Object.keys(cookies)) {
|
|
1188
|
+
this.deleteCookie(name);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
|
|
778
1192
|
/**
|
|
779
1193
|
* Get cookies as a property
|
|
780
1194
|
*/
|
|
@@ -960,6 +1374,8 @@ module.exports = {
|
|
|
960
1374
|
// Classes
|
|
961
1375
|
Session,
|
|
962
1376
|
Response,
|
|
1377
|
+
Cookie,
|
|
1378
|
+
RedirectInfo,
|
|
963
1379
|
HTTPCloakError,
|
|
964
1380
|
// Presets
|
|
965
1381
|
Preset,
|
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTPCloak Node.js Client - ESM Module
|
|
3
|
+
*
|
|
4
|
+
* A fetch/axios-compatible HTTP client with browser fingerprint emulation.
|
|
5
|
+
* Provides TLS fingerprinting for HTTP requests.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createRequire } from "module";
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
// Import the CommonJS module
|
|
12
|
+
const cjs = require("./index.js");
|
|
13
|
+
|
|
14
|
+
// Re-export all named exports
|
|
15
|
+
export const Session = cjs.Session;
|
|
16
|
+
export const Response = cjs.Response;
|
|
17
|
+
export const HTTPCloakError = cjs.HTTPCloakError;
|
|
18
|
+
export const Preset = cjs.Preset;
|
|
19
|
+
export const configure = cjs.configure;
|
|
20
|
+
export const get = cjs.get;
|
|
21
|
+
export const post = cjs.post;
|
|
22
|
+
export const put = cjs.put;
|
|
23
|
+
export const patch = cjs.patch;
|
|
24
|
+
export const head = cjs.head;
|
|
25
|
+
export const options = cjs.options;
|
|
26
|
+
export const request = cjs.request;
|
|
27
|
+
export const version = cjs.version;
|
|
28
|
+
export const availablePresets = cjs.availablePresets;
|
|
29
|
+
|
|
30
|
+
// 'delete' is a reserved word in ESM, so we export it specially
|
|
31
|
+
const del = cjs.delete;
|
|
32
|
+
export { del as delete };
|
|
33
|
+
|
|
34
|
+
// Default export (the entire module)
|
|
35
|
+
export default cjs;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@httpcloak/darwin-arm64",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "HTTPCloak native binary for darwin arm64",
|
|
5
5
|
"os": [
|
|
6
6
|
"darwin"
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
"arm64"
|
|
10
10
|
],
|
|
11
11
|
"main": "lib.js",
|
|
12
|
+
"module": "lib.mjs",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./lib.mjs",
|
|
16
|
+
"require": "./lib.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
"license": "MIT",
|
|
13
20
|
"repository": {
|
|
14
21
|
"type": "git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@httpcloak/darwin-x64",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "HTTPCloak native binary for darwin x64",
|
|
5
5
|
"os": [
|
|
6
6
|
"darwin"
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
"x64"
|
|
10
10
|
],
|
|
11
11
|
"main": "lib.js",
|
|
12
|
+
"module": "lib.mjs",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./lib.mjs",
|
|
16
|
+
"require": "./lib.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
"license": "MIT",
|
|
13
20
|
"repository": {
|
|
14
21
|
"type": "git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@httpcloak/linux-arm64",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "HTTPCloak native binary for linux arm64",
|
|
5
5
|
"os": [
|
|
6
6
|
"linux"
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
"arm64"
|
|
10
10
|
],
|
|
11
11
|
"main": "lib.js",
|
|
12
|
+
"module": "lib.mjs",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./lib.mjs",
|
|
16
|
+
"require": "./lib.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
"license": "MIT",
|
|
13
20
|
"repository": {
|
|
14
21
|
"type": "git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@httpcloak/linux-x64",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "HTTPCloak native binary for linux x64",
|
|
5
5
|
"os": [
|
|
6
6
|
"linux"
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
"x64"
|
|
10
10
|
],
|
|
11
11
|
"main": "lib.js",
|
|
12
|
+
"module": "lib.mjs",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./lib.mjs",
|
|
16
|
+
"require": "./lib.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
"license": "MIT",
|
|
13
20
|
"repository": {
|
|
14
21
|
"type": "git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@httpcloak/win32-arm64",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "HTTPCloak native binary for win32 arm64",
|
|
5
5
|
"os": [
|
|
6
6
|
"win32"
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
"arm64"
|
|
10
10
|
],
|
|
11
11
|
"main": "lib.js",
|
|
12
|
+
"module": "lib.mjs",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./lib.mjs",
|
|
16
|
+
"require": "./lib.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
"license": "MIT",
|
|
13
20
|
"repository": {
|
|
14
21
|
"type": "git",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@httpcloak/win32-x64",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "HTTPCloak native binary for win32 x64",
|
|
5
5
|
"os": [
|
|
6
6
|
"win32"
|
|
@@ -9,6 +9,13 @@
|
|
|
9
9
|
"x64"
|
|
10
10
|
],
|
|
11
11
|
"main": "lib.js",
|
|
12
|
+
"module": "lib.mjs",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./lib.mjs",
|
|
16
|
+
"require": "./lib.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
12
19
|
"license": "MIT",
|
|
13
20
|
"repository": {
|
|
14
21
|
"type": "git",
|
package/package.json
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "httpcloak",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Browser fingerprint emulation HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
|
+
"module": "lib/index.mjs",
|
|
6
7
|
"types": "lib/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./lib/index.d.ts",
|
|
12
|
+
"default": "./lib/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./lib/index.d.ts",
|
|
16
|
+
"default": "./lib/index.js"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
},
|
|
7
20
|
"scripts": {
|
|
8
21
|
"test": "node test.js",
|
|
22
|
+
"test:esm": "node test.mjs",
|
|
9
23
|
"setup-packages": "node scripts/setup-npm-packages.js"
|
|
10
24
|
},
|
|
11
25
|
"keywords": [
|
|
@@ -35,11 +49,11 @@
|
|
|
35
49
|
"koffi": "^2.9.0"
|
|
36
50
|
},
|
|
37
51
|
"optionalDependencies": {
|
|
38
|
-
"@httpcloak/linux-x64": "1.5.
|
|
39
|
-
"@httpcloak/linux-arm64": "1.5.
|
|
40
|
-
"@httpcloak/darwin-x64": "1.5.
|
|
41
|
-
"@httpcloak/darwin-arm64": "1.5.
|
|
42
|
-
"@httpcloak/win32-x64": "1.5.
|
|
43
|
-
"@httpcloak/win32-arm64": "1.5.
|
|
52
|
+
"@httpcloak/linux-x64": "1.5.1",
|
|
53
|
+
"@httpcloak/linux-arm64": "1.5.1",
|
|
54
|
+
"@httpcloak/darwin-x64": "1.5.1",
|
|
55
|
+
"@httpcloak/darwin-arm64": "1.5.1",
|
|
56
|
+
"@httpcloak/win32-x64": "1.5.1",
|
|
57
|
+
"@httpcloak/win32-arm64": "1.5.1"
|
|
44
58
|
}
|
|
45
59
|
}
|