@subsquid/http-client 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/esm.d.ts +2 -0
- package/esm.js +3 -0
- package/lib/agent.d.ts +17 -0
- package/lib/agent.d.ts.map +1 -0
- package/lib/agent.js +57 -0
- package/lib/agent.js.map +1 -0
- package/lib/body.d.ts +15 -0
- package/lib/body.d.ts.map +1 -0
- package/lib/body.js +3 -0
- package/lib/body.js.map +1 -0
- package/lib/client.d.ts +101 -0
- package/lib/client.d.ts.map +1 -0
- package/lib/client.js +341 -0
- package/lib/client.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +21 -0
- package/lib/index.js.map +1 -0
- package/lib/request.d.ts +8 -0
- package/lib/request.d.ts.map +1 -0
- package/lib/request.js +29 -0
- package/lib/request.js.map +1 -0
- package/package.json +30 -0
- package/src/agent.ts +39 -0
- package/src/body.ts +20 -0
- package/src/client.ts +427 -0
- package/src/index.ts +2 -0
- package/src/request.ts +26 -0
package/README.md
ADDED
package/esm.d.ts
ADDED
package/esm.js
ADDED
package/lib/agent.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import * as http from 'http';
|
|
4
|
+
import * as https from 'https';
|
|
5
|
+
export interface AgentProvider {
|
|
6
|
+
getNativeAgent(url: string): http.Agent;
|
|
7
|
+
}
|
|
8
|
+
export declare const defaultAgentProvider: AgentProvider;
|
|
9
|
+
export declare class HttpAgent implements AgentProvider {
|
|
10
|
+
private options;
|
|
11
|
+
private http?;
|
|
12
|
+
private https?;
|
|
13
|
+
constructor(options: https.AgentOptions);
|
|
14
|
+
getNativeAgent(url: string): http.Agent;
|
|
15
|
+
close(): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":";;AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAC5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,WAAW,aAAa;IAC1B,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAA;CAC1C;AAGD,eAAO,MAAM,oBAAoB,EAAE,aAQlC,CAAA;AAGD,qBAAa,SAAU,YAAW,aAAa;IAI/B,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,IAAI,CAAC,CAAY;IACzB,OAAO,CAAC,KAAK,CAAC,CAAa;gBAEP,OAAO,EAAE,KAAK,CAAC,YAAY;IAE/C,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK;IAQvC,KAAK;CAIR"}
|
package/lib/agent.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.HttpAgent = exports.defaultAgentProvider = void 0;
|
|
27
|
+
const http = __importStar(require("http"));
|
|
28
|
+
const https = __importStar(require("https"));
|
|
29
|
+
exports.defaultAgentProvider = {
|
|
30
|
+
getNativeAgent(url) {
|
|
31
|
+
if (url.startsWith('https://')) {
|
|
32
|
+
return https.globalAgent;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
return http.globalAgent;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
class HttpAgent {
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.options = options;
|
|
42
|
+
}
|
|
43
|
+
getNativeAgent(url) {
|
|
44
|
+
if (url.startsWith('https://')) {
|
|
45
|
+
return this.https || (this.https = new https.Agent(this.options));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
return this.http || (this.http = new http.Agent(this.options));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
close() {
|
|
52
|
+
this.http?.destroy();
|
|
53
|
+
this.https?.destroy();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.HttpAgent = HttpAgent;
|
|
57
|
+
//# sourceMappingURL=agent.js.map
|
package/lib/agent.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA4B;AAC5B,6CAA8B;AAQjB,QAAA,oBAAoB,GAAkB;IAC/C,cAAc,CAAC,GAAW;QACtB,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAC5B,OAAO,KAAK,CAAC,WAAW,CAAA;SAC3B;aAAM;YACH,OAAO,IAAI,CAAC,WAAW,CAAA;SAC1B;IACL,CAAC;CACJ,CAAA;AAGD,MAAa,SAAS;IAIlB,YAAoB,OAA2B;QAA3B,YAAO,GAAP,OAAO,CAAoB;IAAG,CAAC;IAEnD,cAAc,CAAC,GAAW;QACtB,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAC5B,OAAO,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;SACpE;aAAM;YACH,OAAO,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;SACjE;IACL,CAAC;IAED,KAAK;QACD,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAA;QACpB,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,CAAA;IACzB,CAAC;CACJ;AAlBD,8BAkBC"}
|
package/lib/body.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type HttpBody = Content | Json | Nothing;
|
|
2
|
+
interface Content {
|
|
3
|
+
content: string | Uint8Array;
|
|
4
|
+
json?: undefined;
|
|
5
|
+
}
|
|
6
|
+
interface Json {
|
|
7
|
+
content?: undefined;
|
|
8
|
+
json: object;
|
|
9
|
+
}
|
|
10
|
+
interface Nothing {
|
|
11
|
+
content?: undefined;
|
|
12
|
+
json?: undefined;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=body.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,IAAI,GAAG,OAAO,CAAA;AAG/C,UAAU,OAAO;IACb,OAAO,EAAE,MAAM,GAAG,UAAU,CAAA;IAC5B,IAAI,CAAC,EAAE,SAAS,CAAA;CACnB;AAGD,UAAU,IAAI;IACV,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACf;AAGD,UAAU,OAAO;IACb,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;CACnB"}
|
package/lib/body.js
ADDED
package/lib/body.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body.js","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":""}
|
package/lib/client.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { Logger } from '@subsquid/logger';
|
|
2
|
+
import type { Headers, RequestInit, Response } from 'node-fetch';
|
|
3
|
+
import { AgentProvider } from './agent';
|
|
4
|
+
import { HttpBody } from './body';
|
|
5
|
+
export interface HttpClientOptions {
|
|
6
|
+
agent?: AgentProvider;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
headers?: Record<string, string | number | bigint>;
|
|
9
|
+
/**
|
|
10
|
+
* Default request timeout in milliseconds.
|
|
11
|
+
*
|
|
12
|
+
* This timeout is only related to individual http requests.
|
|
13
|
+
* Overall request processing time might be much larger due to retries.
|
|
14
|
+
*/
|
|
15
|
+
httpTimeout?: number;
|
|
16
|
+
retryAttempts?: number;
|
|
17
|
+
retrySchedule?: number[];
|
|
18
|
+
log?: Logger;
|
|
19
|
+
}
|
|
20
|
+
export interface RequestOptions {
|
|
21
|
+
query?: Record<string, string | number | bigint>;
|
|
22
|
+
headers?: HeadersInit;
|
|
23
|
+
retryAttempts?: number;
|
|
24
|
+
retrySchedule?: number[];
|
|
25
|
+
httpTimeout?: number;
|
|
26
|
+
abort?: AbortSignal;
|
|
27
|
+
}
|
|
28
|
+
export interface GraphqlRequestOptions extends RequestOptions {
|
|
29
|
+
variables?: Record<string, any>;
|
|
30
|
+
url?: string;
|
|
31
|
+
method?: 'GET' | 'POST';
|
|
32
|
+
}
|
|
33
|
+
export interface FetchRequest extends RequestInit {
|
|
34
|
+
id: number;
|
|
35
|
+
url: string;
|
|
36
|
+
headers: Headers;
|
|
37
|
+
timeout?: number;
|
|
38
|
+
signal?: AbortSignal;
|
|
39
|
+
}
|
|
40
|
+
export declare class HttpClient {
|
|
41
|
+
protected log?: Logger;
|
|
42
|
+
protected headers?: Record<string, string | number | bigint>;
|
|
43
|
+
private baseUrl?;
|
|
44
|
+
private agent;
|
|
45
|
+
private retrySchedule;
|
|
46
|
+
private retryAttempts;
|
|
47
|
+
private httpTimeout;
|
|
48
|
+
private requestCounter;
|
|
49
|
+
constructor(options?: HttpClientOptions);
|
|
50
|
+
get<T = any>(url: string, options?: RequestOptions): Promise<T>;
|
|
51
|
+
post<T = any>(url: string, options?: RequestOptions & HttpBody): Promise<T>;
|
|
52
|
+
request<T = any>(method: string, url: string, options?: RequestOptions & HttpBody): Promise<HttpResponse<T>>;
|
|
53
|
+
protected beforeRequest(req: FetchRequest): void;
|
|
54
|
+
protected beforeRetryPause(req: FetchRequest, reason: Error | HttpResponse, pause: number): void;
|
|
55
|
+
protected afterResponseHeaders(req: FetchRequest, url: string, status: number, headers: Headers): void;
|
|
56
|
+
protected afterResponse(req: FetchRequest, res: HttpResponse): void;
|
|
57
|
+
protected prepareRequest(method: string, url: string, options: RequestOptions & HttpBody): Promise<FetchRequest>;
|
|
58
|
+
private performRequestWithTimeout;
|
|
59
|
+
private performRequest;
|
|
60
|
+
protected handleResponseBody(req: FetchRequest, res: Response): Promise<any>;
|
|
61
|
+
isRetryableError(error: HttpResponse | Error, req?: FetchRequest): boolean;
|
|
62
|
+
getAbsUrl(url: string): string;
|
|
63
|
+
private setBaseUrl;
|
|
64
|
+
graphqlRequest<T = any>(gql: string, options?: GraphqlRequestOptions): Promise<T>;
|
|
65
|
+
}
|
|
66
|
+
export declare class HttpResponse<T = any> {
|
|
67
|
+
readonly requestId: number;
|
|
68
|
+
readonly url: string;
|
|
69
|
+
readonly status: number;
|
|
70
|
+
readonly headers: Headers;
|
|
71
|
+
readonly body: T;
|
|
72
|
+
constructor(requestId: number, url: string, status: number, headers: Headers, body: T);
|
|
73
|
+
get ok(): boolean;
|
|
74
|
+
assert(): void;
|
|
75
|
+
toJSON(): {
|
|
76
|
+
status: number;
|
|
77
|
+
headers: [string, string][];
|
|
78
|
+
body: T;
|
|
79
|
+
url: string;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export declare class HttpError extends Error {
|
|
83
|
+
readonly response: HttpResponse;
|
|
84
|
+
constructor(response: HttpResponse);
|
|
85
|
+
get name(): string;
|
|
86
|
+
}
|
|
87
|
+
export declare class HttpTimeoutError extends Error {
|
|
88
|
+
constructor(ms: number);
|
|
89
|
+
get name(): string;
|
|
90
|
+
}
|
|
91
|
+
export interface GraphqlMessage {
|
|
92
|
+
message: string;
|
|
93
|
+
path?: (string | number)[];
|
|
94
|
+
}
|
|
95
|
+
export declare class GraphqlError extends Error {
|
|
96
|
+
readonly messages: GraphqlMessage[];
|
|
97
|
+
constructor(messages: GraphqlMessage[]);
|
|
98
|
+
get name(): string;
|
|
99
|
+
}
|
|
100
|
+
export declare function isHttpConnectionError(err: unknown): boolean;
|
|
101
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,kBAAkB,CAAA;AAE5C,OAAO,KAAK,EAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAA;AAC9D,OAAO,EAAC,aAAa,EAAuB,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAC,QAAQ,EAAC,MAAM,QAAQ,CAAA;AAI/B,MAAM,WAAW,iBAAiB;IAC9B,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IAClD;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,CAAA;CACf;AAGD,MAAM,WAAW,cAAc;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IAChD,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,WAAW,CAAA;CACtB;AAGD,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAA;CAC1B;AAGD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC7C,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB;AAGD,qBAAa,UAAU;IACnB,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;IAC5D,OAAO,CAAC,OAAO,CAAC,CAAQ;IACxB,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,cAAc,CAAI;gBAEd,OAAO,GAAE,iBAAsB;IAU3C,GAAG,CAAC,CAAC,GAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAI7D,IAAI,CAAC,CAAC,GAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC;IAInE,OAAO,CAAC,CAAC,GAAC,GAAG,EACf,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,cAAc,GAAG,QAAa,GACxC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IA8B3B,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,GAAG,IAAI;IAYhD,SAAS,CAAC,gBAAgB,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,GAAG,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAoBhG,SAAS,CAAC,oBAAoB,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAWtG,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,GAAG,IAAI;cAenD,cAAc,CAC1B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,cAAc,GAAG,QAAQ,GACnC,OAAO,CAAC,YAAY,CAAC;YAqDV,yBAAyB;YAgCzB,cAAc;cASZ,kBAAkB,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAiBlF,gBAAgB,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,EAAE,GAAG,CAAC,EAAE,YAAY,GAAG,OAAO;IAiB1E,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAQ9B,OAAO,CAAC,UAAU;IAeZ,cAAc,CAAC,CAAC,GAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,CAAC,CAAC;CAwB5F;AAGD,qBAAa,YAAY,CAAC,CAAC,GAAC,GAAG;aAEP,SAAS,EAAE,MAAM;aACjB,GAAG,EAAE,MAAM;aACX,MAAM,EAAE,MAAM;aACd,OAAO,EAAE,OAAO;aAChB,IAAI,EAAE,CAAC;gBAJP,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,CAAC;IAI3B,IAAI,EAAE,IAAI,OAAO,CAEhB;IAED,MAAM,IAAI,IAAI;IAKd,MAAM;;;;;;CAQT;AAGD,qBAAa,SAAU,SAAQ,KAAK;aACJ,QAAQ,EAAE,YAAY;gBAAtB,QAAQ,EAAE,YAAY;IAIlD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACJ;AAGD,qBAAa,gBAAiB,SAAQ,KAAK;gBAC3B,EAAE,EAAE,MAAM;IAItB,IAAI,IAAI,IAAI,MAAM,CAEjB;CACJ;AAGD,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;CAC7B;AAGD,qBAAa,YAAa,SAAQ,KAAK;aACP,QAAQ,EAAE,cAAc,EAAE;gBAA1B,QAAQ,EAAE,cAAc,EAAE;IAItD,IAAI,IAAI,IAAI,MAAM,CAEjB;CACJ;AAGD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAI3D"}
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isHttpConnectionError = exports.GraphqlError = exports.HttpTimeoutError = exports.HttpError = exports.HttpResponse = exports.HttpClient = void 0;
|
|
4
|
+
const util_internal_1 = require("@subsquid/util-internal");
|
|
5
|
+
const agent_1 = require("./agent");
|
|
6
|
+
const request_1 = require("./request");
|
|
7
|
+
class HttpClient {
|
|
8
|
+
constructor(options = {}) {
|
|
9
|
+
this.requestCounter = 0;
|
|
10
|
+
this.log = options.log;
|
|
11
|
+
this.headers = options.headers;
|
|
12
|
+
this.setBaseUrl(options.baseUrl);
|
|
13
|
+
this.agent = options.agent || agent_1.defaultAgentProvider;
|
|
14
|
+
this.retrySchedule = options.retrySchedule || [10, 100, 500, 2000, 10000, 20000];
|
|
15
|
+
this.retryAttempts = options.retryAttempts || 0;
|
|
16
|
+
this.httpTimeout = options.httpTimeout ?? 20000;
|
|
17
|
+
}
|
|
18
|
+
get(url, options) {
|
|
19
|
+
return this.request('GET', url, options).then(res => res.body);
|
|
20
|
+
}
|
|
21
|
+
post(url, options) {
|
|
22
|
+
return this.request('POST', url, options).then(res => res.body);
|
|
23
|
+
}
|
|
24
|
+
async request(method, url, options = {}) {
|
|
25
|
+
let req = await this.prepareRequest(method, url, options);
|
|
26
|
+
this.beforeRequest(req);
|
|
27
|
+
let retryAttempts = options.retryAttempts ?? this.retryAttempts;
|
|
28
|
+
let retrySchedule = options.retrySchedule ?? this.retrySchedule;
|
|
29
|
+
let retries = 0;
|
|
30
|
+
while (true) {
|
|
31
|
+
let res = await this.performRequestWithTimeout(req).catch(util_internal_1.ensureError);
|
|
32
|
+
if (res instanceof Error || !res.ok) {
|
|
33
|
+
if (retryAttempts > retries && this.isRetryableError(res, req)) {
|
|
34
|
+
let pause = retrySchedule.length
|
|
35
|
+
? retrySchedule[Math.min(retries, retrySchedule.length - 1)]
|
|
36
|
+
: 1000;
|
|
37
|
+
retries += 1;
|
|
38
|
+
this.beforeRetryPause(req, res, pause);
|
|
39
|
+
await (0, util_internal_1.wait)(pause, req.signal);
|
|
40
|
+
}
|
|
41
|
+
else if (res instanceof Error) {
|
|
42
|
+
throw (0, util_internal_1.addErrorContext)(res, { httpRequestId: req.id });
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
throw new HttpError(res);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
return res;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
beforeRequest(req) {
|
|
54
|
+
if (this.log?.isDebug()) {
|
|
55
|
+
this.log.debug({
|
|
56
|
+
httpRequestId: req.id,
|
|
57
|
+
httpRequestUrl: req.url,
|
|
58
|
+
httpRequestMethod: req.method,
|
|
59
|
+
httpRequestHeaders: Array.from(req.headers),
|
|
60
|
+
httpRequestBody: req.body
|
|
61
|
+
}, 'http request');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
beforeRetryPause(req, reason, pause) {
|
|
65
|
+
if (this.log?.isWarn()) {
|
|
66
|
+
let info = {
|
|
67
|
+
httpRequestId: req.id,
|
|
68
|
+
httpRequestUrl: req.url,
|
|
69
|
+
httpRequestMethod: req.method
|
|
70
|
+
};
|
|
71
|
+
if (reason instanceof Error) {
|
|
72
|
+
info.reason = reason.toString();
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
info.reason = `got ${reason.status}`;
|
|
76
|
+
info.httpResponseUrl = reason.url;
|
|
77
|
+
info.httpResponseStatus = reason.status;
|
|
78
|
+
info.httpResponseHeaders = Array.from(reason.headers);
|
|
79
|
+
info.httpResponseBody = reason.body;
|
|
80
|
+
}
|
|
81
|
+
this.log.warn(info, `request will be retried in ${pause} ms`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
afterResponseHeaders(req, url, status, headers) {
|
|
85
|
+
if (this.log?.isDebug()) {
|
|
86
|
+
this.log.debug({
|
|
87
|
+
httpRequestId: req.id,
|
|
88
|
+
httpResponseUrl: url,
|
|
89
|
+
httpResponseStatus: status,
|
|
90
|
+
httpResponseHeaders: headers
|
|
91
|
+
}, 'http headers');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
afterResponse(req, res) {
|
|
95
|
+
if (this.log?.isDebug()) {
|
|
96
|
+
let httpResponseBody = res.body;
|
|
97
|
+
if (typeof res.body == 'string' || res.body instanceof Uint8Array) {
|
|
98
|
+
if (res.body.length > 1024 * 1024) {
|
|
99
|
+
httpResponseBody = '...body is too long to be logged';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
this.log.debug({
|
|
103
|
+
httpRequestId: req.id,
|
|
104
|
+
httpResponseBody
|
|
105
|
+
}, 'http body');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
async prepareRequest(method, url, options) {
|
|
109
|
+
await request_1.nodeFetch.load();
|
|
110
|
+
let req = {
|
|
111
|
+
id: this.requestCounter++,
|
|
112
|
+
method,
|
|
113
|
+
headers: new request_1.nodeFetch.Headers(options.headers),
|
|
114
|
+
url: this.getAbsUrl(url),
|
|
115
|
+
signal: options.abort,
|
|
116
|
+
compress: true,
|
|
117
|
+
timeout: options.httpTimeout ?? this.httpTimeout
|
|
118
|
+
};
|
|
119
|
+
if (options.query) {
|
|
120
|
+
let qs = new URLSearchParams(options.query).toString();
|
|
121
|
+
if (req.url.includes('?')) {
|
|
122
|
+
req.url += '&' + qs;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
req.url += '?' + qs;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
req.agent = this.agent.getNativeAgent(req.url);
|
|
129
|
+
if (options.content !== undefined) {
|
|
130
|
+
if (typeof options.content == 'string') {
|
|
131
|
+
req.body = options.content;
|
|
132
|
+
if (!req.headers.has('content-type')) {
|
|
133
|
+
req.headers.set('content-type', 'text/plain');
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else if (Buffer.isBuffer(options.content)) {
|
|
137
|
+
req.body = options.content;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
req.body = Buffer.from(options.content.buffer, options.content.byteOffset, options.content.byteLength);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (options.json !== undefined) {
|
|
144
|
+
req.body = JSON.stringify(options.json);
|
|
145
|
+
if (!req.headers.has('content-type')) {
|
|
146
|
+
req.headers.set('content-type', 'application/json');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (let name in this.headers) {
|
|
150
|
+
if (!req.headers.has(name)) {
|
|
151
|
+
req.headers.set(name, '' + this.headers[name]);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return req;
|
|
155
|
+
}
|
|
156
|
+
async performRequestWithTimeout(req) {
|
|
157
|
+
if (!req.timeout)
|
|
158
|
+
return this.performRequest(req);
|
|
159
|
+
let ac = new AbortController();
|
|
160
|
+
function abort() {
|
|
161
|
+
ac.abort();
|
|
162
|
+
}
|
|
163
|
+
req.signal?.addEventListener('abort', abort);
|
|
164
|
+
let timer = setTimeout(() => {
|
|
165
|
+
timer = null;
|
|
166
|
+
abort();
|
|
167
|
+
}, req.timeout);
|
|
168
|
+
try {
|
|
169
|
+
return await this.performRequest({ ...req, signal: ac.signal });
|
|
170
|
+
}
|
|
171
|
+
catch (err) {
|
|
172
|
+
if (timer == null) {
|
|
173
|
+
throw new HttpTimeoutError(req.timeout);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
throw err;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
if (timer != null) {
|
|
181
|
+
clearTimeout(timer);
|
|
182
|
+
}
|
|
183
|
+
req.signal?.removeEventListener('abort', abort);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
async performRequest(req) {
|
|
187
|
+
let res = await request_1.nodeFetch.request(req.url, req);
|
|
188
|
+
this.afterResponseHeaders(req, res.url, res.status, res.headers);
|
|
189
|
+
let body = await this.handleResponseBody(req, res);
|
|
190
|
+
let httpResponse = new HttpResponse(req.id, res.url, res.status, res.headers, body);
|
|
191
|
+
this.afterResponse(req, httpResponse);
|
|
192
|
+
return httpResponse;
|
|
193
|
+
}
|
|
194
|
+
async handleResponseBody(req, res) {
|
|
195
|
+
let contentType = (res.headers.get('content-type') || '').split(';')[0];
|
|
196
|
+
if (contentType == 'application/json') {
|
|
197
|
+
return res.json();
|
|
198
|
+
}
|
|
199
|
+
if (contentType.startsWith('text/')) {
|
|
200
|
+
return res.text();
|
|
201
|
+
}
|
|
202
|
+
let arrayBuffer = await res.arrayBuffer();
|
|
203
|
+
let bytes = Buffer.from(arrayBuffer);
|
|
204
|
+
if (bytes.length == 0)
|
|
205
|
+
return undefined;
|
|
206
|
+
return bytes;
|
|
207
|
+
}
|
|
208
|
+
isRetryableError(error, req) {
|
|
209
|
+
if (isHttpConnectionError(error))
|
|
210
|
+
return true;
|
|
211
|
+
if (error instanceof HttpTimeoutError)
|
|
212
|
+
return true;
|
|
213
|
+
if (error instanceof HttpResponse) {
|
|
214
|
+
switch (error.status) {
|
|
215
|
+
case 429:
|
|
216
|
+
case 502:
|
|
217
|
+
case 503:
|
|
218
|
+
case 504:
|
|
219
|
+
return true;
|
|
220
|
+
default:
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
getAbsUrl(url) {
|
|
227
|
+
if (!this.baseUrl)
|
|
228
|
+
return url;
|
|
229
|
+
if (url.includes('://'))
|
|
230
|
+
return url;
|
|
231
|
+
if (url == '/')
|
|
232
|
+
return this.baseUrl;
|
|
233
|
+
if (url[0] == '/')
|
|
234
|
+
return this.baseUrl + url;
|
|
235
|
+
return this.baseUrl + '/' + url;
|
|
236
|
+
}
|
|
237
|
+
setBaseUrl(url) {
|
|
238
|
+
if (url) {
|
|
239
|
+
let u = new URL(url);
|
|
240
|
+
u.hash = '';
|
|
241
|
+
u.search = '';
|
|
242
|
+
url = u.toString();
|
|
243
|
+
if (url.endsWith('/')) {
|
|
244
|
+
url = url.slice(0, url.length - 1);
|
|
245
|
+
}
|
|
246
|
+
this.baseUrl = url;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
this.baseUrl = undefined;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async graphqlRequest(gql, options = {}) {
|
|
253
|
+
let { method = 'POST', url = '/', variables, ...reqOptions } = options;
|
|
254
|
+
let req = reqOptions;
|
|
255
|
+
if (method == 'GET') {
|
|
256
|
+
req.query = {
|
|
257
|
+
...req.query,
|
|
258
|
+
query: gql,
|
|
259
|
+
};
|
|
260
|
+
if (variables) {
|
|
261
|
+
req.query.variables = JSON.stringify(variables);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
req.json = {
|
|
266
|
+
query: gql,
|
|
267
|
+
variables
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
let res = await this.request(method, url, req);
|
|
271
|
+
if (res.body.errors?.length) {
|
|
272
|
+
throw new GraphqlError(res.body.errors);
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
return res.body.data;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
exports.HttpClient = HttpClient;
|
|
280
|
+
class HttpResponse {
|
|
281
|
+
constructor(requestId, url, status, headers, body) {
|
|
282
|
+
this.requestId = requestId;
|
|
283
|
+
this.url = url;
|
|
284
|
+
this.status = status;
|
|
285
|
+
this.headers = headers;
|
|
286
|
+
this.body = body;
|
|
287
|
+
}
|
|
288
|
+
get ok() {
|
|
289
|
+
return this.status >= 200 && this.status < 300;
|
|
290
|
+
}
|
|
291
|
+
assert() {
|
|
292
|
+
if (this.ok)
|
|
293
|
+
return;
|
|
294
|
+
throw new HttpError(this);
|
|
295
|
+
}
|
|
296
|
+
toJSON() {
|
|
297
|
+
return {
|
|
298
|
+
status: this.status,
|
|
299
|
+
headers: Array.from(this.headers),
|
|
300
|
+
body: this.body,
|
|
301
|
+
url: this.url
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
exports.HttpResponse = HttpResponse;
|
|
306
|
+
class HttpError extends Error {
|
|
307
|
+
constructor(response) {
|
|
308
|
+
super(`Got ${response.status} from ${response.url}`);
|
|
309
|
+
this.response = response;
|
|
310
|
+
}
|
|
311
|
+
get name() {
|
|
312
|
+
return 'HttpError';
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
exports.HttpError = HttpError;
|
|
316
|
+
class HttpTimeoutError extends Error {
|
|
317
|
+
constructor(ms) {
|
|
318
|
+
super(`request timed out after ${ms} ms`);
|
|
319
|
+
}
|
|
320
|
+
get name() {
|
|
321
|
+
return 'HttpTimeoutError';
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
exports.HttpTimeoutError = HttpTimeoutError;
|
|
325
|
+
class GraphqlError extends Error {
|
|
326
|
+
constructor(messages) {
|
|
327
|
+
super(`GraphQL error: ${messages[0].message}`);
|
|
328
|
+
this.messages = messages;
|
|
329
|
+
}
|
|
330
|
+
get name() {
|
|
331
|
+
return 'GraphqlError';
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
exports.GraphqlError = GraphqlError;
|
|
335
|
+
function isHttpConnectionError(err) {
|
|
336
|
+
return err instanceof request_1.nodeFetch.FetchError
|
|
337
|
+
&& err.type == 'system'
|
|
338
|
+
&& (err.message.startsWith('request to') || err.code == 'ERR_STREAM_PREMATURE_CLOSE');
|
|
339
|
+
}
|
|
340
|
+
exports.isHttpConnectionError = isHttpConnectionError;
|
|
341
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,OAAO,EAAC,aAAa,EAAE,SAAS,EAAC,MAAM,SAAS,CAAA"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.HttpAgent = void 0;
|
|
18
|
+
__exportStar(require("./client"), exports);
|
|
19
|
+
var agent_1 = require("./agent");
|
|
20
|
+
Object.defineProperty(exports, "HttpAgent", { enumerable: true, get: function () { return agent_1.HttpAgent; } });
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2CAAwB;AACxB,iCAAgD;AAAzB,kGAAA,SAAS,OAAA"}
|
package/lib/request.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RequestInit, Response } from 'node-fetch';
|
|
2
|
+
export declare const nodeFetch: {
|
|
3
|
+
load(): Promise<typeof import('node-fetch')>;
|
|
4
|
+
readonly Headers: typeof import("node-fetch").Headers;
|
|
5
|
+
readonly FetchError: typeof import("node-fetch").FetchError;
|
|
6
|
+
request(url: string, init?: RequestInit): Promise<Response>;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,WAAW,EAAE,QAAQ,EAAC,MAAM,YAAY,CAAA;AAOrD,eAAO,MAAM,SAAS;YACJ,QAAQ,cAAc,YAAY,CAAC,CAAC;;;iBAY/B,MAAM,SAAS,WAAW,GAAG,QAAQ,QAAQ,CAAC;CAIpE,CAAA"}
|
package/lib/request.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
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
|
+
exports.nodeFetch = void 0;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const esm_1 = require("../esm");
|
|
9
|
+
let mod;
|
|
10
|
+
exports.nodeFetch = {
|
|
11
|
+
async load() {
|
|
12
|
+
if (mod)
|
|
13
|
+
return mod;
|
|
14
|
+
return mod = await (0, esm_1.esm)('node-fetch');
|
|
15
|
+
},
|
|
16
|
+
get Headers() {
|
|
17
|
+
(0, assert_1.default)(mod, 'node-fetch ESM is not loaded');
|
|
18
|
+
return mod.Headers;
|
|
19
|
+
},
|
|
20
|
+
get FetchError() {
|
|
21
|
+
(0, assert_1.default)(mod, 'node-fetch ESM is not loaded');
|
|
22
|
+
return mod.FetchError;
|
|
23
|
+
},
|
|
24
|
+
async request(url, init) {
|
|
25
|
+
let m = await exports.nodeFetch.load();
|
|
26
|
+
return m.default(url, init);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../src/request.ts"],"names":[],"mappings":";;;;;;AAAA,oDAA2B;AAE3B,gCAA0B;AAG1B,IAAI,GAA4C,CAAA;AAGnC,QAAA,SAAS,GAAG;IACrB,KAAK,CAAC,IAAI;QACN,IAAI,GAAG;YAAE,OAAO,GAAG,CAAA;QACnB,OAAO,GAAG,GAAG,MAAM,IAAA,SAAG,EAA+B,YAAY,CAAC,CAAA;IACtE,CAAC;IACD,IAAI,OAAO;QACP,IAAA,gBAAM,EAAC,GAAG,EAAE,8BAA8B,CAAC,CAAA;QAC3C,OAAO,GAAG,CAAC,OAAO,CAAA;IACtB,CAAC;IACD,IAAI,UAAU;QACV,IAAA,gBAAM,EAAC,GAAG,EAAE,8BAA8B,CAAC,CAAA;QAC3C,OAAO,GAAG,CAAC,UAAU,CAAA;IACzB,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,IAAkB;QACzC,IAAI,CAAC,GAAG,MAAM,iBAAS,CAAC,IAAI,EAAE,CAAA;QAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;IAC/B,CAAC;CACJ,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@subsquid/http-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Small convenience layer on top of fetch",
|
|
5
|
+
"license": "GPL-3.0-or-later",
|
|
6
|
+
"repository": "git@github.com:subsquid/squid.git",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"main": "lib/index.js",
|
|
11
|
+
"files": [
|
|
12
|
+
"lib",
|
|
13
|
+
"src",
|
|
14
|
+
"esm.d.ts",
|
|
15
|
+
"esm.js"
|
|
16
|
+
],
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@subsquid/logger": "^1.0.0",
|
|
19
|
+
"@subsquid/util-internal": "^2.0.0",
|
|
20
|
+
"node-fetch": "^3.3.1"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^16.18.25",
|
|
24
|
+
"typescript": "~4.9.5"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "rm -rf lib && tsc"
|
|
28
|
+
},
|
|
29
|
+
"readme": "# @subsquid/util-internal-http-client\n\nA small convenience layer on top of `fetch()` which adds\n\n* `HttpClient` as a store for common request settings\n* retries\n* timeouts\n* logging.\n"
|
|
30
|
+
}
|
package/src/agent.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as http from 'http'
|
|
2
|
+
import * as https from 'https'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
export interface AgentProvider {
|
|
6
|
+
getNativeAgent(url: string): http.Agent
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export const defaultAgentProvider: AgentProvider = {
|
|
11
|
+
getNativeAgent(url: string): http.Agent {
|
|
12
|
+
if (url.startsWith('https://')) {
|
|
13
|
+
return https.globalAgent
|
|
14
|
+
} else {
|
|
15
|
+
return http.globalAgent
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
export class HttpAgent implements AgentProvider {
|
|
22
|
+
private http?: http.Agent
|
|
23
|
+
private https?: https.Agent
|
|
24
|
+
|
|
25
|
+
constructor(private options: https.AgentOptions) {}
|
|
26
|
+
|
|
27
|
+
getNativeAgent(url: string): http.Agent {
|
|
28
|
+
if (url.startsWith('https://')) {
|
|
29
|
+
return this.https || (this.https = new https.Agent(this.options))
|
|
30
|
+
} else {
|
|
31
|
+
return this.http || (this.http = new http.Agent(this.options))
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
close() {
|
|
36
|
+
this.http?.destroy()
|
|
37
|
+
this.https?.destroy()
|
|
38
|
+
}
|
|
39
|
+
}
|
package/src/body.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
export type HttpBody = Content | Json | Nothing
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
interface Content {
|
|
6
|
+
content: string | Uint8Array
|
|
7
|
+
json?: undefined
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
interface Json {
|
|
12
|
+
content?: undefined
|
|
13
|
+
json: object
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
interface Nothing {
|
|
18
|
+
content?: undefined
|
|
19
|
+
json?: undefined
|
|
20
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
import type {Logger} from '@subsquid/logger'
|
|
2
|
+
import {addErrorContext, ensureError, wait} from '@subsquid/util-internal'
|
|
3
|
+
import type {Headers, RequestInit, Response} from 'node-fetch'
|
|
4
|
+
import {AgentProvider, defaultAgentProvider} from './agent'
|
|
5
|
+
import {HttpBody} from './body'
|
|
6
|
+
import {nodeFetch} from './request'
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export interface HttpClientOptions {
|
|
10
|
+
agent?: AgentProvider
|
|
11
|
+
baseUrl?: string
|
|
12
|
+
headers?: Record<string, string | number | bigint>
|
|
13
|
+
/**
|
|
14
|
+
* Default request timeout in milliseconds.
|
|
15
|
+
*
|
|
16
|
+
* This timeout is only related to individual http requests.
|
|
17
|
+
* Overall request processing time might be much larger due to retries.
|
|
18
|
+
*/
|
|
19
|
+
httpTimeout?: number
|
|
20
|
+
retryAttempts?: number
|
|
21
|
+
retrySchedule?: number[]
|
|
22
|
+
log?: Logger
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export interface RequestOptions {
|
|
27
|
+
query?: Record<string, string | number | bigint>
|
|
28
|
+
headers?: HeadersInit
|
|
29
|
+
retryAttempts?: number
|
|
30
|
+
retrySchedule?: number[]
|
|
31
|
+
httpTimeout?: number
|
|
32
|
+
abort?: AbortSignal
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
export interface GraphqlRequestOptions extends RequestOptions {
|
|
37
|
+
variables?: Record<string, any>
|
|
38
|
+
url?: string
|
|
39
|
+
method?: 'GET' | 'POST'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
export interface FetchRequest extends RequestInit {
|
|
44
|
+
id: number
|
|
45
|
+
url: string
|
|
46
|
+
headers: Headers
|
|
47
|
+
timeout?: number
|
|
48
|
+
signal?: AbortSignal
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
export class HttpClient {
|
|
53
|
+
protected log?: Logger
|
|
54
|
+
protected headers?: Record<string, string | number | bigint>
|
|
55
|
+
private baseUrl?: string
|
|
56
|
+
private agent: AgentProvider
|
|
57
|
+
private retrySchedule: number[]
|
|
58
|
+
private retryAttempts: number
|
|
59
|
+
private httpTimeout: number
|
|
60
|
+
private requestCounter = 0
|
|
61
|
+
|
|
62
|
+
constructor(options: HttpClientOptions = {}) {
|
|
63
|
+
this.log = options.log
|
|
64
|
+
this.headers = options.headers
|
|
65
|
+
this.setBaseUrl(options.baseUrl)
|
|
66
|
+
this.agent = options.agent || defaultAgentProvider
|
|
67
|
+
this.retrySchedule = options.retrySchedule || [10, 100, 500, 2000, 10000, 20000]
|
|
68
|
+
this.retryAttempts = options.retryAttempts || 0
|
|
69
|
+
this.httpTimeout = options.httpTimeout ?? 20000
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get<T=any>(url: string, options?: RequestOptions): Promise<T> {
|
|
73
|
+
return this.request('GET', url, options).then(res => res.body)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
post<T=any>(url: string, options?: RequestOptions & HttpBody): Promise<T> {
|
|
77
|
+
return this.request('POST', url, options).then(res => res.body)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async request<T=any>(
|
|
81
|
+
method: string,
|
|
82
|
+
url: string,
|
|
83
|
+
options: RequestOptions & HttpBody = {},
|
|
84
|
+
): Promise<HttpResponse<T>> {
|
|
85
|
+
let req = await this.prepareRequest(method, url, options)
|
|
86
|
+
|
|
87
|
+
this.beforeRequest(req)
|
|
88
|
+
|
|
89
|
+
let retryAttempts = options.retryAttempts ?? this.retryAttempts
|
|
90
|
+
let retrySchedule = options.retrySchedule ?? this.retrySchedule
|
|
91
|
+
let retries = 0
|
|
92
|
+
|
|
93
|
+
while (true) {
|
|
94
|
+
let res: HttpResponse | Error = await this.performRequestWithTimeout(req).catch(ensureError)
|
|
95
|
+
if (res instanceof Error || !res.ok) {
|
|
96
|
+
if (retryAttempts > retries && this.isRetryableError(res, req)) {
|
|
97
|
+
let pause = retrySchedule.length
|
|
98
|
+
? retrySchedule[Math.min(retries, retrySchedule.length - 1)]
|
|
99
|
+
: 1000
|
|
100
|
+
retries += 1
|
|
101
|
+
this.beforeRetryPause(req, res, pause)
|
|
102
|
+
await wait(pause, req.signal)
|
|
103
|
+
} else if (res instanceof Error) {
|
|
104
|
+
throw addErrorContext(res, {httpRequestId: req.id})
|
|
105
|
+
} else {
|
|
106
|
+
throw new HttpError(res)
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
return res
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
protected beforeRequest(req: FetchRequest): void {
|
|
115
|
+
if (this.log?.isDebug()) {
|
|
116
|
+
this.log.debug({
|
|
117
|
+
httpRequestId: req.id,
|
|
118
|
+
httpRequestUrl: req.url,
|
|
119
|
+
httpRequestMethod: req.method,
|
|
120
|
+
httpRequestHeaders: Array.from(req.headers),
|
|
121
|
+
httpRequestBody: req.body
|
|
122
|
+
}, 'http request')
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
protected beforeRetryPause(req: FetchRequest, reason: Error | HttpResponse, pause: number): void {
|
|
127
|
+
if (this.log?.isWarn()) {
|
|
128
|
+
let info: any = {
|
|
129
|
+
httpRequestId: req.id,
|
|
130
|
+
httpRequestUrl: req.url,
|
|
131
|
+
httpRequestMethod: req.method
|
|
132
|
+
}
|
|
133
|
+
if (reason instanceof Error) {
|
|
134
|
+
info.reason = reason.toString()
|
|
135
|
+
} else {
|
|
136
|
+
info.reason = `got ${reason.status}`
|
|
137
|
+
info.httpResponseUrl = reason.url
|
|
138
|
+
info.httpResponseStatus = reason.status
|
|
139
|
+
info.httpResponseHeaders = Array.from(reason.headers)
|
|
140
|
+
info.httpResponseBody = reason.body
|
|
141
|
+
}
|
|
142
|
+
this.log.warn(info, `request will be retried in ${pause} ms`)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
protected afterResponseHeaders(req: FetchRequest, url: string, status: number, headers: Headers): void {
|
|
147
|
+
if (this.log?.isDebug()) {
|
|
148
|
+
this.log.debug({
|
|
149
|
+
httpRequestId: req.id,
|
|
150
|
+
httpResponseUrl: url,
|
|
151
|
+
httpResponseStatus: status,
|
|
152
|
+
httpResponseHeaders: headers
|
|
153
|
+
}, 'http headers')
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
protected afterResponse(req: FetchRequest, res: HttpResponse): void {
|
|
158
|
+
if (this.log?.isDebug()) {
|
|
159
|
+
let httpResponseBody: any = res.body
|
|
160
|
+
if (typeof res.body == 'string' || res.body instanceof Uint8Array) {
|
|
161
|
+
if (res.body.length > 1024 * 1024) {
|
|
162
|
+
httpResponseBody = '...body is too long to be logged'
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
this.log.debug({
|
|
166
|
+
httpRequestId: req.id,
|
|
167
|
+
httpResponseBody
|
|
168
|
+
}, 'http body')
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
protected async prepareRequest(
|
|
173
|
+
method: string,
|
|
174
|
+
url: string,
|
|
175
|
+
options: RequestOptions & HttpBody
|
|
176
|
+
): Promise<FetchRequest> {
|
|
177
|
+
await nodeFetch.load()
|
|
178
|
+
|
|
179
|
+
let req: FetchRequest = {
|
|
180
|
+
id: this.requestCounter++,
|
|
181
|
+
method,
|
|
182
|
+
headers: new nodeFetch.Headers(options.headers),
|
|
183
|
+
url: this.getAbsUrl(url),
|
|
184
|
+
signal: options.abort,
|
|
185
|
+
compress: true,
|
|
186
|
+
timeout: options.httpTimeout ?? this.httpTimeout
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (options.query) {
|
|
190
|
+
let qs = new URLSearchParams(options.query as any).toString()
|
|
191
|
+
if (req.url.includes('?')) {
|
|
192
|
+
req.url += '&' + qs
|
|
193
|
+
} else {
|
|
194
|
+
req.url += '?' + qs
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
req.agent = this.agent.getNativeAgent(req.url)
|
|
199
|
+
|
|
200
|
+
if (options.content !== undefined) {
|
|
201
|
+
if (typeof options.content == 'string') {
|
|
202
|
+
req.body = options.content
|
|
203
|
+
if (!req.headers.has('content-type')) {
|
|
204
|
+
req.headers.set('content-type', 'text/plain')
|
|
205
|
+
}
|
|
206
|
+
} else if (Buffer.isBuffer(options.content)) {
|
|
207
|
+
req.body = options.content
|
|
208
|
+
} else {
|
|
209
|
+
req.body = Buffer.from(options.content.buffer, options.content.byteOffset, options.content.byteLength)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (options.json !== undefined) {
|
|
214
|
+
req.body = JSON.stringify(options.json)
|
|
215
|
+
if (!req.headers.has('content-type')) {
|
|
216
|
+
req.headers.set('content-type', 'application/json')
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
for (let name in this.headers) {
|
|
221
|
+
if (!req.headers.has(name)) {
|
|
222
|
+
req.headers.set(name, ''+this.headers[name])
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return req
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private async performRequestWithTimeout(req: FetchRequest): Promise<HttpResponse> {
|
|
230
|
+
if (!req.timeout) return this.performRequest(req)
|
|
231
|
+
|
|
232
|
+
let ac = new AbortController()
|
|
233
|
+
|
|
234
|
+
function abort() {
|
|
235
|
+
ac.abort()
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
req.signal?.addEventListener('abort', abort)
|
|
239
|
+
|
|
240
|
+
let timer: any | null = setTimeout(() => {
|
|
241
|
+
timer = null
|
|
242
|
+
abort()
|
|
243
|
+
}, req.timeout)
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
return await this.performRequest({...req, signal: ac.signal})
|
|
247
|
+
} catch(err: any) {
|
|
248
|
+
if (timer == null) {
|
|
249
|
+
throw new HttpTimeoutError(req.timeout)
|
|
250
|
+
} else {
|
|
251
|
+
throw err
|
|
252
|
+
}
|
|
253
|
+
} finally {
|
|
254
|
+
if (timer != null) {
|
|
255
|
+
clearTimeout(timer)
|
|
256
|
+
}
|
|
257
|
+
req.signal?.removeEventListener('abort', abort)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private async performRequest(req: FetchRequest): Promise<HttpResponse> {
|
|
262
|
+
let res = await nodeFetch.request(req.url, req)
|
|
263
|
+
this.afterResponseHeaders(req, res.url, res.status, res.headers)
|
|
264
|
+
let body = await this.handleResponseBody(req, res)
|
|
265
|
+
let httpResponse = new HttpResponse(req.id, res.url, res.status, res.headers, body)
|
|
266
|
+
this.afterResponse(req, httpResponse)
|
|
267
|
+
return httpResponse
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
protected async handleResponseBody(req: FetchRequest, res: Response): Promise<any> {
|
|
271
|
+
let contentType = (res.headers.get('content-type') || '').split(';')[0]
|
|
272
|
+
|
|
273
|
+
if (contentType == 'application/json') {
|
|
274
|
+
return res.json()
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (contentType.startsWith('text/')) {
|
|
278
|
+
return res.text()
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
let arrayBuffer = await res.arrayBuffer()
|
|
282
|
+
let bytes = Buffer.from(arrayBuffer)
|
|
283
|
+
if (bytes.length == 0) return undefined
|
|
284
|
+
return bytes
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
isRetryableError(error: HttpResponse | Error, req?: FetchRequest): boolean {
|
|
288
|
+
if (isHttpConnectionError(error)) return true
|
|
289
|
+
if (error instanceof HttpTimeoutError) return true
|
|
290
|
+
if (error instanceof HttpResponse) {
|
|
291
|
+
switch(error.status) {
|
|
292
|
+
case 429:
|
|
293
|
+
case 502:
|
|
294
|
+
case 503:
|
|
295
|
+
case 504:
|
|
296
|
+
return true
|
|
297
|
+
default:
|
|
298
|
+
return false
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return false
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
getAbsUrl(url: string): string {
|
|
305
|
+
if (!this.baseUrl) return url
|
|
306
|
+
if (url.includes('://')) return url
|
|
307
|
+
if (url == '/') return this.baseUrl
|
|
308
|
+
if (url[0] == '/') return this.baseUrl + url
|
|
309
|
+
return this.baseUrl + '/' + url
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private setBaseUrl(url?: string): void {
|
|
313
|
+
if (url) {
|
|
314
|
+
let u = new URL(url)
|
|
315
|
+
u.hash = ''
|
|
316
|
+
u.search = ''
|
|
317
|
+
url = u.toString()
|
|
318
|
+
if (url.endsWith('/')) {
|
|
319
|
+
url = url.slice(0, url.length - 1)
|
|
320
|
+
}
|
|
321
|
+
this.baseUrl = url
|
|
322
|
+
} else {
|
|
323
|
+
this.baseUrl = undefined
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
async graphqlRequest<T=any>(gql: string, options: GraphqlRequestOptions = {}): Promise<T> {
|
|
328
|
+
let {method = 'POST', url = '/', variables, ...reqOptions} = options
|
|
329
|
+
let req: RequestOptions & {json?: any} = reqOptions
|
|
330
|
+
if (method == 'GET') {
|
|
331
|
+
req.query = {
|
|
332
|
+
...req.query,
|
|
333
|
+
query: gql,
|
|
334
|
+
}
|
|
335
|
+
if (variables) {
|
|
336
|
+
req.query.variables = JSON.stringify(variables)
|
|
337
|
+
}
|
|
338
|
+
} else {
|
|
339
|
+
req.json = {
|
|
340
|
+
query: gql,
|
|
341
|
+
variables
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
let res = await this.request<{data: T, errors?: GraphqlMessage[]}>(method, url, req)
|
|
345
|
+
if (res.body.errors?.length) {
|
|
346
|
+
throw new GraphqlError(res.body.errors)
|
|
347
|
+
} else {
|
|
348
|
+
return res.body.data
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
export class HttpResponse<T=any> {
|
|
355
|
+
constructor(
|
|
356
|
+
public readonly requestId: number,
|
|
357
|
+
public readonly url: string,
|
|
358
|
+
public readonly status: number,
|
|
359
|
+
public readonly headers: Headers,
|
|
360
|
+
public readonly body: T
|
|
361
|
+
) {
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
get ok(): boolean {
|
|
365
|
+
return this.status >= 200 && this.status < 300
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
assert(): void {
|
|
369
|
+
if (this.ok) return
|
|
370
|
+
throw new HttpError(this)
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
toJSON() {
|
|
374
|
+
return {
|
|
375
|
+
status: this.status,
|
|
376
|
+
headers: Array.from(this.headers),
|
|
377
|
+
body: this.body,
|
|
378
|
+
url: this.url
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
export class HttpError extends Error {
|
|
385
|
+
constructor(public readonly response: HttpResponse) {
|
|
386
|
+
super(`Got ${response.status} from ${response.url}`)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
get name(): string {
|
|
390
|
+
return 'HttpError'
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
export class HttpTimeoutError extends Error {
|
|
396
|
+
constructor(ms: number) {
|
|
397
|
+
super(`request timed out after ${ms} ms`)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
get name(): string {
|
|
401
|
+
return 'HttpTimeoutError'
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
export interface GraphqlMessage {
|
|
407
|
+
message: string
|
|
408
|
+
path?: (string | number)[]
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
export class GraphqlError extends Error {
|
|
413
|
+
constructor(public readonly messages: GraphqlMessage[]) {
|
|
414
|
+
super(`GraphQL error: ${messages[0].message}`)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
get name(): string {
|
|
418
|
+
return 'GraphqlError'
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
export function isHttpConnectionError(err: unknown): boolean {
|
|
424
|
+
return err instanceof nodeFetch.FetchError
|
|
425
|
+
&& err.type == 'system'
|
|
426
|
+
&& (err.message.startsWith('request to') || err.code == 'ERR_STREAM_PREMATURE_CLOSE')
|
|
427
|
+
}
|
package/src/index.ts
ADDED
package/src/request.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import assert from 'assert'
|
|
2
|
+
import type {RequestInit, Response} from 'node-fetch'
|
|
3
|
+
import {esm} from '../esm'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
let mod: typeof import('node-fetch') | undefined
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
export const nodeFetch = {
|
|
10
|
+
async load(): Promise<typeof import('node-fetch')> {
|
|
11
|
+
if (mod) return mod
|
|
12
|
+
return mod = await esm<typeof import('node-fetch') >('node-fetch')
|
|
13
|
+
},
|
|
14
|
+
get Headers() {
|
|
15
|
+
assert(mod, 'node-fetch ESM is not loaded')
|
|
16
|
+
return mod.Headers
|
|
17
|
+
},
|
|
18
|
+
get FetchError() {
|
|
19
|
+
assert(mod, 'node-fetch ESM is not loaded')
|
|
20
|
+
return mod.FetchError
|
|
21
|
+
},
|
|
22
|
+
async request(url: string, init?: RequestInit): Promise<Response> {
|
|
23
|
+
let m = await nodeFetch.load()
|
|
24
|
+
return m.default(url, init)
|
|
25
|
+
}
|
|
26
|
+
}
|