@hyperttp/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +210 -0
- package/dist/Core/HyperCore.d.ts +59 -0
- package/dist/Core/HyperCore.d.ts.map +1 -0
- package/dist/Core/HyperCore.js +162 -0
- package/dist/Core/HyperCore.js.map +1 -0
- package/dist/Core/RequestExecutor.d.ts +56 -0
- package/dist/Core/RequestExecutor.d.ts.map +1 -0
- package/dist/Core/RequestExecutor.js +194 -0
- package/dist/Core/RequestExecutor.js.map +1 -0
- package/dist/Core/index.d.ts +4 -0
- package/dist/Core/index.d.ts.map +1 -0
- package/dist/Core/index.js +3 -0
- package/dist/Core/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/types/errors.d.ts +15 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +28 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/http.d.ts +5 -0
- package/dist/types/http.d.ts.map +1 -0
- package/dist/types/http.js +2 -0
- package/dist/types/http.js.map +1 -0
- package/dist/types/metrics.d.ts +63 -0
- package/dist/types/metrics.d.ts.map +1 -0
- package/dist/types/metrics.js +2 -0
- package/dist/types/metrics.js.map +1 -0
- package/dist/types/network.d.ts +60 -0
- package/dist/types/network.d.ts.map +1 -0
- package/dist/types/network.js +2 -0
- package/dist/types/network.js.map +1 -0
- package/dist/types/options.d.ts +41 -0
- package/dist/types/options.d.ts.map +1 -0
- package/dist/types/options.js +2 -0
- package/dist/types/options.js.map +1 -0
- package/dist/types/request.d.ts +189 -0
- package/dist/types/request.d.ts.map +1 -0
- package/dist/types/request.js +2 -0
- package/dist/types/request.js.map +1 -0
- package/dist/types/retry.d.ts +28 -0
- package/dist/types/retry.d.ts.map +1 -0
- package/dist/types/retry.js +2 -0
- package/dist/types/retry.js.map +1 -0
- package/dist/types/stream.d.ts +39 -0
- package/dist/types/stream.d.ts.map +1 -0
- package/dist/types/stream.js +2 -0
- package/dist/types/stream.js.map +1 -0
- package/package.json +30 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 IT IF OR
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# @hyperttp/core 🚀
|
|
2
|
+
|
|
3
|
+
> English | Русский
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🌐 Language / Язык
|
|
8
|
+
|
|
9
|
+
- 🇺🇸 [English](https://github.com/IT-IF-OR/hyperttp-core)
|
|
10
|
+
- 🇷🇺 [Русский](https://github.com/IT-IF-OR/hyperttp-core/tree/main/lang/ru)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
High-performance HTTP core for Node.js and Bun built on top of `undici`.
|
|
15
|
+
|
|
16
|
+
`@hyperttp/core` is designed for:
|
|
17
|
+
|
|
18
|
+
- stable p90/p99 latency,
|
|
19
|
+
- predictable behavior under load,
|
|
20
|
+
- tail-latency reduction,
|
|
21
|
+
- high throughput performance,
|
|
22
|
+
- low overhead transport-layer abstraction.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- ⚡ High performance HTTP execution layer
|
|
29
|
+
- 📉 Stable p90/p99 latency under load
|
|
30
|
+
- 🔄 Keep-Alive & connection pooling
|
|
31
|
+
- 🌊 Stream response support
|
|
32
|
+
- 🍪 CookieAgent integration
|
|
33
|
+
- 📈 Request metrics tracking
|
|
34
|
+
- 🔧 Flexible network-layer configuration
|
|
35
|
+
- ♻️ Retry & redirect handling
|
|
36
|
+
- 🧩 Simple API over `undici`
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Performance
|
|
41
|
+
|
|
42
|
+
`@hyperttp/core` provides:
|
|
43
|
+
|
|
44
|
+
- minimal p99 latency among most HTTP clients,
|
|
45
|
+
- throughput close to `undici`,
|
|
46
|
+
- significantly more stable latency under load.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Benchmark
|
|
51
|
+
|
|
52
|
+
### Test configuration
|
|
53
|
+
|
|
54
|
+
```txt
|
|
55
|
+
Requests 20000
|
|
56
|
+
Concurrency 200
|
|
57
|
+
Warmup 500
|
|
58
|
+
Timeout 60000 ms
|
|
59
|
+
Runtime Node.js
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Benchmark executed via:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx tsx ./bench.ts
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## [Benchmark results](https://github.com/IT-IF-OR/bench)
|
|
71
|
+
|
|
72
|
+
| Client | RPS | Avg | p99 | Heap |
|
|
73
|
+
| :------------- | ----: | ------: | -------: | ------: |
|
|
74
|
+
| undici | 9.86K | 20.22ms | 203.05ms | 155 MB |
|
|
75
|
+
| @hyperttp/core | 9.04K | 22.10ms | 29.14ms | 295 MB |
|
|
76
|
+
| hyperttp | 7.10K | 28.12ms | 40.02ms | 272 MB |
|
|
77
|
+
| fetch | 5.78K | 34.47ms | 322.17ms | 289 MB |
|
|
78
|
+
| ky | 4.50K | 44.35ms | 440.24ms | 374 MB |
|
|
79
|
+
| axios | 4.08K | 48.76ms | 54.92ms | 238 MB |
|
|
80
|
+
| node-fetch | 3.62K | 55.10ms | 83.60ms | 434 MB |
|
|
81
|
+
| got | 3.06K | 65.31ms | 96.38ms | 164 MB |
|
|
82
|
+
| superagent | 2.96K | 67.29ms | 78.96ms | 81.1 MB |
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Why p99 matters
|
|
87
|
+
|
|
88
|
+
Most HTTP clients look good on average latency but suffer from high tail latency
|
|
89
|
+
under load.
|
|
90
|
+
|
|
91
|
+
`@hyperttp/core` is optimized for:
|
|
92
|
+
|
|
93
|
+
- stable scheduling behavior,
|
|
94
|
+
- predictable concurrency,
|
|
95
|
+
- minimized latency spikes,
|
|
96
|
+
- burst workload stability.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Installation
|
|
101
|
+
|
|
102
|
+
### Bun
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
bun add @hyperttp/core
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### npm
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npm install @hyperttp/core
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Quick start
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { HyperCore } from "@hyperttp/core";
|
|
120
|
+
|
|
121
|
+
const core = new HyperCore({
|
|
122
|
+
verbose: true,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const response = await core.get("http://localhost:3000/json");
|
|
126
|
+
|
|
127
|
+
console.log(response.body);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Configuration
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { HyperCore } from "@hyperttp/core";
|
|
136
|
+
|
|
137
|
+
const core = new HyperCore({
|
|
138
|
+
verbose: true,
|
|
139
|
+
|
|
140
|
+
trackMetrics: true,
|
|
141
|
+
|
|
142
|
+
network: {
|
|
143
|
+
timeout: 30000,
|
|
144
|
+
maxConcurrent: 500,
|
|
145
|
+
pipelining: 10,
|
|
146
|
+
keepAliveTimeout: 30000,
|
|
147
|
+
allowHttp2: true,
|
|
148
|
+
followRedirects: true,
|
|
149
|
+
maxRedirects: 5,
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
retry: {
|
|
153
|
+
maxRetries: 3,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Stream API
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import fs from "node:fs";
|
|
164
|
+
|
|
165
|
+
const stream = await core.stream("https://example.com/file.zip");
|
|
166
|
+
|
|
167
|
+
stream.body.pipe(fs.createWriteStream("./file.zip"));
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Metrics
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
const core = new HyperCore({
|
|
176
|
+
trackMetrics: true,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
const response = await core.get("https://api.example.com");
|
|
180
|
+
|
|
181
|
+
console.log(response.meta?.timings);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Example:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
{
|
|
188
|
+
networkMs: 12.41;
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Runtime support
|
|
195
|
+
|
|
196
|
+
- Node.js 18+
|
|
197
|
+
- Bun
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Built on
|
|
202
|
+
|
|
203
|
+
- `undici`
|
|
204
|
+
- `http-cookie-agent`
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## License
|
|
209
|
+
|
|
210
|
+
MIT
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Method } from "../types/http.js";
|
|
2
|
+
import type { HttpClientOptions } from "../types/options.js";
|
|
3
|
+
import type { RequestBodyData, RequestInterface } from "../types/request.js";
|
|
4
|
+
import type { StreamResponse } from "../types/stream.js";
|
|
5
|
+
import type { Readable } from "node:stream";
|
|
6
|
+
import type { RequestMetrics } from "../types/metrics.js";
|
|
7
|
+
export interface InternalRequest {
|
|
8
|
+
method: Method;
|
|
9
|
+
url: RequestInterface | string;
|
|
10
|
+
headers: Record<string, string>;
|
|
11
|
+
body?: RequestBodyData;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
isGet: boolean;
|
|
14
|
+
meta?: {
|
|
15
|
+
timings?: {
|
|
16
|
+
serializationMs?: number;
|
|
17
|
+
networkMs?: number;
|
|
18
|
+
parsingMs?: number;
|
|
19
|
+
};
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface HttpResponse<T = any> {
|
|
24
|
+
status: number;
|
|
25
|
+
headers: Record<string, any>;
|
|
26
|
+
url?: string;
|
|
27
|
+
body: T;
|
|
28
|
+
}
|
|
29
|
+
export interface HyperStats {
|
|
30
|
+
inflightRequests?: number;
|
|
31
|
+
cacheSize?: number;
|
|
32
|
+
queuedRequests?: number;
|
|
33
|
+
activeQueue?: number;
|
|
34
|
+
rateLimitHits?: number;
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}
|
|
37
|
+
export declare class HyperCore {
|
|
38
|
+
config: HttpClientOptions;
|
|
39
|
+
private agent;
|
|
40
|
+
private executor;
|
|
41
|
+
private defaultHeaders;
|
|
42
|
+
constructor(config: HttpClientOptions);
|
|
43
|
+
dispatch: <T = any>(req: InternalRequest) => Promise<HttpResponse<T>>;
|
|
44
|
+
get<T = any>(req: RequestInterface | string, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
45
|
+
post<T = any>(req: RequestInterface | string, body?: RequestBodyData, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
46
|
+
put<T = any>(req: RequestInterface | string, body?: RequestBodyData): Promise<HttpResponse<T>>;
|
|
47
|
+
delete<T = any>(req: RequestInterface | string): Promise<HttpResponse<T>>;
|
|
48
|
+
patch<T = any>(req: RequestInterface | string, body?: RequestBodyData): Promise<HttpResponse<T>>;
|
|
49
|
+
options<T = any>(req: RequestInterface | string, body?: RequestBodyData): Promise<HttpResponse<T>>;
|
|
50
|
+
head(req: RequestInterface | string): Promise<HttpResponse<null>>;
|
|
51
|
+
extend(options: Partial<HttpClientOptions>): HyperCore;
|
|
52
|
+
create(options: Partial<HttpClientOptions>): HyperCore;
|
|
53
|
+
stream(req: RequestInterface | string): Promise<StreamResponse<Readable>>;
|
|
54
|
+
private requestInternal;
|
|
55
|
+
getStats(): HyperStats;
|
|
56
|
+
getAllMetrics(): RequestMetrics[];
|
|
57
|
+
destroy(): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=HyperCore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HyperCore.d.ts","sourceRoot":"","sources":["../../src/Core/HyperCore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,gBAAgB,GAAG,MAAM,CAAC;IAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE;YACR,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,SAAS,CAAC,EAAE,MAAM,CAAC;SACpB,CAAC;QACF,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,WAAW,UAAU;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,qBAAa,SAAS;IACb,MAAM,EAAE,iBAAiB,CAAC;IACjC,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,cAAc,CAAyB;gBAEnC,MAAM,EAAE,iBAAiB;IA8C9B,QAAQ,GAAU,CAAC,GAAG,GAAG,EAC9B,KAAK,eAAe,KACnB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAiCzB;IAEK,GAAG,CAAC,CAAC,GAAG,GAAG,EAChB,GAAG,EAAE,gBAAgB,GAAG,MAAM,EAC9B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAapB,IAAI,CAAC,CAAC,GAAG,GAAG,EACjB,GAAG,EAAE,gBAAgB,GAAG,MAAM,EAC9B,IAAI,CAAC,EAAE,eAAe,EACtB,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAIpB,GAAG,CAAC,CAAC,GAAG,GAAG,EAChB,GAAG,EAAE,gBAAgB,GAAG,MAAM,EAC9B,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAIpB,MAAM,CAAC,CAAC,GAAG,GAAG,EACnB,GAAG,EAAE,gBAAgB,GAAG,MAAM,GAC7B,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAIpB,KAAK,CAAC,CAAC,GAAG,GAAG,EAClB,GAAG,EAAE,gBAAgB,GAAG,MAAM,EAC9B,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAIpB,OAAO,CAAC,CAAC,GAAG,GAAG,EACpB,GAAG,EAAE,gBAAgB,GAAG,MAAM,EAC9B,IAAI,CAAC,EAAE,eAAe,GACrB,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAId,IAAI,CACf,GAAG,EAAE,gBAAgB,GAAG,MAAM,GAC7B,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAIvB,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,SAAS;IAWtD,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,SAAS;IAIhD,MAAM,CACjB,GAAG,EAAE,gBAAgB,GAAG,MAAM,GAC7B,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YA2BtB,eAAe;IAqBtB,QAAQ,IAAI,UAAU;IAItB,aAAa,IAAI,cAAc,EAAE;IAI3B,OAAO;CAcrB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { CookieAgent } from "http-cookie-agent/undici";
|
|
2
|
+
import { RequestExecutor } from "./RequestExecutor.js";
|
|
3
|
+
export class HyperCore {
|
|
4
|
+
config;
|
|
5
|
+
agent;
|
|
6
|
+
executor;
|
|
7
|
+
defaultHeaders;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
const concurrency = config.network?.maxConcurrent === 0
|
|
11
|
+
? Infinity
|
|
12
|
+
: (config.network?.maxConcurrent ?? 500);
|
|
13
|
+
const pipelining = config.network?.pipelining === 0
|
|
14
|
+
? 256
|
|
15
|
+
: (config.network?.pipelining ?? 10);
|
|
16
|
+
this.agent = new CookieAgent({
|
|
17
|
+
connections: concurrency === Infinity ? 0x7fffffff : concurrency,
|
|
18
|
+
pipelining: pipelining,
|
|
19
|
+
keepAliveTimeout: config.network?.keepAliveTimeout ?? 30000,
|
|
20
|
+
keepAliveMaxTimeout: config.network?.keepAliveTimeout ?? 30000,
|
|
21
|
+
connect: { rejectUnauthorized: config.network?.rejectUnauthorized },
|
|
22
|
+
allowH2: config.network?.allowHttp2 ?? true,
|
|
23
|
+
});
|
|
24
|
+
const retryOptions = {
|
|
25
|
+
maxRetries: config.retry?.maxRetries ?? 3,
|
|
26
|
+
...config.retry,
|
|
27
|
+
};
|
|
28
|
+
const network = config.network;
|
|
29
|
+
this.executor = new RequestExecutor(this.agent, {
|
|
30
|
+
timeout: network?.timeout ?? 30000,
|
|
31
|
+
maxRetries: retryOptions.maxRetries ?? 3,
|
|
32
|
+
followRedirects: network?.followRedirects ?? true,
|
|
33
|
+
maxRedirects: network?.maxRedirects ?? 5,
|
|
34
|
+
retryOptions: retryOptions,
|
|
35
|
+
verbose: config.verbose ?? false,
|
|
36
|
+
logger: config.logger,
|
|
37
|
+
});
|
|
38
|
+
this.defaultHeaders = {
|
|
39
|
+
Accept: "application/json, text/plain, */*",
|
|
40
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
41
|
+
"User-Agent": config.network?.userAgent || "Hyperttp/2.0",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
dispatch = async (req) => {
|
|
45
|
+
const urlString = typeof req.url === "string" ? req.url : req.url.getURL();
|
|
46
|
+
if (req.signal?.aborted) {
|
|
47
|
+
throw new Error("Request aborted by user");
|
|
48
|
+
}
|
|
49
|
+
req.meta = req.meta || {};
|
|
50
|
+
req.meta.timings = req.meta.timings || {};
|
|
51
|
+
const startNetwork = this.config.trackMetrics
|
|
52
|
+
? process.hrtime.bigint()
|
|
53
|
+
: null;
|
|
54
|
+
const rawResponse = await this.executor.execute(req.method, urlString, req.headers, req.body, req.signal);
|
|
55
|
+
if (this.config.trackMetrics && startNetwork !== null) {
|
|
56
|
+
req.meta.timings.networkMs =
|
|
57
|
+
Number(process.hrtime.bigint() - startNetwork) / 1_000_000;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
status: rawResponse.status,
|
|
61
|
+
headers: rawResponse.headers,
|
|
62
|
+
body: req.method === "HEAD" ? undefined : rawResponse.body,
|
|
63
|
+
url: rawResponse.url,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
get(req, signal) {
|
|
67
|
+
if (typeof req === "string") {
|
|
68
|
+
return this.dispatch({
|
|
69
|
+
method: "GET",
|
|
70
|
+
url: req,
|
|
71
|
+
headers: { ...this.defaultHeaders },
|
|
72
|
+
isGet: true,
|
|
73
|
+
signal,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return this.requestInternal("GET", req, undefined, true, signal);
|
|
77
|
+
}
|
|
78
|
+
post(req, body, signal) {
|
|
79
|
+
return this.requestInternal("POST", req, body, false, signal);
|
|
80
|
+
}
|
|
81
|
+
put(req, body) {
|
|
82
|
+
return this.requestInternal("PUT", req, body, false);
|
|
83
|
+
}
|
|
84
|
+
delete(req) {
|
|
85
|
+
return this.requestInternal("DELETE", req, undefined, false);
|
|
86
|
+
}
|
|
87
|
+
patch(req, body) {
|
|
88
|
+
return this.requestInternal("PATCH", req, body, false);
|
|
89
|
+
}
|
|
90
|
+
options(req, body) {
|
|
91
|
+
return this.requestInternal("OPTIONS", req, body, false);
|
|
92
|
+
}
|
|
93
|
+
async head(req) {
|
|
94
|
+
return this.requestInternal("HEAD", req, undefined, false);
|
|
95
|
+
}
|
|
96
|
+
extend(options) {
|
|
97
|
+
return new HyperCore({
|
|
98
|
+
...this.config,
|
|
99
|
+
...options,
|
|
100
|
+
network: {
|
|
101
|
+
...this.config.network,
|
|
102
|
+
...options.network,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
create(options) {
|
|
107
|
+
return this.extend(options);
|
|
108
|
+
}
|
|
109
|
+
async stream(req) {
|
|
110
|
+
const url = typeof req === "string" ? req : req.getURL();
|
|
111
|
+
const signal = typeof req !== "string"
|
|
112
|
+
? (req.getSignal?.() ?? req.signal)
|
|
113
|
+
: undefined;
|
|
114
|
+
const headers = {
|
|
115
|
+
...this.defaultHeaders,
|
|
116
|
+
...(typeof req !== "string" ? req.getHeaders?.() : {}),
|
|
117
|
+
};
|
|
118
|
+
const rawResponse = await this.executor.execute("GET", url, headers, undefined, signal);
|
|
119
|
+
return {
|
|
120
|
+
status: rawResponse.status,
|
|
121
|
+
headers: rawResponse.headers,
|
|
122
|
+
body: rawResponse.body,
|
|
123
|
+
url: rawResponse.url,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
async requestInternal(method, req, body, isGet = false, signal) {
|
|
127
|
+
return this.dispatch({
|
|
128
|
+
method,
|
|
129
|
+
url: req,
|
|
130
|
+
headers: {
|
|
131
|
+
...this.defaultHeaders,
|
|
132
|
+
...(typeof req !== "string" ? req.getHeaders?.() : {}),
|
|
133
|
+
},
|
|
134
|
+
body: typeof req !== "string" && req.getBodyData ? req.getBodyData() : body,
|
|
135
|
+
isGet,
|
|
136
|
+
signal: typeof req !== "string" ? req.getSignal?.() : signal,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
getStats() {
|
|
140
|
+
return {};
|
|
141
|
+
}
|
|
142
|
+
getAllMetrics() {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
async destroy() {
|
|
146
|
+
try {
|
|
147
|
+
const anyAgent = this.agent;
|
|
148
|
+
if (typeof anyAgent.destroy === "function") {
|
|
149
|
+
await anyAgent.destroy();
|
|
150
|
+
}
|
|
151
|
+
else if (typeof anyAgent.close === "function") {
|
|
152
|
+
await anyAgent.close();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
if (this.config.verbose) {
|
|
157
|
+
console.warn("[HyperCore] destroy failed:", error);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=HyperCore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HyperCore.js","sourceRoot":"","sources":["../../src/Core/HyperCore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Agent } from "undici";
|
|
2
|
+
import type { RetryOptions } from "../types/retry.js";
|
|
3
|
+
import type { LogLevel } from "../types/http.js";
|
|
4
|
+
import type { RequestMetrics } from "../types/metrics.js";
|
|
5
|
+
type LowLevelResponse = {
|
|
6
|
+
status: number;
|
|
7
|
+
headers: Record<string, string | string[] | undefined>;
|
|
8
|
+
body: any;
|
|
9
|
+
url: string;
|
|
10
|
+
};
|
|
11
|
+
interface DynamicInterceptor {
|
|
12
|
+
applyRequest(config: any): Promise<any>;
|
|
13
|
+
applyResponse(response: any): Promise<any>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @en Low-level request executor responsible for handling the actual HTTP lifecycle.
|
|
17
|
+
* @ru Низкоуровневый исполнитель запросов, отвечающий за полный цикл HTTP-жизни.
|
|
18
|
+
*/
|
|
19
|
+
export declare class RequestExecutor {
|
|
20
|
+
private agent;
|
|
21
|
+
private options;
|
|
22
|
+
private readonly redirectStatusCodes;
|
|
23
|
+
constructor(agent: Agent, options: {
|
|
24
|
+
timeout: number;
|
|
25
|
+
maxRetries: number;
|
|
26
|
+
followRedirects: boolean;
|
|
27
|
+
maxRedirects: number;
|
|
28
|
+
retryOptions: RetryOptions;
|
|
29
|
+
verbose?: boolean;
|
|
30
|
+
logger?: (level: LogLevel, message: string, meta?: any) => void;
|
|
31
|
+
});
|
|
32
|
+
/**
|
|
33
|
+
* @en Executes a raw HTTP request.
|
|
34
|
+
* @ru Выполняет "сырой" HTTP-запрос.
|
|
35
|
+
*/
|
|
36
|
+
execute(method: string, url: string, headers: Record<string, string>, body: string | Buffer | undefined, signal?: AbortSignal, metrics?: RequestMetrics, interceptors?: DynamicInterceptor | any): Promise<LowLevelResponse>;
|
|
37
|
+
/**
|
|
38
|
+
* @en Calculates the delay for the next retry attempt using exponential backoff.
|
|
39
|
+
* @ru Вычисляет задержку для следующей попытки повтора.
|
|
40
|
+
*/
|
|
41
|
+
private calcDelay;
|
|
42
|
+
private sleep;
|
|
43
|
+
/**
|
|
44
|
+
* @en Ensures that the response body stream is properly closed to prevent memory leaks.
|
|
45
|
+
* @ru Гарантирует, что поток тела ответа корректно закрыт.
|
|
46
|
+
*/
|
|
47
|
+
private drainBody;
|
|
48
|
+
/**
|
|
49
|
+
* @en Checks if the status code should trigger a retry attempt.
|
|
50
|
+
* @ru Проверяет, должен ли данный статус-код вызывать повтор запроса.
|
|
51
|
+
*/
|
|
52
|
+
private shouldRetry;
|
|
53
|
+
private executeCore;
|
|
54
|
+
}
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=RequestExecutor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestExecutor.d.ts","sourceRoot":"","sources":["../../src/Core/RequestExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,KAAK,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAU,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,KAAK,gBAAgB,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,IAAI,EAAE,GAAG,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,UAAU,kBAAkB;IAC1B,YAAY,CAAC,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACxC,aAAa,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CAC5C;AAED;;;GAGG;AACH,qBAAa,eAAe;IAIxB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,OAAO;IAJjB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsC;gBAGhE,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,eAAe,EAAE,OAAO,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,YAAY,CAAC;QAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC;KACjE;IAGH;;;OAGG;IACG,OAAO,CACX,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EACjC,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,CAAC,EAAE,cAAc,EACxB,YAAY,CAAC,EAAE,kBAAkB,GAAG,GAAG,GACtC,OAAO,CAAC,gBAAgB,CAAC;IAa5B;;;OAGG;IACH,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,KAAK;IAIb;;;OAGG;YACW,SAAS;IAoBvB;;;OAGG;IACH,OAAO,CAAC,WAAW;YAQL,WAAW;CA2L1B"}
|