@hyperttp/core 1.2.6 → 1.3.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/Core/HyperCore.d.ts +36 -23
- package/Core/HyperCore.d.ts.map +1 -1
- package/Core/HyperCore.js +213 -231
- package/Core/HyperCore.js.map +1 -1
- package/package.json +6 -3
- package/transports/manager.d.ts +28 -0
- package/transports/manager.d.ts.map +1 -0
- package/transports/manager.js +193 -0
- package/transports/manager.js.map +1 -0
- package/transports/node.d.ts +11 -10
- package/transports/node.d.ts.map +1 -1
- package/transports/node.js +81 -325
- package/transports/node.js.map +1 -1
- package/utils/decompress.d.ts +7 -0
- package/utils/decompress.d.ts.map +1 -0
- package/utils/decompress.js +78 -0
- package/utils/decompress.js.map +1 -0
- package/utils/normalize.d.ts +2 -1
- package/utils/normalize.d.ts.map +1 -1
- package/utils/normalize.js +139 -61
- package/utils/normalize.js.map +1 -1
- package/utils/pipeline.d.ts +14 -5
- package/utils/pipeline.d.ts.map +1 -1
- package/utils/pipeline.js +102 -16
- package/utils/pipeline.js.map +1 -1
- package/utils/response.d.ts +0 -3
- package/utils/response.d.ts.map +1 -1
- package/utils/response.js +0 -3
- package/utils/response.js.map +1 -1
package/Core/HyperCore.d.ts
CHANGED
|
@@ -1,48 +1,61 @@
|
|
|
1
1
|
import type { IHyperCore, HyperTransport, HttpClientOptions, HyperPlugin, InternalRequest, HttpResponse, RequestInterface, StreamResponse, RequestBodyData } from "@hyperttp/types";
|
|
2
|
-
declare module "@hyperttp/types" {
|
|
3
|
-
interface HyperttpPluginsExtension {
|
|
4
|
-
baseURL?: string;
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
export type Runtime = "bun" | "node";
|
|
8
|
-
export declare function getRuntime(): Runtime;
|
|
9
|
-
type TransportDef = {
|
|
10
|
-
name: string;
|
|
11
|
-
runtime: Runtime[];
|
|
12
|
-
pkg: string;
|
|
13
|
-
export: string;
|
|
14
|
-
priority: number;
|
|
15
|
-
};
|
|
16
|
-
export declare const TRANSPORTS: TransportDef[];
|
|
17
|
-
export declare function resolveTransport(config: HttpClientOptions): Promise<HyperTransport>;
|
|
18
2
|
export declare class HyperCore implements IHyperCore {
|
|
19
3
|
config: HttpClientOptions;
|
|
20
|
-
private
|
|
21
|
-
private transportPromise;
|
|
4
|
+
private readonly transportManager;
|
|
22
5
|
private readonly defaultHeaders;
|
|
23
6
|
private readonly pluginCtx;
|
|
24
7
|
private readonly pipelines;
|
|
25
8
|
constructor(config?: HttpClientOptions, transport?: HyperTransport);
|
|
26
|
-
private
|
|
9
|
+
private get transport();
|
|
27
10
|
private ensureTransport;
|
|
11
|
+
/**
|
|
12
|
+
* Центральный метод обработки запросов
|
|
13
|
+
*/
|
|
14
|
+
private dispatchInternal;
|
|
28
15
|
dispatch<T = unknown>(req: InternalRequest): Promise<HttpResponse<T>>;
|
|
16
|
+
/**
|
|
17
|
+
* Регистрация плагинов
|
|
18
|
+
*/
|
|
29
19
|
use(plugin: HyperPlugin): this;
|
|
20
|
+
/**
|
|
21
|
+
* Публичные HTTP методы-помощники
|
|
22
|
+
*/
|
|
30
23
|
stream(req: RequestInterface | string, signal?: AbortSignal): Promise<StreamResponse<unknown>>;
|
|
24
|
+
postStream<T = unknown>(req: RequestInterface | string, body?: RequestBodyData, signal?: AbortSignal): Promise<StreamResponse<T>>;
|
|
31
25
|
get<T = unknown>(req: RequestInterface | string, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
32
26
|
post<T = unknown>(req: RequestInterface | string, body?: RequestBodyData, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
33
|
-
postStream<T = unknown>(req: RequestInterface | string, body?: RequestBodyData, signal?: AbortSignal): Promise<StreamResponse<T>>;
|
|
34
27
|
put<T = unknown>(req: RequestInterface | string, body?: RequestBodyData, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
35
28
|
patch<T = unknown>(req: RequestInterface | string, body?: RequestBodyData, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
36
29
|
delete<T = unknown>(req: RequestInterface | string, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
37
30
|
options<T = unknown>(req: RequestInterface | string, body?: RequestBodyData, signal?: AbortSignal): Promise<HttpResponse<T>>;
|
|
38
31
|
head(req: RequestInterface | string, signal?: AbortSignal): Promise<HttpResponse<null>>;
|
|
39
|
-
|
|
40
|
-
extend(options: Partial<HttpClientOptions>): this;
|
|
32
|
+
extend(options: Partial<HttpClientOptions>): HyperCore;
|
|
41
33
|
create(options: Partial<HttpClientOptions>): HyperCore;
|
|
42
34
|
destroy(graceful?: boolean): Promise<void>;
|
|
43
35
|
json<T = unknown>(req: RequestInterface | string, signal?: AbortSignal): Promise<T>;
|
|
44
36
|
text(req: RequestInterface | string, signal?: AbortSignal): Promise<string>;
|
|
45
37
|
dump(req: RequestInterface | string, signal?: AbortSignal): Promise<void>;
|
|
38
|
+
/**
|
|
39
|
+
* ПРИВАТНЫЕ МЕТОДЫ-ПОМОЩНИКИ (РЕФАКТОРИНГ)
|
|
40
|
+
*/
|
|
41
|
+
private runResponsePipeline;
|
|
42
|
+
/**
|
|
43
|
+
* Изолированная обработка ошибок пайплайна ответа
|
|
44
|
+
*/
|
|
45
|
+
private handleDispatchError;
|
|
46
|
+
/**
|
|
47
|
+
* Применение встроенной декомпрессии на основе заголовков ответа транспорта
|
|
48
|
+
*/
|
|
49
|
+
private applyDecompression;
|
|
50
|
+
/**
|
|
51
|
+
* Сборка внутреннего объекта запроса InternalRequest
|
|
52
|
+
*/
|
|
53
|
+
private buildInternalRequest;
|
|
54
|
+
/**
|
|
55
|
+
* Фабрика сохранения прототипа исходного запроса с подменой дескрипторов базовых свойств
|
|
56
|
+
*/
|
|
57
|
+
private createInternalRequestObject;
|
|
58
|
+
private appendQueryParams;
|
|
59
|
+
private dispatchShortcut;
|
|
46
60
|
}
|
|
47
|
-
export {};
|
|
48
61
|
//# sourceMappingURL=HyperCore.d.ts.map
|
package/Core/HyperCore.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HyperCore.d.ts","sourceRoot":"","sources":["../../src/Core/HyperCore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,iBAAiB,EAEjB,WAAW,EACX,eAAe,EACf,YAAY,EAEZ,gBAAgB,EAChB,cAAc,EACd,eAAe,EAEhB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"HyperCore.d.ts","sourceRoot":"","sources":["../../src/Core/HyperCore.ts"],"names":[],"mappings":"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"}
|
package/Core/HyperCore.js
CHANGED
|
@@ -1,67 +1,12 @@
|
|
|
1
1
|
import { defaultConfig } from "../defaultConfig.js";
|
|
2
2
|
import { mapResponseFast, mapStreamFast, mergeHeadersFast, } from "../utils/response.js";
|
|
3
|
-
import {
|
|
4
|
-
import { createPipelines, executeErrorPipeline, executeRequestPipeline, executeResponsePipeline, insertHookSorted, } from "../utils/pipeline.js";
|
|
5
|
-
import { normalizeBody, normalizeHeaders,
|
|
6
|
-
|
|
7
|
-
if (typeof Bun !== "undefined")
|
|
8
|
-
return "bun";
|
|
9
|
-
return "node";
|
|
10
|
-
}
|
|
11
|
-
export const TRANSPORTS = [
|
|
12
|
-
{
|
|
13
|
-
name: "Bun",
|
|
14
|
-
runtime: ["bun"],
|
|
15
|
-
pkg: "@hyperttp/transport-bun",
|
|
16
|
-
export: "BunTransport",
|
|
17
|
-
priority: 100,
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
name: "Undici",
|
|
21
|
-
runtime: ["node"],
|
|
22
|
-
pkg: "@hyperttp/transport-undici",
|
|
23
|
-
export: "UndiciTransport",
|
|
24
|
-
priority: 90,
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: "Node",
|
|
28
|
-
runtime: ["node", "bun"],
|
|
29
|
-
pkg: "../transports/node.js",
|
|
30
|
-
export: "NodeTransport",
|
|
31
|
-
priority: 10,
|
|
32
|
-
},
|
|
33
|
-
];
|
|
34
|
-
export async function resolveTransport(config) {
|
|
35
|
-
if (config.customTransport) {
|
|
36
|
-
config.logger?.("debug", "Using user-provided custom transport.");
|
|
37
|
-
return config.customTransport;
|
|
38
|
-
}
|
|
39
|
-
const runtime = getRuntime();
|
|
40
|
-
const candidates = TRANSPORTS.filter((t) => t.runtime.includes(runtime)).sort((a, b) => b.priority - a.priority);
|
|
41
|
-
const localRequire = createRequire(process.cwd() + "/package.json");
|
|
42
|
-
for (const t of candidates) {
|
|
43
|
-
config.logger?.("debug", `Loading transport: ${t.name}`);
|
|
44
|
-
try {
|
|
45
|
-
const path = t.pkg.startsWith(".")
|
|
46
|
-
? new URL(t.pkg, import.meta.url).href
|
|
47
|
-
: localRequire.resolve(t.pkg);
|
|
48
|
-
const mod = await import(path);
|
|
49
|
-
const Transport = mod[t.export] || mod.default?.[t.export] || mod.default;
|
|
50
|
-
if (!Transport)
|
|
51
|
-
continue;
|
|
52
|
-
config.logger?.("info", `Selected transport: ${t.name}`);
|
|
53
|
-
return new Transport(config);
|
|
54
|
-
}
|
|
55
|
-
catch (e) {
|
|
56
|
-
config.logger?.("debug", `Skip ${t.name}: ${e}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
throw new Error(`No compatible transport implementation available for runtime: ${runtime}`);
|
|
60
|
-
}
|
|
3
|
+
import { TransportManager } from "../transports/manager.js";
|
|
4
|
+
import { createPipelines, executeErrorPipeline, executeRequestPipeline, executeResponsePipeline, executeResponseDataPipeline, insertHookSorted, } from "../utils/pipeline.js";
|
|
5
|
+
import { normalizeBody, normalizeHeaders, normalizeUrl, } from "../utils/normalize.js";
|
|
6
|
+
import { decompressBuffer, createDecompressStream, } from "../utils/decompress.js";
|
|
61
7
|
export class HyperCore {
|
|
62
8
|
config;
|
|
63
|
-
|
|
64
|
-
transportPromise = null;
|
|
9
|
+
transportManager;
|
|
65
10
|
defaultHeaders;
|
|
66
11
|
pluginCtx;
|
|
67
12
|
pipelines = createPipelines();
|
|
@@ -71,54 +16,57 @@ export class HyperCore {
|
|
|
71
16
|
...config,
|
|
72
17
|
network: { ...defaultConfig.network, ...config.network },
|
|
73
18
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
this.transportPromise = Promise.resolve(transport);
|
|
77
|
-
if ("config" in transport) {
|
|
78
|
-
transport.config = this.config;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
this.defaultHeaders = {
|
|
19
|
+
this.transportManager = new TransportManager(this.config, transport);
|
|
20
|
+
this.defaultHeaders = normalizeHeaders({
|
|
82
21
|
Accept: "application/json, text/plain, */*",
|
|
83
22
|
"Accept-Encoding": "gzip, deflate, br",
|
|
84
23
|
"User-Agent": this.config.network?.userAgent ?? "Hyperttp/2.0",
|
|
85
24
|
...this.config.network?.headers,
|
|
86
|
-
};
|
|
25
|
+
});
|
|
87
26
|
this.pluginCtx = { config: this.config, core: this };
|
|
88
27
|
}
|
|
89
|
-
|
|
90
|
-
return
|
|
28
|
+
get transport() {
|
|
29
|
+
return this.transportManager.instance;
|
|
91
30
|
}
|
|
92
31
|
ensureTransport() {
|
|
93
|
-
return
|
|
94
|
-
(this.transportPromise = this.createTransport().then((t) => {
|
|
95
|
-
this.transport = t;
|
|
96
|
-
return t;
|
|
97
|
-
})));
|
|
32
|
+
return this.transportManager.get();
|
|
98
33
|
}
|
|
99
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Центральный метод обработки запросов
|
|
36
|
+
*/
|
|
37
|
+
async dispatchInternal(req) {
|
|
100
38
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
39
|
+
if (this.pipelines.request.length > 0) {
|
|
40
|
+
const shortCircuit = await executeRequestPipeline(this.pipelines.request, req, this.pluginCtx);
|
|
41
|
+
if (shortCircuit) {
|
|
42
|
+
await this.runResponsePipeline(shortCircuit, req);
|
|
43
|
+
return shortCircuit;
|
|
44
|
+
}
|
|
105
45
|
}
|
|
46
|
+
req.headers = normalizeHeaders(req.headers);
|
|
106
47
|
const transport = this.transport || (await this.ensureTransport());
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
48
|
+
let rawResponse = await transport.execute(req);
|
|
49
|
+
if (this.pipelines.responseData.length > 0) {
|
|
50
|
+
rawResponse = await executeResponseDataPipeline(this.pipelines.responseData, rawResponse, this.pluginCtx);
|
|
51
|
+
}
|
|
52
|
+
this.applyDecompression(rawResponse);
|
|
53
|
+
const isStream = req.meta?.responseType === "stream";
|
|
54
|
+
const response = isStream
|
|
55
|
+
? mapStreamFast(rawResponse)
|
|
56
|
+
: mapResponseFast(rawResponse);
|
|
57
|
+
await this.runResponsePipeline(response, req);
|
|
110
58
|
return response;
|
|
111
59
|
}
|
|
112
60
|
catch (error) {
|
|
113
|
-
|
|
114
|
-
const recovered = await executeErrorPipeline(this.pipelines.error, httpError, req, this.pluginCtx);
|
|
115
|
-
if (recovered) {
|
|
116
|
-
await executeResponsePipeline(this.pipelines.responseMutators, this.pipelines.responseSideEffects, recovered, req, this.pluginCtx, this.config.logger);
|
|
117
|
-
return recovered;
|
|
118
|
-
}
|
|
119
|
-
throw error;
|
|
61
|
+
return this.handleDispatchError(error, req);
|
|
120
62
|
}
|
|
121
63
|
}
|
|
64
|
+
async dispatch(req) {
|
|
65
|
+
return this.dispatchInternal(req);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Регистрация плагинов
|
|
69
|
+
*/
|
|
122
70
|
use(plugin) {
|
|
123
71
|
const isEnabled = plugin.enabled ? plugin.enabled(this.config) : true;
|
|
124
72
|
if (!isEnabled)
|
|
@@ -134,20 +82,21 @@ export class HyperCore {
|
|
|
134
82
|
});
|
|
135
83
|
}
|
|
136
84
|
if (plugin.onResponse) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
85
|
+
const targetPipeline = plugin.mode === "background"
|
|
86
|
+
? this.pipelines.responseSideEffects
|
|
87
|
+
: this.pipelines.responseMutators;
|
|
88
|
+
insertHookSorted(targetPipeline, {
|
|
89
|
+
name: plugin.name,
|
|
90
|
+
priority,
|
|
91
|
+
run: plugin.onResponse,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (plugin.onResponseData) {
|
|
95
|
+
insertHookSorted(this.pipelines.responseData, {
|
|
96
|
+
name: plugin.name,
|
|
97
|
+
priority,
|
|
98
|
+
run: plugin.onResponseData,
|
|
99
|
+
});
|
|
151
100
|
}
|
|
152
101
|
if (plugin.onError) {
|
|
153
102
|
insertHookSorted(this.pipelines.error, {
|
|
@@ -158,20 +107,18 @@ export class HyperCore {
|
|
|
158
107
|
}
|
|
159
108
|
return this;
|
|
160
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Публичные HTTP методы-помощники
|
|
112
|
+
*/
|
|
161
113
|
async stream(req, signal) {
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
signal: finalSignal,
|
|
171
|
-
};
|
|
172
|
-
const transport = this.transport || (await this.ensureTransport());
|
|
173
|
-
const rawResponse = await transport.execute(transportArgs);
|
|
174
|
-
return mapStreamFast(rawResponse);
|
|
114
|
+
const internalReq = this.buildInternalRequest("GET", req, undefined, signal);
|
|
115
|
+
internalReq.meta = { ...internalReq.meta, responseType: "stream" };
|
|
116
|
+
return this.dispatchInternal(internalReq);
|
|
117
|
+
}
|
|
118
|
+
async postStream(req, body, signal) {
|
|
119
|
+
const internalReq = this.buildInternalRequest("POST", req, body, signal);
|
|
120
|
+
internalReq.meta = { ...internalReq.meta, responseType: "stream" };
|
|
121
|
+
return this.dispatchInternal(internalReq);
|
|
175
122
|
}
|
|
176
123
|
get(req, signal) {
|
|
177
124
|
return this.dispatch(this.buildInternalRequest("GET", req, undefined, signal));
|
|
@@ -179,22 +126,6 @@ export class HyperCore {
|
|
|
179
126
|
post(req, body, signal) {
|
|
180
127
|
return this.dispatch(this.buildInternalRequest("POST", req, body, signal));
|
|
181
128
|
}
|
|
182
|
-
async postStream(req, body, signal) {
|
|
183
|
-
const isStr = typeof req === "string";
|
|
184
|
-
const url = isStr ? req : req.url;
|
|
185
|
-
const reqHeaders = isStr ? undefined : req.headers;
|
|
186
|
-
const finalSignal = isStr ? signal : (req.signal ?? signal);
|
|
187
|
-
const transportArgs = {
|
|
188
|
-
method: normalizeMethod("POST"),
|
|
189
|
-
url,
|
|
190
|
-
headers: normalizeHeaders(mergeHeadersFast(this.defaultHeaders, reqHeaders)),
|
|
191
|
-
body: normalizeBody("POST", isStr ? body : (req.body ?? body)),
|
|
192
|
-
signal: finalSignal,
|
|
193
|
-
};
|
|
194
|
-
const transport = this.transport || (await this.ensureTransport());
|
|
195
|
-
const rawResponse = await transport.execute(transportArgs);
|
|
196
|
-
return mapStreamFast(rawResponse);
|
|
197
|
-
}
|
|
198
129
|
put(req, body, signal) {
|
|
199
130
|
return this.dispatch(this.buildInternalRequest("PUT", req, body, signal));
|
|
200
131
|
}
|
|
@@ -210,124 +141,175 @@ export class HyperCore {
|
|
|
210
141
|
head(req, signal) {
|
|
211
142
|
return this.dispatch(this.buildInternalRequest("HEAD", req, undefined, signal));
|
|
212
143
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
144
|
+
extend(options) {
|
|
145
|
+
return new HyperCore({
|
|
146
|
+
...this.config,
|
|
147
|
+
...options,
|
|
148
|
+
network: { ...this.config.network, ...options.network },
|
|
149
|
+
}, this.transport ?? undefined);
|
|
150
|
+
}
|
|
151
|
+
create(options) {
|
|
152
|
+
return this.extend(options);
|
|
153
|
+
}
|
|
154
|
+
async destroy(graceful = true) {
|
|
155
|
+
await this.transportManager.destroy(graceful);
|
|
156
|
+
}
|
|
157
|
+
async json(req, signal) {
|
|
158
|
+
const res = await this.dispatchShortcut(req, signal);
|
|
159
|
+
if (!res.json)
|
|
160
|
+
throw new Error("[HyperCore] Method 'json()' is missing on response object.");
|
|
161
|
+
return res.json();
|
|
162
|
+
}
|
|
163
|
+
async text(req, signal) {
|
|
164
|
+
const res = await this.dispatchShortcut(req, signal);
|
|
165
|
+
if (!res.text)
|
|
166
|
+
throw new Error("[HyperCore] Method 'text()' is missing on response object.");
|
|
167
|
+
return res.text();
|
|
168
|
+
}
|
|
169
|
+
async dump(req, signal) {
|
|
170
|
+
const res = await this.dispatchShortcut(req, signal);
|
|
171
|
+
if (!res.dump)
|
|
172
|
+
throw new Error("[HyperCore] Method 'dump()' is missing on response object.");
|
|
173
|
+
await res.dump();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* ПРИВАТНЫЕ МЕТОДЫ-ПОМОЩНИКИ (РЕФАКТОРИНГ)
|
|
177
|
+
*/
|
|
178
|
+
async runResponsePipeline(response, req) {
|
|
179
|
+
const hasMutators = this.pipelines.responseMutators.length > 0;
|
|
180
|
+
const hasSideEffects = this.pipelines.responseSideEffects.length > 0;
|
|
181
|
+
if (hasMutators || hasSideEffects) {
|
|
182
|
+
await executeResponsePipeline(this.pipelines.responseMutators, this.pipelines.responseSideEffects, response, req, this.pluginCtx, this.config.logger);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Изолированная обработка ошибок пайплайна ответа
|
|
187
|
+
*/
|
|
188
|
+
async handleDispatchError(error, req) {
|
|
189
|
+
if (this.pipelines.error.length > 0) {
|
|
190
|
+
const recovered = await executeErrorPipeline(this.pipelines.error, error, req, this.pluginCtx);
|
|
191
|
+
if (recovered) {
|
|
192
|
+
await this.runResponsePipeline(recovered, req);
|
|
193
|
+
return recovered;
|
|
242
194
|
}
|
|
243
195
|
}
|
|
244
|
-
|
|
245
|
-
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Применение встроенной декомпрессии на основе заголовков ответа транспорта
|
|
200
|
+
*/
|
|
201
|
+
applyDecompression(rawResponse) {
|
|
202
|
+
if (!rawResponse.body)
|
|
203
|
+
return;
|
|
204
|
+
const encodingHeader = rawResponse.headers?.["content-encoding"] ??
|
|
205
|
+
rawResponse.headers?.["Content-Encoding"];
|
|
206
|
+
if (!encodingHeader)
|
|
207
|
+
return;
|
|
208
|
+
const contentEncoding = typeof encodingHeader === "string"
|
|
209
|
+
? encodingHeader
|
|
210
|
+
: Array.isArray(encodingHeader)
|
|
211
|
+
? encodingHeader[0]
|
|
212
|
+
: undefined;
|
|
213
|
+
if (!contentEncoding)
|
|
214
|
+
return;
|
|
215
|
+
if (rawResponse.body instanceof Uint8Array) {
|
|
216
|
+
rawResponse.body = decompressBuffer(rawResponse.body, contentEncoding);
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
rawResponse.body = createDecompressStream(rawResponse.body, contentEncoding);
|
|
246
220
|
}
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Сборка внутреннего объекта запроса InternalRequest
|
|
224
|
+
*/
|
|
225
|
+
buildInternalRequest(method, req, body, signal) {
|
|
226
|
+
const isStr = typeof req === "string";
|
|
227
|
+
const rawUrl = normalizeUrl(req);
|
|
247
228
|
if (!rawUrl) {
|
|
248
|
-
throw new Error(`[
|
|
249
|
-
`Verify incoming arguments or environment configurations.`);
|
|
229
|
+
throw new Error(`[HyperCore] Critical failure: 'url' resolved to undefined for ${method}.`);
|
|
250
230
|
}
|
|
231
|
+
const urlObj = new URL(rawUrl);
|
|
232
|
+
const castedReq = isStr
|
|
233
|
+
? undefined
|
|
234
|
+
: req;
|
|
235
|
+
if (castedReq?.query) {
|
|
236
|
+
this.appendQueryParams(urlObj, castedReq.query);
|
|
237
|
+
}
|
|
238
|
+
const context = {
|
|
239
|
+
method,
|
|
240
|
+
url: urlObj.href,
|
|
241
|
+
origin: urlObj.origin,
|
|
242
|
+
path: urlObj.pathname + urlObj.search,
|
|
243
|
+
};
|
|
251
244
|
if (isStr) {
|
|
252
245
|
return {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
headers: normalizeHeaders(this.defaultHeaders),
|
|
246
|
+
...context,
|
|
247
|
+
headers: { ...this.defaultHeaders },
|
|
256
248
|
body,
|
|
257
249
|
signal,
|
|
258
|
-
meta:
|
|
250
|
+
meta: {},
|
|
259
251
|
};
|
|
260
252
|
}
|
|
261
|
-
const
|
|
262
|
-
const rawHeaders = req.headers ?? castedReq._headers;
|
|
253
|
+
const rawHeaders = (req.headers ?? castedReq._headers);
|
|
263
254
|
const headers = rawHeaders
|
|
264
|
-
? mergeHeadersFast(this.defaultHeaders, rawHeaders)
|
|
255
|
+
? normalizeHeaders(mergeHeadersFast(this.defaultHeaders, rawHeaders))
|
|
265
256
|
: { ...this.defaultHeaders };
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
`bodyLength: ${typeof internalRequest.body === "string" ? internalRequest.body.length : 0} ` +
|
|
280
|
-
`}`);
|
|
281
|
-
return internalRequest;
|
|
282
|
-
}
|
|
283
|
-
extend(options) {
|
|
284
|
-
this.config = {
|
|
285
|
-
...this.config,
|
|
286
|
-
...options,
|
|
287
|
-
network: { ...this.config.network, ...options.network },
|
|
288
|
-
};
|
|
289
|
-
this.pluginCtx.config = this.config;
|
|
290
|
-
return this;
|
|
257
|
+
const rawBody = castedReq.body ?? castedReq.bodyData ?? castedReq._bodyData ?? body;
|
|
258
|
+
const computedBody = normalizeBody(method, rawBody);
|
|
259
|
+
const computedSignal = req.signal ?? castedReq._signal ?? signal;
|
|
260
|
+
const meta = (req.meta ??
|
|
261
|
+
castedReq._meta ??
|
|
262
|
+
{});
|
|
263
|
+
return this.createInternalRequestObject(castedReq, {
|
|
264
|
+
...context,
|
|
265
|
+
headers,
|
|
266
|
+
body: computedBody,
|
|
267
|
+
signal: computedSignal,
|
|
268
|
+
meta,
|
|
269
|
+
});
|
|
291
270
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
271
|
+
/**
|
|
272
|
+
* Фабрика сохранения прототипа исходного запроса с подменой дескрипторов базовых свойств
|
|
273
|
+
*/
|
|
274
|
+
createInternalRequestObject(sourceReq, overrides) {
|
|
275
|
+
const proto = Object.getPrototypeOf(sourceReq);
|
|
276
|
+
const target = proto && proto !== Object.prototype ? Object.create(proto) : {};
|
|
277
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(sourceReq));
|
|
278
|
+
const propertyDescriptors = {};
|
|
279
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
280
|
+
propertyDescriptors[key] = {
|
|
281
|
+
value,
|
|
282
|
+
enumerable: true,
|
|
283
|
+
writable: true,
|
|
284
|
+
configurable: true,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
Object.defineProperties(target, propertyDescriptors);
|
|
288
|
+
return target;
|
|
298
289
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const transport = this.transport;
|
|
302
|
-
if (!transport)
|
|
290
|
+
appendQueryParams(url, query) {
|
|
291
|
+
if (!query)
|
|
303
292
|
return;
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
293
|
+
for (const [key, value] of Object.entries(query)) {
|
|
294
|
+
if (value === undefined || value === null)
|
|
295
|
+
continue;
|
|
296
|
+
if (Array.isArray(value)) {
|
|
297
|
+
for (const item of value) {
|
|
298
|
+
if (item === undefined || item === null)
|
|
299
|
+
continue;
|
|
300
|
+
url.searchParams.append(key, String(item));
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
url.searchParams.set(key, String(value));
|
|
305
|
+
}
|
|
309
306
|
}
|
|
310
307
|
}
|
|
311
|
-
async
|
|
312
|
-
const method = typeof req === "string"
|
|
313
|
-
? "GET"
|
|
314
|
-
: (req.method ?? "GET");
|
|
315
|
-
const res = await this.dispatch(this.buildInternalRequest(method, req, undefined, signal));
|
|
316
|
-
return res.json();
|
|
317
|
-
}
|
|
318
|
-
async text(req, signal) {
|
|
308
|
+
async dispatchShortcut(req, signal) {
|
|
319
309
|
const method = typeof req === "string"
|
|
320
310
|
? "GET"
|
|
321
311
|
: (req.method ?? "GET");
|
|
322
|
-
|
|
323
|
-
return res.text();
|
|
324
|
-
}
|
|
325
|
-
async dump(req, signal) {
|
|
326
|
-
const method = typeof req === "string"
|
|
327
|
-
? "GET"
|
|
328
|
-
: (req.method ?? "GET");
|
|
329
|
-
const res = await this.dispatch(this.buildInternalRequest(method, req, undefined, signal));
|
|
330
|
-
await res.dump();
|
|
312
|
+
return this.dispatch(this.buildInternalRequest(method, req, undefined, signal));
|
|
331
313
|
}
|
|
332
314
|
}
|
|
333
315
|
//# sourceMappingURL=HyperCore.js.map
|