wreq-js 0.1.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/LICENSE +22 -0
- package/README.md +260 -0
- package/dist/generated-types.d.ts +9 -0
- package/dist/generated-types.d.ts.map +1 -0
- package/dist/generated-types.js +7 -0
- package/dist/generated-types.js.map +1 -0
- package/dist/test/http.spec.d.ts +2 -0
- package/dist/test/http.spec.d.ts.map +1 -0
- package/dist/test/http.spec.js +63 -0
- package/dist/test/http.spec.js.map +1 -0
- package/dist/test/websocket.spec.d.ts +2 -0
- package/dist/test/websocket.spec.d.ts.map +1 -0
- package/dist/test/websocket.spec.js +122 -0
- package/dist/test/websocket.spec.js.map +1 -0
- package/dist/types.d.ts +112 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/dist/wreq-js.d.ts +136 -0
- package/dist/wreq-js.d.ts.map +1 -0
- package/dist/wreq-js.js +253 -0
- package/dist/wreq-js.js.map +1 -0
- package/package.json +91 -0
- package/rust/wreq-js.darwin-arm64.node +0 -0
- package/rust/wreq-js.darwin-x64.node +0 -0
- package/rust/wreq-js.linux-arm64-gnu.node +0 -0
- package/rust/wreq-js.linux-x64-gnu.node +0 -0
- package/rust/wreq-js.win32-x64-msvc.node +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 will-work-for-meal
|
|
4
|
+
Copyright (c) 2025 Oleksandr Herasymov
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# wreq-js
|
|
2
|
+
|
|
3
|
+
High-performance Node.js bindings for the Rust-based wreq HTTP client with native TLS and HTTP/2 browser impersonation.
|
|
4
|
+
|
|
5
|
+
Note: This is a personal fork of [will-work-for-meal/node-wreq](https://github.com/will-work-for-meal/node-wreq) (originally named node-wreq) with ongoing maintenance and faster dependency updates.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Native performance (no process spawning)
|
|
10
|
+
- TLS fingerprinting (JA3/JA4) aligned with real browsers
|
|
11
|
+
- HTTP/2 fingerprinting: SETTINGS, PRIORITY, and header ordering
|
|
12
|
+
- Multiple browser profiles (Chrome, Firefox, Safari, Edge, Opera, OkHttp)
|
|
13
|
+
- WebSocket support
|
|
14
|
+
- TypeScript definitions included
|
|
15
|
+
|
|
16
|
+
## How It Works
|
|
17
|
+
|
|
18
|
+
The library provides Node.js bindings over [wreq](https://github.com/0x676e67/wreq), a Rust HTTP client that uses BoringSSL to replicate browser network behavior at the TLS and HTTP/2 layers.
|
|
19
|
+
|
|
20
|
+
### Why It Works
|
|
21
|
+
|
|
22
|
+
Traditional HTTP clients (axios, fetch, curl) have differences in:
|
|
23
|
+
- **TLS handshake signatures** — Different cipher suites and extensions
|
|
24
|
+
- **HTTP/2 frame ordering** — Different SETTINGS and PRIORITY patterns
|
|
25
|
+
- **Header ordering** — Different sequence and values
|
|
26
|
+
|
|
27
|
+
This library reproduces browser network behavior with high fidelity.
|
|
28
|
+
|
|
29
|
+
### Browser Profiles and wreq-util
|
|
30
|
+
|
|
31
|
+
- Browser profiles are generally tracked in the upstream `wreq-util` project; we depend on it for compatibility and support.
|
|
32
|
+
- Profiles in this package are available in `src/generated-types.ts` and are automatically generated from the `wreq-util` codebase to improve update speed and reduce maintenance overhead.
|
|
33
|
+
- Use `getProfiles()` to query the current set of supported profiles programmatically.
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# From GitHub (this fork)
|
|
39
|
+
# Latest master branch
|
|
40
|
+
npm install wreq-js
|
|
41
|
+
yarn add wreq-js
|
|
42
|
+
pnpm add wreq-js
|
|
43
|
+
bun add wreq-js
|
|
44
|
+
|
|
45
|
+
# From npm registry (original repo as node-wreq)
|
|
46
|
+
npm install node-wreq
|
|
47
|
+
yarn add node-wreq
|
|
48
|
+
pnpm add node-wreq
|
|
49
|
+
bun add node-wreq
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Pre-built native modules are included for major platforms:
|
|
53
|
+
- macOS (Intel and Apple Silicon)
|
|
54
|
+
- Linux (x64 and ARM64)
|
|
55
|
+
- Windows (x64)
|
|
56
|
+
|
|
57
|
+
Note on GitHub installs: if a matching prebuilt binary is not available for the referenced tag/commit, installation may build from source. Ensure a Rust toolchain and platform build prerequisites are installed.
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
### Basic Request
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { request } from 'wreq-js';
|
|
65
|
+
|
|
66
|
+
const response = await request({
|
|
67
|
+
url: 'https://example.com/api',
|
|
68
|
+
browser: 'chrome_137',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log(response.status); // 200
|
|
72
|
+
console.log(response.body); // Response body
|
|
73
|
+
console.log(response.headers); // Response headers
|
|
74
|
+
console.log(response.cookies); // Cookies
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### With Custom Headers
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
import { request } from 'wreq-js';
|
|
81
|
+
|
|
82
|
+
const response = await request({
|
|
83
|
+
url: 'https://api.example.com/data',
|
|
84
|
+
browser: 'firefox_139',
|
|
85
|
+
headers: {
|
|
86
|
+
'Authorization': 'Bearer token123',
|
|
87
|
+
'Custom-Header': 'value',
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### POST Request
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { post } from 'wreq-js';
|
|
96
|
+
|
|
97
|
+
const response = await post(
|
|
98
|
+
'https://api.example.com/submit',
|
|
99
|
+
JSON.stringify({ foo: 'bar' }),
|
|
100
|
+
{
|
|
101
|
+
browser: 'chrome_137',
|
|
102
|
+
headers: {
|
|
103
|
+
'Content-Type': 'application/json',
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Convenience Methods
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
import { get, post } from 'wreq-js';
|
|
113
|
+
|
|
114
|
+
// GET request
|
|
115
|
+
const data = await get('https://api.example.com/users');
|
|
116
|
+
|
|
117
|
+
// POST request
|
|
118
|
+
const result = await post(
|
|
119
|
+
'https://api.example.com/users',
|
|
120
|
+
JSON.stringify({ name: 'John' })
|
|
121
|
+
);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### With Proxy
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { request } from 'wreq-js';
|
|
128
|
+
|
|
129
|
+
const response = await request({
|
|
130
|
+
url: 'https://example.com',
|
|
131
|
+
browser: 'chrome_137',
|
|
132
|
+
// proxy: 'http://proxy.example.com:8080',
|
|
133
|
+
// proxy: 'http://username:password@proxy.example.com:8080',
|
|
134
|
+
// proxy: 'socks5://proxy.example.com:1080',
|
|
135
|
+
});
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### WebSocket Connection
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { websocket } from 'wreq-js';
|
|
142
|
+
|
|
143
|
+
const ws = await websocket({
|
|
144
|
+
url: 'wss://echo.websocket.org',
|
|
145
|
+
browser: 'chrome_137',
|
|
146
|
+
onMessage: (data) => {
|
|
147
|
+
console.log('Received:', data);
|
|
148
|
+
},
|
|
149
|
+
onClose: () => {
|
|
150
|
+
console.log('Connection closed');
|
|
151
|
+
},
|
|
152
|
+
onError: (error) => {
|
|
153
|
+
console.error('Error:', error);
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Send text message
|
|
158
|
+
await ws.send('Hello!');
|
|
159
|
+
|
|
160
|
+
// Send binary message
|
|
161
|
+
await ws.send(Buffer.from([1, 2, 3]));
|
|
162
|
+
|
|
163
|
+
// Close connection
|
|
164
|
+
await ws.close();
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## API Reference
|
|
168
|
+
|
|
169
|
+
### `request(options:` [`RequestOptions`](#requestoptions)`): Promise<`[`Response`](#response)`>`
|
|
170
|
+
|
|
171
|
+
Main function for making HTTP requests with browser impersonation.
|
|
172
|
+
|
|
173
|
+
**Options:**
|
|
174
|
+
<a name="requestoptions"></a>
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
interface RequestOptions {
|
|
178
|
+
url: string; // Required: URL to request
|
|
179
|
+
browser?: BrowserProfile; // Default: 'chrome_137'
|
|
180
|
+
method?: HttpMethod; // Default: 'GET'
|
|
181
|
+
headers?: Record<string, string>;
|
|
182
|
+
body?: string;
|
|
183
|
+
proxy?: string; // HTTP/HTTPS/SOCKS5 proxy URL
|
|
184
|
+
timeout?: number; // Default: 30000ms
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Response:**
|
|
189
|
+
<a name="response"></a>
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
interface Response {
|
|
193
|
+
status: number;
|
|
194
|
+
headers: Record<string, string>;
|
|
195
|
+
body: string;
|
|
196
|
+
cookies: Record<string, string>;
|
|
197
|
+
url: string; // Final URL after redirects
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `get(url: string, options?): Promise<`[`Response`](#response)`>`
|
|
202
|
+
|
|
203
|
+
### `post(url: string, body?: string, options?): Promise<`[`Response`](#response)`>`
|
|
204
|
+
|
|
205
|
+
### `websocket(options:` [`WebSocketOptions`](#websocketoptions)`): Promise<WebSocket>`
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
**Options:**
|
|
209
|
+
<a name="websocketoptions"></a>
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
interface WebSocketOptions {
|
|
213
|
+
url: string; // Required: WebSocket URL (ws:// or wss://)
|
|
214
|
+
browser?: BrowserProfile; // Default: 'chrome_137'
|
|
215
|
+
headers?: Record<string, string>;
|
|
216
|
+
proxy?: string; // HTTP/HTTPS/SOCKS5 proxy URL
|
|
217
|
+
onMessage: (data: string | Buffer) => void; // Required: Message callback
|
|
218
|
+
onClose?: () => void; // Optional: Close callback
|
|
219
|
+
onError?: (error: string) => void; // Optional: Error callback
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**WebSocket Methods:**
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
class WebSocket {
|
|
227
|
+
send(data: string | Buffer): Promise<void>;
|
|
228
|
+
close(): Promise<void>;
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### `getProfiles():` [`BrowserProfile[]`](#browser-profiles)
|
|
233
|
+
|
|
234
|
+
Get list of available browser profiles.
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
import { getProfiles } from 'wreq-js';
|
|
238
|
+
|
|
239
|
+
const profiles = getProfiles();
|
|
240
|
+
|
|
241
|
+
console.log(profiles);
|
|
242
|
+
// ['chrome_100', 'chrome_101', ..., 'chrome_137', 'edge_101', ..., 'safari_18', ...]
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Documentation
|
|
246
|
+
|
|
247
|
+
- **[Architecture Guide](docs/ARCHITECTURE.md)** — Technical details about TLS/HTTP2 fingerprinting, how browser impersonation works
|
|
248
|
+
- **[Build Instructions](docs/BUILD.md)** — Developer guide for building from source
|
|
249
|
+
- **[Publishing Guide](docs/PUBLISHING.md)** — How to publish the package
|
|
250
|
+
|
|
251
|
+
## Contributing
|
|
252
|
+
|
|
253
|
+
Please read the [Contributing Guide](CONTRIBUTING.md).
|
|
254
|
+
|
|
255
|
+
## Acknowledgments
|
|
256
|
+
|
|
257
|
+
- [wreq](https://github.com/0x676e67/wreq) — Rust HTTP client with browser impersonation
|
|
258
|
+
- [wreq-util](https://github.com/0x676e67/wreq-util) — Upstream utility project that tracks and ships browser fingerprint updates rapidly
|
|
259
|
+
- [Neon](https://neon-bindings.com/) — Rust ↔ Node.js bindings
|
|
260
|
+
- Original Node.js wrapper: [will-work-for-meal/node-wreq](https://github.com/will-work-for-meal/node-wreq) (named node-wreq) — clean, well-written baseline this fork builds on
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generated from Rust build script
|
|
3
|
+
* DO NOT EDIT MANUALLY
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Browser profile names supported
|
|
7
|
+
*/
|
|
8
|
+
export type BrowserProfile = 'chrome_100' | 'chrome_101' | 'chrome_104' | 'chrome_105' | 'chrome_106' | 'chrome_107' | 'chrome_108' | 'chrome_109' | 'chrome_110' | 'chrome_114' | 'chrome_116' | 'chrome_117' | 'chrome_118' | 'chrome_119' | 'chrome_120' | 'chrome_123' | 'chrome_124' | 'chrome_126' | 'chrome_127' | 'chrome_128' | 'chrome_129' | 'chrome_130' | 'chrome_131' | 'chrome_132' | 'chrome_133' | 'chrome_134' | 'chrome_135' | 'chrome_136' | 'chrome_137' | 'chrome_138' | 'chrome_139' | 'chrome_140' | 'chrome_141' | 'chrome_142' | 'edge_101' | 'edge_122' | 'edge_127' | 'edge_131' | 'edge_134' | 'opera_116' | 'opera_117' | 'opera_118' | 'opera_119' | 'safari_ios_17.2' | 'safari_ios_17.4.1' | 'safari_ios_16.5' | 'safari_15.3' | 'safari_15.5' | 'safari_15.6.1' | 'safari_16' | 'safari_16.5' | 'safari_17.0' | 'safari_17.2.1' | 'safari_17.4.1' | 'safari_17.5' | 'safari_18' | 'safari_ipad_18' | 'safari_18.2' | 'safari_ios_18.1.1' | 'safari_18.3' | 'safari_18.3.1' | 'safari_18.5' | 'safari_26' | 'safari_ipad_26' | 'safari_ios_26' | 'firefox_109' | 'firefox_117' | 'firefox_128' | 'firefox_133' | 'firefox_135' | 'firefox_private_135' | 'firefox_android_135' | 'firefox_136' | 'firefox_private_136' | 'firefox_139' | 'firefox_142' | 'firefox_143' | 'okhttp_3.9' | 'okhttp_3.11' | 'okhttp_3.13' | 'okhttp_3.14' | 'okhttp_4.9' | 'okhttp_4.10' | 'okhttp_4.12' | 'okhttp_5';
|
|
9
|
+
//# sourceMappingURL=generated-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generated-types.d.ts","sourceRoot":"","sources":["../src/generated-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,GACV,UAAU,GACV,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,iBAAiB,GACjB,mBAAmB,GACnB,iBAAiB,GACjB,aAAa,GACb,aAAa,GACb,eAAe,GACf,WAAW,GACX,aAAa,GACb,aAAa,GACb,eAAe,GACf,eAAe,GACf,aAAa,GACb,WAAW,GACX,gBAAgB,GAChB,aAAa,GACb,mBAAmB,GACnB,aAAa,GACb,eAAe,GACf,aAAa,GACb,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,aAAa,GACb,aAAa,GACb,aAAa,GACb,aAAa,GACb,aAAa,GACb,qBAAqB,GACrB,qBAAqB,GACrB,aAAa,GACb,qBAAqB,GACrB,aAAa,GACb,aAAa,GACb,aAAa,GACb,YAAY,GACZ,aAAa,GACb,aAAa,GACb,aAAa,GACb,YAAY,GACZ,aAAa,GACb,aAAa,GACb,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generated-types.js","sourceRoot":"","sources":["../src/generated-types.ts"],"names":[],"mappings":";AAAA;;;GAGG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.spec.d.ts","sourceRoot":"","sources":["../../src/test/http.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
|
+
const wreq_js_1 = require("../wreq-js");
|
|
9
|
+
(0, node_test_1.describe)('HTTP', () => {
|
|
10
|
+
(0, node_test_1.before)(() => {
|
|
11
|
+
console.log('🔌 HTTP Test Suite\n');
|
|
12
|
+
});
|
|
13
|
+
(0, node_test_1.test)('should return available browser profiles', () => {
|
|
14
|
+
const profiles = (0, wreq_js_1.getProfiles)();
|
|
15
|
+
node_assert_1.default.ok(Array.isArray(profiles), 'Profiles should be an array');
|
|
16
|
+
node_assert_1.default.ok(profiles.length > 0, 'Should have at least one profile');
|
|
17
|
+
node_assert_1.default.ok(profiles.some((p) => p.includes('chrome')) ||
|
|
18
|
+
profiles.some((p) => p.includes('firefox')) ||
|
|
19
|
+
profiles.some((p) => p.includes('safari')), 'Should include standard browser profiles');
|
|
20
|
+
console.log('Available profiles:', profiles.join(', '));
|
|
21
|
+
});
|
|
22
|
+
(0, node_test_1.test)('should make a simple GET request', async () => {
|
|
23
|
+
const response = await (0, wreq_js_1.request)({
|
|
24
|
+
url: 'https://httpbingo.org/get',
|
|
25
|
+
browser: 'chrome_131',
|
|
26
|
+
timeout: 10000,
|
|
27
|
+
});
|
|
28
|
+
node_assert_1.default.ok(response.status >= 200 && response.status < 300, 'Should return successful status');
|
|
29
|
+
node_assert_1.default.ok(Object.keys(response.headers).length > 0, 'Should have response headers');
|
|
30
|
+
node_assert_1.default.ok(response.body.length > 0, 'Should have response body');
|
|
31
|
+
const body = JSON.parse(response.body);
|
|
32
|
+
node_assert_1.default.ok(body.headers['User-Agent'], 'Should have User-Agent header');
|
|
33
|
+
console.log('Status:', response.status);
|
|
34
|
+
console.log('User-Agent:', body.headers['User-Agent']);
|
|
35
|
+
});
|
|
36
|
+
(0, node_test_1.test)('should work with different browser profiles', async () => {
|
|
37
|
+
const testUrl = 'https://httpbingo.org/user-agent';
|
|
38
|
+
const browsers = ['chrome_137', 'firefox_139', 'safari_18'];
|
|
39
|
+
for (const browser of browsers) {
|
|
40
|
+
const response = await (0, wreq_js_1.request)({
|
|
41
|
+
url: testUrl,
|
|
42
|
+
browser: browser,
|
|
43
|
+
timeout: 10000,
|
|
44
|
+
});
|
|
45
|
+
node_assert_1.default.ok(response.status === 200, `${browser} should return status 200`);
|
|
46
|
+
const data = JSON.parse(response.body);
|
|
47
|
+
node_assert_1.default.ok(data['user-agent'], `${browser} should have user-agent`);
|
|
48
|
+
console.log(`${browser}:`, data['user-agent'].substring(0, 70) + '...');
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
(0, node_test_1.test)('should handle timeout errors', async () => {
|
|
52
|
+
await node_assert_1.default.rejects(async () => {
|
|
53
|
+
await (0, wreq_js_1.request)({
|
|
54
|
+
url: 'https://httpbingo.org/delay/10',
|
|
55
|
+
browser: 'chrome_137',
|
|
56
|
+
timeout: 1000, // 1 second timeout for 10 second delay
|
|
57
|
+
});
|
|
58
|
+
}, {
|
|
59
|
+
name: 'RequestError',
|
|
60
|
+
}, 'Should throw an error on timeout');
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=http.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.spec.js","sourceRoot":"","sources":["../../src/test/http.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.spec.d.ts","sourceRoot":"","sources":["../../src/test/websocket.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
|
+
const promises_1 = require("node:timers/promises");
|
|
9
|
+
const wreq_js_1 = require("../wreq-js");
|
|
10
|
+
(0, node_test_1.describe)('WebSocket', () => {
|
|
11
|
+
(0, node_test_1.before)(() => {
|
|
12
|
+
console.log('🔌 WebSocket Test Suite\n');
|
|
13
|
+
});
|
|
14
|
+
(0, node_test_1.test)('should connect to WebSocket and send/receive messages', async () => {
|
|
15
|
+
const messages = [];
|
|
16
|
+
let isClosed = false;
|
|
17
|
+
const ws = await (0, wreq_js_1.websocket)({
|
|
18
|
+
url: 'wss://echo.websocket.org',
|
|
19
|
+
browser: 'chrome_137',
|
|
20
|
+
onMessage: (data) => {
|
|
21
|
+
messages.push(data);
|
|
22
|
+
},
|
|
23
|
+
onClose: () => {
|
|
24
|
+
isClosed = true;
|
|
25
|
+
},
|
|
26
|
+
onError: (error) => {
|
|
27
|
+
console.error('WebSocket error:', error);
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
console.log('WebSocket connected');
|
|
31
|
+
await ws.send('Hello!');
|
|
32
|
+
// Wait for echo response
|
|
33
|
+
await (0, promises_1.setTimeout)(1000);
|
|
34
|
+
node_assert_1.default.ok(messages.length > 0, 'Should receive at least one message');
|
|
35
|
+
// Wait a bit for close callback
|
|
36
|
+
await ws.close();
|
|
37
|
+
await (0, promises_1.setTimeout)(5000);
|
|
38
|
+
node_assert_1.default.ok(isClosed, 'Should receive close event');
|
|
39
|
+
// Rate limit protection: wait before next test
|
|
40
|
+
await (0, promises_1.setTimeout)(2000);
|
|
41
|
+
});
|
|
42
|
+
(0, node_test_1.test)('should handle parallel sends on same WebSocket', async () => {
|
|
43
|
+
const messages = [];
|
|
44
|
+
const expectedMessages = ['Message 1', 'Message 2', 'Message 3', 'Message 4', 'Message 5'];
|
|
45
|
+
const ws = await (0, wreq_js_1.websocket)({
|
|
46
|
+
url: 'wss://echo.websocket.org',
|
|
47
|
+
browser: 'chrome_137',
|
|
48
|
+
onMessage: (data) => {
|
|
49
|
+
messages.push(data);
|
|
50
|
+
},
|
|
51
|
+
onClose: () => { },
|
|
52
|
+
onError: (error) => {
|
|
53
|
+
console.error('WebSocket error:', error);
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
console.log('Testing parallel sends...');
|
|
57
|
+
// Send multiple messages in parallel
|
|
58
|
+
await Promise.all([
|
|
59
|
+
ws.send('Message 1'),
|
|
60
|
+
ws.send('Message 2'),
|
|
61
|
+
ws.send('Message 3'),
|
|
62
|
+
ws.send('Message 4'),
|
|
63
|
+
ws.send('Message 5'),
|
|
64
|
+
]);
|
|
65
|
+
console.log('All messages sent in parallel');
|
|
66
|
+
// Wait for echo responses
|
|
67
|
+
await (0, promises_1.setTimeout)(2000);
|
|
68
|
+
node_assert_1.default.ok(messages.length >= 5, 'Should receive at least 5 messages');
|
|
69
|
+
// Verify that all expected messages were received (order may vary)
|
|
70
|
+
const receivedStrings = messages.map((m) => (Buffer.isBuffer(m) ? m.toString() : m));
|
|
71
|
+
for (const expected of expectedMessages) {
|
|
72
|
+
node_assert_1.default.ok(receivedStrings.includes(expected), `Should receive message: "${expected}". Got: ${receivedStrings.join(', ')}`);
|
|
73
|
+
}
|
|
74
|
+
console.log('All messages received correctly:', receivedStrings.join(', '));
|
|
75
|
+
await ws.close();
|
|
76
|
+
// Rate limit protection: wait before next test
|
|
77
|
+
await (0, promises_1.setTimeout)(2000);
|
|
78
|
+
});
|
|
79
|
+
(0, node_test_1.test)('should handle multiple WebSocket connections simultaneously', async () => {
|
|
80
|
+
const ws1Messages = [];
|
|
81
|
+
const ws2Messages = [];
|
|
82
|
+
// Create two WebSocket connections in parallel
|
|
83
|
+
const [ws1, ws2] = await Promise.all([
|
|
84
|
+
(0, wreq_js_1.websocket)({
|
|
85
|
+
url: 'wss://echo.websocket.org',
|
|
86
|
+
browser: 'chrome_137',
|
|
87
|
+
onMessage: (data) => ws1Messages.push(data),
|
|
88
|
+
onClose: () => { },
|
|
89
|
+
onError: () => { },
|
|
90
|
+
}),
|
|
91
|
+
(0, wreq_js_1.websocket)({
|
|
92
|
+
url: 'wss://echo.websocket.org',
|
|
93
|
+
browser: 'firefox_139',
|
|
94
|
+
onMessage: (data) => ws2Messages.push(data),
|
|
95
|
+
onClose: () => { },
|
|
96
|
+
onError: () => { },
|
|
97
|
+
}),
|
|
98
|
+
]);
|
|
99
|
+
console.log('WebSocket connections created');
|
|
100
|
+
// Send unique messages on both connections in parallel
|
|
101
|
+
await Promise.all([ws1.send('From WS1'), ws2.send('From WS2')]);
|
|
102
|
+
// Wait for responses
|
|
103
|
+
await (0, promises_1.setTimeout)(1500);
|
|
104
|
+
node_assert_1.default.ok(ws1Messages.length > 0, 'WS1 should receive messages');
|
|
105
|
+
node_assert_1.default.ok(ws2Messages.length > 0, 'WS2 should receive messages');
|
|
106
|
+
// Verify that each connection received the correct message (not mixed up)
|
|
107
|
+
// Note: echo.websocket.org sends a "Request served by..." message first, then echoes
|
|
108
|
+
const ws1Strings = ws1Messages.map((m) => (Buffer.isBuffer(m) ? m.toString() : m));
|
|
109
|
+
const ws2Strings = ws2Messages.map((m) => (Buffer.isBuffer(m) ? m.toString() : m));
|
|
110
|
+
node_assert_1.default.ok(ws1Strings.includes('From WS1'), 'WS1 should receive its own message');
|
|
111
|
+
node_assert_1.default.ok(ws2Strings.includes('From WS2'), 'WS2 should receive its own message');
|
|
112
|
+
// Verify messages are not mixed up between connections
|
|
113
|
+
node_assert_1.default.ok(!ws1Strings.includes('From WS2'), 'WS1 should NOT receive WS2 message');
|
|
114
|
+
node_assert_1.default.ok(!ws2Strings.includes('From WS1'), 'WS2 should NOT receive WS1 message');
|
|
115
|
+
console.log('Messages correctly isolated between connections:');
|
|
116
|
+
console.log(' WS1:', ws1Strings);
|
|
117
|
+
console.log(' WS2:', ws2Strings);
|
|
118
|
+
// Close both connections
|
|
119
|
+
await Promise.all([ws1.close(), ws2.close()]);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=websocket.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.spec.js","sourceRoot":"","sources":["../../src/test/websocket.spec.ts"],"names":[],"mappings":";;;;;AAAA,yCAAmD;AACnD,8DAAiC;AACjC,mDAA2D;AAC3D,wCAAuC;AAEvC,IAAA,oBAAQ,EAAC,WAAW,EAAE,GAAG,EAAE;IACzB,IAAA,kBAAM,EAAC,GAAG,EAAE;QACV,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAA,gBAAI,EAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,EAAE,GAAG,MAAM,IAAA,mBAAS,EAAC;YACzB,GAAG,EAAE,0BAA0B;YAC/B,OAAO,EAAE,YAAY;YACrB,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;gBAClB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;YACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAEnC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAExB,yBAAyB;QACzB,MAAM,IAAA,qBAAK,EAAC,IAAI,CAAC,CAAC;QAClB,qBAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,qCAAqC,CAAC,CAAC;QAEtE,gCAAgC;QAChC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,IAAA,qBAAK,EAAC,IAAI,CAAC,CAAC;QAClB,qBAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAC;QAElD,+CAA+C;QAC/C,MAAM,IAAA,qBAAK,EAAC,IAAI,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,IAAA,gBAAI,EAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,QAAQ,GAAwB,EAAE,CAAC;QACzC,MAAM,gBAAgB,GAAG,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC;QAE3F,MAAM,EAAE,GAAG,MAAM,IAAA,mBAAS,EAAC;YACzB,GAAG,EAAE,0BAA0B;YAC/B,OAAO,EAAE,YAAY;YACrB,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE;gBAClB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,CAAC;YACD,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;YACjB,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;gBACjB,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;YAC3C,CAAC;SACF,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QAEzC,qCAAqC;QACrC,MAAM,OAAO,CAAC,GAAG,CAAC;YAChB,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;YACpB,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;YACpB,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;YACpB,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;YACpB,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC;SACrB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAE7C,0BAA0B;QAC1B,MAAM,IAAA,qBAAK,EAAC,IAAI,CAAC,CAAC;QAElB,qBAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,EAAE,oCAAoC,CAAC,CAAC;QAEtE,mEAAmE;QACnE,MAAM,eAAe,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAErF,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;YACxC,qBAAM,CAAC,EAAE,CACP,eAAe,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAClC,4BAA4B,QAAQ,WAAW,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC5E,CAAC;QACJ,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAE5E,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QAEjB,+CAA+C;QAC/C,MAAM,IAAA,qBAAK,EAAC,IAAI,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,IAAA,gBAAI,EAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC7E,MAAM,WAAW,GAAwB,EAAE,CAAC;QAC5C,MAAM,WAAW,GAAwB,EAAE,CAAC;QAE5C,+CAA+C;QAC/C,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACnC,IAAA,mBAAS,EAAC;gBACR,GAAG,EAAE,0BAA0B;gBAC/B,OAAO,EAAE,YAAY;gBACrB,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3C,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;gBACjB,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;aAClB,CAAC;YACF,IAAA,mBAAS,EAAC;gBACR,GAAG,EAAE,0BAA0B;gBAC/B,OAAO,EAAE,aAAa;gBACtB,SAAS,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3C,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;gBACjB,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;aAClB,CAAC;SACH,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAE7C,uDAAuD;QACvD,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAEhE,qBAAqB;QACrB,MAAM,IAAA,qBAAK,EAAC,IAAI,CAAC,CAAC;QAElB,qBAAM,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,6BAA6B,CAAC,CAAC;QACjE,qBAAM,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,6BAA6B,CAAC,CAAC;QAEjE,0EAA0E;QAC1E,qFAAqF;QACrF,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACnF,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEnF,qBAAM,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,oCAAoC,CAAC,CAAC;QACjF,qBAAM,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,oCAAoC,CAAC,CAAC;QAEjF,uDAAuD;QACvD,qBAAM,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,oCAAoC,CAAC,CAAC;QAClF,qBAAM,CAAC,EAAE,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,oCAAoC,CAAC,CAAC;QAElF,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAElC,yBAAyB;QACzB,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { BrowserProfile } from './generated-types';
|
|
2
|
+
export type { BrowserProfile };
|
|
3
|
+
/**
|
|
4
|
+
* HTTP method types
|
|
5
|
+
*/
|
|
6
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD';
|
|
7
|
+
/**
|
|
8
|
+
* Request options for making HTTP requests with browser impersonation
|
|
9
|
+
*/
|
|
10
|
+
export interface RequestOptions {
|
|
11
|
+
/**
|
|
12
|
+
* The URL to request
|
|
13
|
+
*/
|
|
14
|
+
url: string;
|
|
15
|
+
/**
|
|
16
|
+
* Browser profile to impersonate
|
|
17
|
+
* @default 'chrome_137'
|
|
18
|
+
*/
|
|
19
|
+
browser?: BrowserProfile;
|
|
20
|
+
/**
|
|
21
|
+
* HTTP method
|
|
22
|
+
* @default 'GET'
|
|
23
|
+
*/
|
|
24
|
+
method?: HttpMethod;
|
|
25
|
+
/**
|
|
26
|
+
* Additional headers to send with the request
|
|
27
|
+
* Browser-specific headers will be automatically added
|
|
28
|
+
*/
|
|
29
|
+
headers?: Record<string, string>;
|
|
30
|
+
/**
|
|
31
|
+
* Request body (for POST, PUT, PATCH requests)
|
|
32
|
+
*/
|
|
33
|
+
body?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Proxy URL (e.g., 'http://proxy.example.com:8080')
|
|
36
|
+
*/
|
|
37
|
+
proxy?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Request timeout in milliseconds
|
|
40
|
+
* @default 30000
|
|
41
|
+
*/
|
|
42
|
+
timeout?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Response object returned from HTTP requests
|
|
46
|
+
*/
|
|
47
|
+
export interface Response {
|
|
48
|
+
/**
|
|
49
|
+
* HTTP status code
|
|
50
|
+
*/
|
|
51
|
+
status: number;
|
|
52
|
+
/**
|
|
53
|
+
* Response headers
|
|
54
|
+
*/
|
|
55
|
+
headers: Record<string, string>;
|
|
56
|
+
/**
|
|
57
|
+
* Response body as string
|
|
58
|
+
*/
|
|
59
|
+
body: string;
|
|
60
|
+
/**
|
|
61
|
+
* Cookies set by the server
|
|
62
|
+
*/
|
|
63
|
+
cookies: Record<string, string>;
|
|
64
|
+
/**
|
|
65
|
+
* Final URL after redirects
|
|
66
|
+
*/
|
|
67
|
+
url: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* WebSocket options for creating a connection
|
|
71
|
+
*/
|
|
72
|
+
export interface WebSocketOptions {
|
|
73
|
+
/**
|
|
74
|
+
* The WebSocket URL to connect to (wss:// or ws://)
|
|
75
|
+
*/
|
|
76
|
+
url: string;
|
|
77
|
+
/**
|
|
78
|
+
* Browser profile to impersonate
|
|
79
|
+
* @default 'chrome_137'
|
|
80
|
+
*/
|
|
81
|
+
browser?: BrowserProfile;
|
|
82
|
+
/**
|
|
83
|
+
* Additional headers to send with the WebSocket upgrade request
|
|
84
|
+
*/
|
|
85
|
+
headers?: Record<string, string>;
|
|
86
|
+
/**
|
|
87
|
+
* Proxy URL (e.g., 'http://proxy.example.com:8080')
|
|
88
|
+
*/
|
|
89
|
+
proxy?: string;
|
|
90
|
+
/**
|
|
91
|
+
* Callback for incoming messages (required)
|
|
92
|
+
*/
|
|
93
|
+
onMessage: (data: string | Buffer) => void;
|
|
94
|
+
/**
|
|
95
|
+
* Callback for connection close event
|
|
96
|
+
*/
|
|
97
|
+
onClose?: () => void;
|
|
98
|
+
/**
|
|
99
|
+
* Callback for error events
|
|
100
|
+
*/
|
|
101
|
+
onError?: (error: string) => void;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Internal WebSocket connection object returned from native binding
|
|
105
|
+
*/
|
|
106
|
+
export interface NativeWebSocketConnection {
|
|
107
|
+
_id: number;
|
|
108
|
+
}
|
|
109
|
+
export declare class RequestError extends Error {
|
|
110
|
+
constructor(message: string);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9E;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IAEzB;;;OAGG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEhC;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;;OAGG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IAEzB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,qBAAa,YAAa,SAAQ,KAAK;gBACzB,OAAO,EAAE,MAAM;CAI5B"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RequestError = void 0;
|
|
4
|
+
class RequestError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'RequestError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.RequestError = RequestError;
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAmIA,MAAa,YAAa,SAAQ,KAAK;IACrC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AALD,oCAKC"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { RequestOptions, Response, BrowserProfile, WebSocketOptions, NativeWebSocketConnection } from './types';
|
|
2
|
+
import { RequestError } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Make an HTTP request with browser impersonation
|
|
5
|
+
*
|
|
6
|
+
* @param options - Request options
|
|
7
|
+
* @returns Promise that resolves to the response
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { request } from 'wreq-js';
|
|
12
|
+
*
|
|
13
|
+
* const response = await request({
|
|
14
|
+
* url: 'https://example.com/api',
|
|
15
|
+
* browser: 'chrome_137',
|
|
16
|
+
* headers: {
|
|
17
|
+
* 'Custom-Header': 'value'
|
|
18
|
+
* }
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* console.log(response.status); // 200
|
|
22
|
+
* console.log(response.body); // Response body
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function request(options: RequestOptions): Promise<Response>;
|
|
26
|
+
/**
|
|
27
|
+
* Get list of available browser profiles
|
|
28
|
+
*
|
|
29
|
+
* @returns Array of browser profile names
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { getProfiles } from 'wreq-js';
|
|
34
|
+
*
|
|
35
|
+
* const profiles = getProfiles();
|
|
36
|
+
* console.log(profiles); // ['chrome_120', 'chrome_131', 'firefox', ...]
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function getProfiles(): BrowserProfile[];
|
|
40
|
+
/**
|
|
41
|
+
* Convenience function for GET requests
|
|
42
|
+
*
|
|
43
|
+
* @param url - URL to request
|
|
44
|
+
* @param options - Additional request options
|
|
45
|
+
* @returns Promise that resolves to the response
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* import { get } from 'wreq-js';
|
|
50
|
+
*
|
|
51
|
+
* const response = await get('https://example.com/api');
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function get(url: string, options?: Omit<RequestOptions, 'url' | 'method'>): Promise<Response>;
|
|
55
|
+
/**
|
|
56
|
+
* Convenience function for POST requests
|
|
57
|
+
*
|
|
58
|
+
* @param url - URL to request
|
|
59
|
+
* @param body - Request body
|
|
60
|
+
* @param options - Additional request options
|
|
61
|
+
* @returns Promise that resolves to the response
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* import { post } from 'wreq-js';
|
|
66
|
+
*
|
|
67
|
+
* const response = await post(
|
|
68
|
+
* 'https://example.com/api',
|
|
69
|
+
* JSON.stringify({ foo: 'bar' }),
|
|
70
|
+
* { headers: { 'Content-Type': 'application/json' } }
|
|
71
|
+
* );
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare function post(url: string, body?: string, options?: Omit<RequestOptions, 'url' | 'method' | 'body'>): Promise<Response>;
|
|
75
|
+
/**
|
|
76
|
+
* WebSocket connection class
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { websocket } from 'wreq-js';
|
|
81
|
+
*
|
|
82
|
+
* const ws = await websocket({
|
|
83
|
+
* url: 'wss://echo.websocket.org',
|
|
84
|
+
* browser: 'chrome_137',
|
|
85
|
+
* onMessage: (data) => {
|
|
86
|
+
* console.log('Received:', data);
|
|
87
|
+
* },
|
|
88
|
+
* onClose: () => {
|
|
89
|
+
* console.log('Connection closed');
|
|
90
|
+
* },
|
|
91
|
+
* onError: (error) => {
|
|
92
|
+
* console.error('Error:', error);
|
|
93
|
+
* }
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
* // Send text message
|
|
97
|
+
* await ws.send('Hello World');
|
|
98
|
+
*
|
|
99
|
+
* // Send binary message
|
|
100
|
+
* await ws.send(Buffer.from([1, 2, 3]));
|
|
101
|
+
*
|
|
102
|
+
* // Close connection
|
|
103
|
+
* await ws.close();
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export declare class WebSocket {
|
|
107
|
+
private _connection;
|
|
108
|
+
constructor(connection: NativeWebSocketConnection);
|
|
109
|
+
/**
|
|
110
|
+
* Send a message (text or binary)
|
|
111
|
+
*/
|
|
112
|
+
send(data: string | Buffer): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Close the WebSocket connection
|
|
115
|
+
*/
|
|
116
|
+
close(): Promise<void>;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Create a WebSocket connection with browser impersonation
|
|
120
|
+
*
|
|
121
|
+
* @param options - WebSocket options
|
|
122
|
+
* @returns Promise that resolves to the WebSocket instance
|
|
123
|
+
*/
|
|
124
|
+
export declare function websocket(options: WebSocketOptions): Promise<WebSocket>;
|
|
125
|
+
export type { RequestOptions, Response, BrowserProfile, HttpMethod, WebSocketOptions, } from './types';
|
|
126
|
+
export type { RequestError };
|
|
127
|
+
declare const _default: {
|
|
128
|
+
request: typeof request;
|
|
129
|
+
get: typeof get;
|
|
130
|
+
post: typeof post;
|
|
131
|
+
getProfiles: typeof getProfiles;
|
|
132
|
+
websocket: typeof websocket;
|
|
133
|
+
WebSocket: typeof WebSocket;
|
|
134
|
+
};
|
|
135
|
+
export default _default;
|
|
136
|
+
//# sourceMappingURL=wreq-js.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wreq-js.d.ts","sourceRoot":"","sources":["../src/wreq-js.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA0EvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoBxE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,IAAI,cAAc,EAAE,CAE9C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,GAAG,CACvB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,QAAQ,CAAC,GAC/C,OAAO,CAAC,QAAQ,CAAC,CAEnB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,IAAI,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,IAAI,CAAC,cAAc,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,GACxD,OAAO,CAAC,QAAQ,CAAC,CAEnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,WAAW,CAA4B;gBAEnC,UAAU,EAAE,yBAAyB;IAIjD;;OAEG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQhD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,SAAS,CAAC,CAkC7E;AAED,YAAY,EACV,cAAc,EACd,QAAQ,EACR,cAAc,EACd,UAAU,EACV,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAEjB,YAAY,EAAE,YAAY,EAAE,CAAC;;;;;;;;;AAE7B,wBAOE"}
|
package/dist/wreq-js.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocket = void 0;
|
|
4
|
+
exports.request = request;
|
|
5
|
+
exports.getProfiles = getProfiles;
|
|
6
|
+
exports.get = get;
|
|
7
|
+
exports.post = post;
|
|
8
|
+
exports.websocket = websocket;
|
|
9
|
+
const types_1 = require("./types");
|
|
10
|
+
let nativeBinding;
|
|
11
|
+
function loadNativeBinding() {
|
|
12
|
+
const platform = process.platform;
|
|
13
|
+
const arch = process.arch;
|
|
14
|
+
// Map Node.js platform/arch to Rust target triple suffixes
|
|
15
|
+
// napi-rs creates files like: wreq-js.linux-x64-gnu.node
|
|
16
|
+
const platformArchMap = {
|
|
17
|
+
darwin: {
|
|
18
|
+
x64: 'darwin-x64',
|
|
19
|
+
arm64: 'darwin-arm64',
|
|
20
|
+
},
|
|
21
|
+
linux: {
|
|
22
|
+
x64: 'linux-x64-gnu',
|
|
23
|
+
arm64: 'linux-arm64-gnu',
|
|
24
|
+
},
|
|
25
|
+
win32: {
|
|
26
|
+
x64: 'win32-x64-msvc',
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const platformArch = platformArchMap[platform]?.[arch];
|
|
30
|
+
if (!platformArch) {
|
|
31
|
+
throw new Error(`Unsupported platform: ${platform}-${arch}. ` +
|
|
32
|
+
`Supported platforms: darwin-x64, darwin-arm64, linux-x64, linux-arm64, win32-x64`);
|
|
33
|
+
}
|
|
34
|
+
// Try to load platform-specific binary
|
|
35
|
+
const binaryName = `wreq-js.${platformArch}.node`;
|
|
36
|
+
try {
|
|
37
|
+
return require(`../rust/${binaryName}`);
|
|
38
|
+
}
|
|
39
|
+
catch (e1) {
|
|
40
|
+
// Fallback to wreq-js.node (for local development)
|
|
41
|
+
try {
|
|
42
|
+
return require('../rust/wreq-js.node');
|
|
43
|
+
}
|
|
44
|
+
catch (e2) {
|
|
45
|
+
throw new Error(`Failed to load native module for ${platform}-${arch}. ` +
|
|
46
|
+
`Tried: ../rust/${binaryName} and ../rust/wreq-js.node. ` +
|
|
47
|
+
`Make sure the package is installed correctly and the native module is built for your platform.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
nativeBinding = loadNativeBinding();
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Make an HTTP request with browser impersonation
|
|
59
|
+
*
|
|
60
|
+
* @param options - Request options
|
|
61
|
+
* @returns Promise that resolves to the response
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* import { request } from 'wreq-js';
|
|
66
|
+
*
|
|
67
|
+
* const response = await request({
|
|
68
|
+
* url: 'https://example.com/api',
|
|
69
|
+
* browser: 'chrome_137',
|
|
70
|
+
* headers: {
|
|
71
|
+
* 'Custom-Header': 'value'
|
|
72
|
+
* }
|
|
73
|
+
* });
|
|
74
|
+
*
|
|
75
|
+
* console.log(response.status); // 200
|
|
76
|
+
* console.log(response.body); // Response body
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
async function request(options) {
|
|
80
|
+
if (!options.url) {
|
|
81
|
+
throw new types_1.RequestError('URL is required');
|
|
82
|
+
}
|
|
83
|
+
if (options.browser) {
|
|
84
|
+
const profiles = getProfiles();
|
|
85
|
+
if (!profiles.includes(options.browser)) {
|
|
86
|
+
throw new types_1.RequestError(`Invalid browser profile: ${options.browser}. Available profiles: ${profiles.join(', ')}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
return await nativeBinding.request(options);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
throw new types_1.RequestError(String(error));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get list of available browser profiles
|
|
98
|
+
*
|
|
99
|
+
* @returns Array of browser profile names
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* import { getProfiles } from 'wreq-js';
|
|
104
|
+
*
|
|
105
|
+
* const profiles = getProfiles();
|
|
106
|
+
* console.log(profiles); // ['chrome_120', 'chrome_131', 'firefox', ...]
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
function getProfiles() {
|
|
110
|
+
return nativeBinding.getProfiles();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Convenience function for GET requests
|
|
114
|
+
*
|
|
115
|
+
* @param url - URL to request
|
|
116
|
+
* @param options - Additional request options
|
|
117
|
+
* @returns Promise that resolves to the response
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* import { get } from 'wreq-js';
|
|
122
|
+
*
|
|
123
|
+
* const response = await get('https://example.com/api');
|
|
124
|
+
* ```
|
|
125
|
+
*/
|
|
126
|
+
async function get(url, options) {
|
|
127
|
+
return request({ ...options, url, method: 'GET' });
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Convenience function for POST requests
|
|
131
|
+
*
|
|
132
|
+
* @param url - URL to request
|
|
133
|
+
* @param body - Request body
|
|
134
|
+
* @param options - Additional request options
|
|
135
|
+
* @returns Promise that resolves to the response
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* import { post } from 'wreq-js';
|
|
140
|
+
*
|
|
141
|
+
* const response = await post(
|
|
142
|
+
* 'https://example.com/api',
|
|
143
|
+
* JSON.stringify({ foo: 'bar' }),
|
|
144
|
+
* { headers: { 'Content-Type': 'application/json' } }
|
|
145
|
+
* );
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
async function post(url, body, options) {
|
|
149
|
+
return request({ ...options, url, method: 'POST', body });
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* WebSocket connection class
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```typescript
|
|
156
|
+
* import { websocket } from 'wreq-js';
|
|
157
|
+
*
|
|
158
|
+
* const ws = await websocket({
|
|
159
|
+
* url: 'wss://echo.websocket.org',
|
|
160
|
+
* browser: 'chrome_137',
|
|
161
|
+
* onMessage: (data) => {
|
|
162
|
+
* console.log('Received:', data);
|
|
163
|
+
* },
|
|
164
|
+
* onClose: () => {
|
|
165
|
+
* console.log('Connection closed');
|
|
166
|
+
* },
|
|
167
|
+
* onError: (error) => {
|
|
168
|
+
* console.error('Error:', error);
|
|
169
|
+
* }
|
|
170
|
+
* });
|
|
171
|
+
*
|
|
172
|
+
* // Send text message
|
|
173
|
+
* await ws.send('Hello World');
|
|
174
|
+
*
|
|
175
|
+
* // Send binary message
|
|
176
|
+
* await ws.send(Buffer.from([1, 2, 3]));
|
|
177
|
+
*
|
|
178
|
+
* // Close connection
|
|
179
|
+
* await ws.close();
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
class WebSocket {
|
|
183
|
+
constructor(connection) {
|
|
184
|
+
this._connection = connection;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Send a message (text or binary)
|
|
188
|
+
*/
|
|
189
|
+
async send(data) {
|
|
190
|
+
try {
|
|
191
|
+
await nativeBinding.websocketSend(this._connection, data);
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
throw new types_1.RequestError(String(error));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Close the WebSocket connection
|
|
199
|
+
*/
|
|
200
|
+
async close() {
|
|
201
|
+
try {
|
|
202
|
+
await nativeBinding.websocketClose(this._connection);
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
throw new types_1.RequestError(String(error));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.WebSocket = WebSocket;
|
|
210
|
+
/**
|
|
211
|
+
* Create a WebSocket connection with browser impersonation
|
|
212
|
+
*
|
|
213
|
+
* @param options - WebSocket options
|
|
214
|
+
* @returns Promise that resolves to the WebSocket instance
|
|
215
|
+
*/
|
|
216
|
+
async function websocket(options) {
|
|
217
|
+
if (!options.url) {
|
|
218
|
+
throw new types_1.RequestError('URL is required');
|
|
219
|
+
}
|
|
220
|
+
if (!options.onMessage) {
|
|
221
|
+
throw new types_1.RequestError('onMessage callback is required');
|
|
222
|
+
}
|
|
223
|
+
if (options.browser) {
|
|
224
|
+
const profiles = getProfiles();
|
|
225
|
+
if (!profiles.includes(options.browser)) {
|
|
226
|
+
throw new types_1.RequestError(`Invalid browser profile: ${options.browser}. Available profiles: ${profiles.join(', ')}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
const connection = await nativeBinding.websocketConnect({
|
|
231
|
+
url: options.url,
|
|
232
|
+
browser: options.browser || 'chrome_137',
|
|
233
|
+
headers: options.headers || {},
|
|
234
|
+
proxy: options.proxy,
|
|
235
|
+
onMessage: options.onMessage,
|
|
236
|
+
onClose: options.onClose,
|
|
237
|
+
onError: options.onError,
|
|
238
|
+
});
|
|
239
|
+
return new WebSocket(connection);
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
throw new types_1.RequestError(String(error));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
exports.default = {
|
|
246
|
+
request,
|
|
247
|
+
get,
|
|
248
|
+
post,
|
|
249
|
+
getProfiles,
|
|
250
|
+
websocket,
|
|
251
|
+
WebSocket,
|
|
252
|
+
};
|
|
253
|
+
//# sourceMappingURL=wreq-js.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wreq-js.js","sourceRoot":"","sources":["../src/wreq-js.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wreq-js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Browser fingerprint bypass library using Rust for TLS/HTTP2 impersonation",
|
|
5
|
+
"main": "dist/wreq-js.js",
|
|
6
|
+
"types": "dist/wreq-js.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/wreq-js.d.ts",
|
|
10
|
+
"require": "./dist/wreq-js.js",
|
|
11
|
+
"import": "./dist/wreq-js.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "npm run build:rust && npm run build:ts",
|
|
16
|
+
"build:rust": "napi build --platform --release --cargo-cwd rust rust",
|
|
17
|
+
"build:ts": "npm run clean:dist && tsc",
|
|
18
|
+
"clean:dist": "rimraf dist",
|
|
19
|
+
"artifacts": "napi artifacts",
|
|
20
|
+
"clean": "rimraf dist rust/target rust/*.node",
|
|
21
|
+
"test": "npm run build && node --test dist/test/http.spec.js dist/test/websocket.spec.js",
|
|
22
|
+
"format": "prettier --write \"src/**/*.{ts,js,json,md}\"",
|
|
23
|
+
"format:check": "prettier --check \"src/**/*.{ts,js,json,md}\""
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"browser",
|
|
27
|
+
"fingerprint",
|
|
28
|
+
"bypass",
|
|
29
|
+
"anti-bot",
|
|
30
|
+
"tls",
|
|
31
|
+
"http2",
|
|
32
|
+
"impersonation",
|
|
33
|
+
"web-scraping",
|
|
34
|
+
"crawler",
|
|
35
|
+
"web-scraper",
|
|
36
|
+
"wreq",
|
|
37
|
+
"ja3",
|
|
38
|
+
"tls-fingerprint",
|
|
39
|
+
"ja4",
|
|
40
|
+
"browser-fingerprint-bypass"
|
|
41
|
+
],
|
|
42
|
+
"author": "Oleksandr Herasymov <herasymov7@icloud.com>",
|
|
43
|
+
"contributors": [
|
|
44
|
+
"will-work-for-meal"
|
|
45
|
+
],
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/sqdshguy/wreq-js.git"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/sqdshguy/wreq-js/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/sqdshguy/wreq-js#readme",
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@napi-rs/cli": "^2.18.0",
|
|
57
|
+
"@types/node": "^20.0.0",
|
|
58
|
+
"prettier": "^3.2.5",
|
|
59
|
+
"rimraf": "^6.0.1",
|
|
60
|
+
"typescript": "^5.0.0"
|
|
61
|
+
},
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=20.0.0"
|
|
64
|
+
},
|
|
65
|
+
"os": [
|
|
66
|
+
"darwin",
|
|
67
|
+
"linux",
|
|
68
|
+
"win32"
|
|
69
|
+
],
|
|
70
|
+
"cpu": [
|
|
71
|
+
"x64",
|
|
72
|
+
"arm64"
|
|
73
|
+
],
|
|
74
|
+
"files": [
|
|
75
|
+
"dist",
|
|
76
|
+
"rust/*.node"
|
|
77
|
+
],
|
|
78
|
+
"napi": {
|
|
79
|
+
"name": "wreq-js",
|
|
80
|
+
"triples": {
|
|
81
|
+
"defaults": true,
|
|
82
|
+
"additional": [
|
|
83
|
+
"x86_64-apple-darwin",
|
|
84
|
+
"aarch64-apple-darwin",
|
|
85
|
+
"x86_64-unknown-linux-gnu",
|
|
86
|
+
"aarch64-unknown-linux-gnu",
|
|
87
|
+
"x86_64-pc-windows-msvc"
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|