urllib 3.0.0-alpha.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/History.md +858 -0
- package/README.md +41 -106
- package/package.json +15 -12
- package/src/HttpAgent.ts +72 -0
- package/src/HttpClient.ts +324 -84
- package/src/Request.ts +56 -54
- package/src/Response.ts +38 -17
- package/src/cjs/HttpAgent.d.ts +16 -0
- package/src/cjs/HttpAgent.js +62 -0
- package/src/cjs/HttpAgent.js.map +1 -0
- package/src/cjs/HttpClient.d.ts +31 -22
- package/src/cjs/HttpClient.js +376 -180
- package/src/cjs/HttpClient.js.map +1 -1
- package/src/cjs/Request.d.ts +51 -54
- package/src/cjs/Response.d.ts +33 -17
- package/src/cjs/index.d.ts +3 -22
- package/src/cjs/index.js +3 -1
- package/src/cjs/index.js.map +1 -1
- package/src/cjs/utils.d.ts +3 -0
- package/src/cjs/utils.js +56 -0
- package/src/cjs/utils.js.map +1 -0
- package/src/esm/HttpAgent.d.ts +16 -0
- package/src/esm/HttpAgent.js +58 -0
- package/src/esm/HttpAgent.js.map +1 -0
- package/src/esm/HttpClient.d.ts +31 -22
- package/src/esm/HttpClient.js +375 -179
- package/src/esm/HttpClient.js.map +1 -1
- package/src/esm/Request.d.ts +51 -54
- package/src/esm/Response.d.ts +33 -17
- package/src/esm/index.d.ts +3 -22
- package/src/esm/index.js +3 -2
- package/src/esm/index.js.map +1 -1
- package/src/esm/utils.d.ts +3 -0
- package/src/esm/utils.js +51 -0
- package/src/esm/utils.js.map +1 -0
- package/src/index.ts +3 -3
- package/src/utils.ts +53 -0
package/src/esm/HttpClient.js
CHANGED
@@ -1,14 +1,43 @@
|
|
1
|
-
var
|
1
|
+
var _a, _b, _c;
|
2
|
+
var _BlobFromStream_stream, _BlobFromStream_type, _HttpClient_instances, _HttpClient_defaultArgs, _HttpClient_dispatcher, _HttpClient_requestInternal;
|
2
3
|
import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
|
3
4
|
import { EventEmitter } from 'events';
|
4
5
|
import { debuglog } from 'util';
|
5
|
-
import {
|
6
|
+
import { createGunzip, createBrotliDecompress, gunzipSync, brotliDecompressSync, } from 'zlib';
|
6
7
|
import { Blob } from 'buffer';
|
7
|
-
import {
|
8
|
+
import { Readable, pipeline } from 'stream';
|
9
|
+
import stream from 'stream';
|
8
10
|
import { basename } from 'path';
|
9
|
-
import {
|
11
|
+
import { createReadStream } from 'fs';
|
12
|
+
import { performance } from 'perf_hooks';
|
13
|
+
import { FormData as FormDataNative, request as undiciRequest, } from 'undici';
|
14
|
+
import { FormData as FormDataNode } from 'formdata-node';
|
15
|
+
import { FormDataEncoder } from 'form-data-encoder';
|
10
16
|
import createUserAgent from 'default-user-agent';
|
11
17
|
import mime from 'mime-types';
|
18
|
+
import pump from 'pump';
|
19
|
+
import { HttpAgent } from './HttpAgent.js';
|
20
|
+
import { parseJSON, sleep } from './utils.js';
|
21
|
+
const FormData = FormDataNative !== null && FormDataNative !== void 0 ? FormDataNative : FormDataNode;
|
22
|
+
// impl isReadable on Node.js 14
|
23
|
+
const isReadable = (_a = stream.isReadable) !== null && _a !== void 0 ? _a : function isReadable(stream) {
|
24
|
+
return stream && typeof stream.read === 'function';
|
25
|
+
};
|
26
|
+
// impl promise pipeline on Node.js 14
|
27
|
+
const pipelinePromise = (_c = (_b = stream.promises) === null || _b === void 0 ? void 0 : _b.pipeline) !== null && _c !== void 0 ? _c : function pipeline(...args) {
|
28
|
+
return new Promise((resolve, reject) => {
|
29
|
+
pump(...args, (err) => {
|
30
|
+
if (err)
|
31
|
+
return reject(err);
|
32
|
+
resolve();
|
33
|
+
});
|
34
|
+
});
|
35
|
+
};
|
36
|
+
function noop() {
|
37
|
+
// noop
|
38
|
+
}
|
39
|
+
const MAX_REQURE_ID_VALUE = Math.pow(2, 31) - 10;
|
40
|
+
let globalRequestId = 0;
|
12
41
|
const debug = debuglog('urllib');
|
13
42
|
// https://github.com/octet-stream/form-data
|
14
43
|
class BlobFromStream {
|
@@ -36,7 +65,7 @@ class HttpClientRequestTimeoutError extends Error {
|
|
36
65
|
Error.captureStackTrace(this, this.constructor);
|
37
66
|
}
|
38
67
|
}
|
39
|
-
const HEADER_USER_AGENT = createUserAgent('node-urllib', '3.0.0');
|
68
|
+
export const HEADER_USER_AGENT = createUserAgent('node-urllib', '3.0.0');
|
40
69
|
function getFileName(stream) {
|
41
70
|
const filePath = stream.path;
|
42
71
|
if (filePath) {
|
@@ -44,223 +73,390 @@ function getFileName(stream) {
|
|
44
73
|
}
|
45
74
|
return '';
|
46
75
|
}
|
76
|
+
function defaultIsRetry(response) {
|
77
|
+
return response.status >= 500;
|
78
|
+
}
|
79
|
+
function performanceTime(startTime) {
|
80
|
+
return Math.floor((performance.now() - startTime) * 1000) / 1000;
|
81
|
+
}
|
47
82
|
export class HttpClient extends EventEmitter {
|
48
83
|
constructor(clientOptions) {
|
49
84
|
super();
|
50
|
-
this
|
85
|
+
_HttpClient_instances.add(this);
|
86
|
+
_HttpClient_defaultArgs.set(this, void 0);
|
87
|
+
_HttpClient_dispatcher.set(this, void 0);
|
88
|
+
__classPrivateFieldSet(this, _HttpClient_defaultArgs, clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.defaultArgs, "f");
|
89
|
+
if ((clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.lookup) || (clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.checkAddress) || (clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.connect)) {
|
90
|
+
__classPrivateFieldSet(this, _HttpClient_dispatcher, new HttpAgent({
|
91
|
+
lookup: clientOptions.lookup,
|
92
|
+
checkAddress: clientOptions.checkAddress,
|
93
|
+
connect: clientOptions.connect,
|
94
|
+
}), "f");
|
95
|
+
}
|
51
96
|
}
|
52
97
|
async request(url, options) {
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
98
|
+
return await __classPrivateFieldGet(this, _HttpClient_instances, "m", _HttpClient_requestInternal).call(this, url, options);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
_HttpClient_defaultArgs = new WeakMap(), _HttpClient_dispatcher = new WeakMap(), _HttpClient_instances = new WeakSet(), _HttpClient_requestInternal = async function _HttpClient_requestInternal(url, options, requestContext) {
|
102
|
+
var _a, _b, _c, _d, _e, _f;
|
103
|
+
if (globalRequestId >= MAX_REQURE_ID_VALUE) {
|
104
|
+
globalRequestId = 0;
|
105
|
+
}
|
106
|
+
const requestId = ++globalRequestId;
|
107
|
+
const requestUrl = typeof url === 'string' ? new URL(url) : url;
|
108
|
+
const args = {
|
109
|
+
retry: 0,
|
110
|
+
...__classPrivateFieldGet(this, _HttpClient_defaultArgs, "f"),
|
111
|
+
...options,
|
112
|
+
};
|
113
|
+
requestContext = {
|
114
|
+
retries: 0,
|
115
|
+
...requestContext,
|
116
|
+
};
|
117
|
+
const requestStartTime = performance.now();
|
118
|
+
const reqMeta = {
|
119
|
+
requestId,
|
120
|
+
url: requestUrl.href,
|
121
|
+
args,
|
122
|
+
ctx: args.ctx,
|
123
|
+
};
|
124
|
+
// keep urllib createCallbackResponse style
|
125
|
+
const resHeaders = {};
|
126
|
+
const res = {
|
127
|
+
status: -1,
|
128
|
+
statusCode: -1,
|
129
|
+
headers: resHeaders,
|
130
|
+
size: 0,
|
131
|
+
aborted: false,
|
132
|
+
rt: 0,
|
133
|
+
keepAliveSocket: true,
|
134
|
+
requestUrls: [],
|
135
|
+
timing: {
|
136
|
+
waiting: 0,
|
137
|
+
contentDownload: 0,
|
138
|
+
},
|
139
|
+
};
|
140
|
+
let headersTimeout = 5000;
|
141
|
+
let bodyTimeout = 5000;
|
142
|
+
if (args.timeout) {
|
143
|
+
if (Array.isArray(args.timeout)) {
|
144
|
+
headersTimeout = (_a = args.timeout[0]) !== null && _a !== void 0 ? _a : headersTimeout;
|
145
|
+
bodyTimeout = (_b = args.timeout[1]) !== null && _b !== void 0 ? _b : bodyTimeout;
|
146
|
+
}
|
147
|
+
else {
|
148
|
+
headersTimeout = bodyTimeout = args.timeout;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
const method = ((_c = args.method) !== null && _c !== void 0 ? _c : 'GET').toUpperCase();
|
152
|
+
const headers = {};
|
153
|
+
if (args.headers) {
|
154
|
+
// convert headers to lower-case
|
155
|
+
for (const name in args.headers) {
|
156
|
+
headers[name.toLowerCase()] = args.headers[name];
|
157
|
+
}
|
158
|
+
}
|
159
|
+
// hidden user-agent
|
160
|
+
const hiddenUserAgent = 'user-agent' in headers && !headers['user-agent'];
|
161
|
+
if (hiddenUserAgent) {
|
162
|
+
delete headers['user-agent'];
|
163
|
+
}
|
164
|
+
else if (!headers['user-agent']) {
|
165
|
+
// need to set user-agent
|
166
|
+
headers['user-agent'] = HEADER_USER_AGENT;
|
167
|
+
}
|
168
|
+
// Alias to dataType = 'stream'
|
169
|
+
if (args.streaming || args.customResponse) {
|
170
|
+
args.dataType = 'stream';
|
171
|
+
}
|
172
|
+
if (args.dataType === 'json' && !headers.accept) {
|
173
|
+
headers.accept = 'application/json';
|
174
|
+
}
|
175
|
+
// gzip alias to compressed
|
176
|
+
if (args.gzip && args.compressed !== false) {
|
177
|
+
args.compressed = true;
|
178
|
+
}
|
179
|
+
if (args.compressed && !headers['accept-encoding']) {
|
180
|
+
headers['accept-encoding'] = 'gzip, br';
|
181
|
+
}
|
182
|
+
if (requestContext.retries > 0) {
|
183
|
+
headers['x-urllib-retry'] = `${requestContext.retries}/${args.retry}`;
|
184
|
+
}
|
185
|
+
if (args.auth && !headers.authorization) {
|
186
|
+
headers.authorization = `Basic ${Buffer.from(args.auth).toString('base64')}`;
|
187
|
+
}
|
188
|
+
let opaque = args.opaque;
|
189
|
+
try {
|
190
|
+
const requestOptions = {
|
191
|
+
method,
|
192
|
+
keepalive: true,
|
193
|
+
maxRedirections: (_d = args.maxRedirects) !== null && _d !== void 0 ? _d : 10,
|
194
|
+
headersTimeout,
|
195
|
+
bodyTimeout,
|
196
|
+
opaque,
|
197
|
+
dispatcher: __classPrivateFieldGet(this, _HttpClient_dispatcher, "f"),
|
80
198
|
};
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
}
|
199
|
+
if (args.followRedirect === false) {
|
200
|
+
requestOptions.maxRedirections = 0;
|
201
|
+
}
|
202
|
+
const isGETOrHEAD = requestOptions.method === 'GET' || requestOptions.method === 'HEAD';
|
203
|
+
// alias to args.content
|
204
|
+
if (args.stream && !args.content) {
|
205
|
+
args.content = args.stream;
|
89
206
|
}
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
try {
|
94
|
-
const headers = new Headers((_c = args.headers) !== null && _c !== void 0 ? _c : {});
|
95
|
-
// don't set user-agent
|
96
|
-
const disableUserAgent = args.headers &&
|
97
|
-
(args.headers['User-Agent'] === null || args.headers['user-agent'] === null);
|
98
|
-
if (!disableUserAgent && !headers.has('user-agent')) {
|
99
|
-
// need to set user-agent
|
100
|
-
headers.set('user-agent', HEADER_USER_AGENT);
|
207
|
+
if (args.files) {
|
208
|
+
if (isGETOrHEAD) {
|
209
|
+
requestOptions.method = 'POST';
|
101
210
|
}
|
102
|
-
|
103
|
-
|
211
|
+
const formData = new FormData();
|
212
|
+
const uploadFiles = [];
|
213
|
+
if (Array.isArray(args.files)) {
|
214
|
+
for (const [index, file] of args.files.entries()) {
|
215
|
+
const field = index === 0 ? 'file' : `file${index}`;
|
216
|
+
uploadFiles.push([field, file]);
|
217
|
+
}
|
104
218
|
}
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
if (args.followRedirect === false) {
|
111
|
-
requestOptions.redirect = 'manual';
|
219
|
+
else if (args.files instanceof Readable || isReadable(args.files)) {
|
220
|
+
uploadFiles.push(['file', args.files]);
|
221
|
+
}
|
222
|
+
else if (typeof args.files === 'string' || Buffer.isBuffer(args.files)) {
|
223
|
+
uploadFiles.push(['file', args.files]);
|
112
224
|
}
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
requestOptions.method = 'POST';
|
225
|
+
else if (typeof args.files === 'object') {
|
226
|
+
for (const field in args.files) {
|
227
|
+
uploadFiles.push([field, args.files[field]]);
|
117
228
|
}
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
uploadFiles.push([field, file]);
|
124
|
-
}
|
229
|
+
}
|
230
|
+
// set normal fields first
|
231
|
+
if (args.data) {
|
232
|
+
for (const field in args.data) {
|
233
|
+
formData.append(field, args.data[field]);
|
125
234
|
}
|
126
|
-
|
127
|
-
|
235
|
+
}
|
236
|
+
for (const [index, [field, file]] of uploadFiles.entries()) {
|
237
|
+
if (typeof file === 'string') {
|
238
|
+
// FIXME: support non-ascii filename
|
239
|
+
// const fileName = encodeURIComponent(basename(file));
|
240
|
+
// formData.append(field, await fileFromPath(file, `utf-8''${fileName}`, { type: mime.lookup(fileName) || '' }));
|
241
|
+
const fileName = basename(file);
|
242
|
+
const fileReadable = createReadStream(file);
|
243
|
+
formData.append(field, new BlobFromStream(fileReadable, mime.lookup(fileName) || ''), fileName);
|
128
244
|
}
|
129
|
-
else if (
|
130
|
-
|
245
|
+
else if (Buffer.isBuffer(file)) {
|
246
|
+
formData.append(field, new Blob([file]), `bufferfile${index}`);
|
131
247
|
}
|
132
|
-
else if (
|
133
|
-
|
134
|
-
|
135
|
-
}
|
248
|
+
else if (file instanceof Readable || isReadable(file)) {
|
249
|
+
const fileName = getFileName(file) || `streamfile${index}`;
|
250
|
+
formData.append(field, new BlobFromStream(file, mime.lookup(fileName) || ''), fileName);
|
136
251
|
}
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
252
|
+
}
|
253
|
+
if (FormDataNative) {
|
254
|
+
requestOptions.body = formData;
|
255
|
+
}
|
256
|
+
else {
|
257
|
+
// Node.js 14 does not support spec-compliant FormData
|
258
|
+
// https://github.com/octet-stream/form-data#usage
|
259
|
+
const encoder = new FormDataEncoder(formData);
|
260
|
+
Object.assign(headers, encoder.headers);
|
261
|
+
// fix "Content-Length":"NaN"
|
262
|
+
delete headers['Content-Length'];
|
263
|
+
requestOptions.body = Readable.from(encoder);
|
264
|
+
}
|
265
|
+
}
|
266
|
+
else if (args.content) {
|
267
|
+
if (!isGETOrHEAD) {
|
268
|
+
// handle content
|
269
|
+
requestOptions.body = args.content;
|
270
|
+
if (args.contentType) {
|
271
|
+
headers['content-type'] = args.contentType;
|
142
272
|
}
|
143
|
-
|
144
|
-
|
145
|
-
// FIXME: support non-ascii filename
|
146
|
-
// const fileName = encodeURIComponent(basename(file));
|
147
|
-
// formData.append(field, await fileFromPath(file, `utf-8''${fileName}`, { type: mime.lookup(fileName) || '' }));
|
148
|
-
const fileName = basename(file);
|
149
|
-
const fileReader = createReadStream(file);
|
150
|
-
formData.append(field, new BlobFromStream(fileReader, mime.lookup(fileName) || ''), fileName);
|
151
|
-
}
|
152
|
-
else if (Buffer.isBuffer(file)) {
|
153
|
-
formData.append(field, new Blob([file]), `bufferfile${index}`);
|
154
|
-
}
|
155
|
-
else if (file instanceof Readable || isReadable(file)) {
|
156
|
-
const fileName = getFileName(file) || `streamfile${index}`;
|
157
|
-
formData.append(field, new BlobFromStream(file, mime.lookup(fileName) || ''), fileName);
|
158
|
-
}
|
273
|
+
if (typeof args.content === 'string' && !headers['content-type']) {
|
274
|
+
headers['content-type'] = 'text/plain;charset=UTF-8';
|
159
275
|
}
|
160
|
-
requestOptions.body = formData;
|
161
276
|
}
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
headers.set('content-type', args.contentType);
|
277
|
+
}
|
278
|
+
else if (args.data) {
|
279
|
+
const isStringOrBufferOrReadable = typeof args.data === 'string'
|
280
|
+
|| Buffer.isBuffer(args.data)
|
281
|
+
|| isReadable(args.data);
|
282
|
+
if (isGETOrHEAD) {
|
283
|
+
if (!isStringOrBufferOrReadable) {
|
284
|
+
for (const field in args.data) {
|
285
|
+
requestUrl.searchParams.append(field, args.data[field]);
|
172
286
|
}
|
173
287
|
}
|
174
288
|
}
|
175
|
-
else
|
176
|
-
|
177
|
-
|
178
|
-
|| isReadable(args.data);
|
179
|
-
if (isGETOrHEAD) {
|
180
|
-
if (!isStringOrBufferOrReadable) {
|
181
|
-
for (const field in args.data) {
|
182
|
-
requestUrl.searchParams.append(field, args.data[field]);
|
183
|
-
}
|
184
|
-
}
|
289
|
+
else {
|
290
|
+
if (isStringOrBufferOrReadable) {
|
291
|
+
requestOptions.body = args.data;
|
185
292
|
}
|
186
293
|
else {
|
187
|
-
if (
|
188
|
-
|
189
|
-
|
190
|
-
|
294
|
+
if (args.contentType === 'json'
|
295
|
+
|| args.contentType === 'application/json'
|
296
|
+
|| ((_e = headers['content-type']) === null || _e === void 0 ? void 0 : _e.startsWith('application/json'))) {
|
297
|
+
requestOptions.body = JSON.stringify(args.data);
|
298
|
+
if (!headers['content-type']) {
|
299
|
+
headers['content-type'] = 'application/json';
|
191
300
|
}
|
192
|
-
requestOptions.body = args.data;
|
193
301
|
}
|
194
302
|
else {
|
195
|
-
|
196
|
-
|
197
|
-
|| ((_d = headers.get('content-type')) === null || _d === void 0 ? void 0 : _d.startsWith('application/json'))) {
|
198
|
-
requestOptions.body = JSON.stringify(args.data);
|
199
|
-
if (!headers.has('content-type')) {
|
200
|
-
headers.set('content-type', 'application/json');
|
201
|
-
}
|
202
|
-
}
|
203
|
-
else {
|
204
|
-
requestOptions.body = new URLSearchParams(args.data);
|
205
|
-
}
|
303
|
+
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
|
304
|
+
requestOptions.body = new URLSearchParams(args.data).toString();
|
206
305
|
}
|
207
306
|
}
|
208
307
|
}
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
308
|
+
}
|
309
|
+
debug('Request#%d %s %s, headers: %j, headersTimeout: %s, bodyTimeout: %s', requestId, requestOptions.method, requestUrl.href, headers, headersTimeout, bodyTimeout);
|
310
|
+
requestOptions.headers = headers;
|
311
|
+
if (this.listenerCount('request') > 0) {
|
312
|
+
this.emit('request', reqMeta);
|
313
|
+
}
|
314
|
+
const response = await undiciRequest(requestUrl, requestOptions);
|
315
|
+
opaque = response.opaque;
|
316
|
+
if (args.timing) {
|
317
|
+
res.timing.waiting = performanceTime(requestStartTime);
|
318
|
+
}
|
319
|
+
const context = response.context;
|
320
|
+
let lastUrl = '';
|
321
|
+
if (context === null || context === void 0 ? void 0 : context.history) {
|
322
|
+
for (const urlObject of context === null || context === void 0 ? void 0 : context.history) {
|
323
|
+
res.requestUrls.push(urlObject.href);
|
324
|
+
lastUrl = urlObject.href;
|
325
|
+
}
|
326
|
+
}
|
327
|
+
else {
|
328
|
+
res.requestUrls.push(requestUrl.href);
|
329
|
+
lastUrl = requestUrl.href;
|
330
|
+
}
|
331
|
+
const contentEncoding = response.headers['content-encoding'];
|
332
|
+
const isCompressedContent = contentEncoding === 'gzip' || contentEncoding === 'br';
|
333
|
+
res.headers = response.headers;
|
334
|
+
res.status = res.statusCode = response.statusCode;
|
335
|
+
if (res.headers['content-length']) {
|
336
|
+
res.size = parseInt(res.headers['content-length']);
|
337
|
+
}
|
338
|
+
let data = null;
|
339
|
+
let responseBodyStream;
|
340
|
+
if (args.dataType === 'stream') {
|
341
|
+
// streaming mode will disable retry
|
342
|
+
args.retry = 0;
|
343
|
+
const meta = {
|
344
|
+
status: res.status,
|
345
|
+
statusCode: res.statusCode,
|
346
|
+
headers: res.headers,
|
347
|
+
};
|
348
|
+
if (isCompressedContent) {
|
349
|
+
// gzip or br
|
350
|
+
const decoder = contentEncoding === 'gzip' ? createGunzip() : createBrotliDecompress();
|
351
|
+
responseBodyStream = Object.assign(pipeline(response.body, decoder, noop), meta);
|
352
|
+
}
|
353
|
+
else {
|
354
|
+
responseBodyStream = Object.assign(response.body, meta);
|
214
355
|
}
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
356
|
+
}
|
357
|
+
else if (args.writeStream) {
|
358
|
+
// streaming mode will disable retry
|
359
|
+
args.retry = 0;
|
360
|
+
if (isCompressedContent) {
|
361
|
+
const decoder = contentEncoding === 'gzip' ? createGunzip() : createBrotliDecompress();
|
362
|
+
await pipelinePromise(response.body, decoder, args.writeStream);
|
219
363
|
}
|
220
|
-
|
221
|
-
|
364
|
+
else {
|
365
|
+
await pipelinePromise(response.body, args.writeStream);
|
222
366
|
}
|
223
|
-
|
224
|
-
|
225
|
-
|
367
|
+
}
|
368
|
+
else {
|
369
|
+
// buffer
|
370
|
+
data = Buffer.from(await response.body.arrayBuffer());
|
371
|
+
if (isCompressedContent) {
|
372
|
+
try {
|
373
|
+
data = contentEncoding === 'gzip' ? gunzipSync(data) : brotliDecompressSync(data);
|
374
|
+
}
|
375
|
+
catch (err) {
|
376
|
+
if (err.name === 'Error') {
|
377
|
+
err.name = 'UnzipError';
|
378
|
+
}
|
379
|
+
throw err;
|
380
|
+
}
|
226
381
|
}
|
227
|
-
|
228
|
-
data =
|
382
|
+
if (args.dataType === 'text') {
|
383
|
+
data = data.toString();
|
229
384
|
}
|
230
385
|
else if (args.dataType === 'json') {
|
231
|
-
if (
|
232
|
-
data =
|
386
|
+
if (data.length === 0) {
|
387
|
+
data = null;
|
233
388
|
}
|
234
389
|
else {
|
235
|
-
data =
|
390
|
+
data = parseJSON(data.toString(), args.fixJSONCtlChars);
|
236
391
|
}
|
237
392
|
}
|
238
|
-
|
239
|
-
|
240
|
-
|
393
|
+
}
|
394
|
+
res.rt = performanceTime(requestStartTime);
|
395
|
+
if (args.timing) {
|
396
|
+
res.timing.contentDownload = res.rt;
|
397
|
+
}
|
398
|
+
const clientResponse = {
|
399
|
+
opaque,
|
400
|
+
data,
|
401
|
+
status: res.status,
|
402
|
+
headers: res.headers,
|
403
|
+
url: lastUrl,
|
404
|
+
redirected: res.requestUrls.length > 1,
|
405
|
+
requestUrls: res.requestUrls,
|
406
|
+
res: responseBodyStream !== null && responseBodyStream !== void 0 ? responseBodyStream : res,
|
407
|
+
};
|
408
|
+
if (args.retry > 0 && requestContext.retries < args.retry) {
|
409
|
+
const isRetry = (_f = args.isRetry) !== null && _f !== void 0 ? _f : defaultIsRetry;
|
410
|
+
if (isRetry(clientResponse)) {
|
411
|
+
if (args.retryDelay) {
|
412
|
+
await sleep(args.retryDelay);
|
413
|
+
}
|
414
|
+
requestContext.retries++;
|
415
|
+
return await __classPrivateFieldGet(this, _HttpClient_instances, "m", _HttpClient_requestInternal).call(this, url, options, requestContext);
|
241
416
|
}
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
417
|
+
}
|
418
|
+
if (this.listenerCount('response') > 0) {
|
419
|
+
this.emit('response', {
|
420
|
+
requestId,
|
421
|
+
error: null,
|
422
|
+
ctx: args.ctx,
|
423
|
+
req: reqMeta,
|
249
424
|
res,
|
250
|
-
};
|
425
|
+
});
|
251
426
|
}
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
throw err;
|
427
|
+
return clientResponse;
|
428
|
+
}
|
429
|
+
catch (e) {
|
430
|
+
debug('Request#%d throw error: %s', requestId, e);
|
431
|
+
let err = e;
|
432
|
+
if (err.name === 'HeadersTimeoutError') {
|
433
|
+
err = new HttpClientRequestTimeoutError(headersTimeout, { cause: e });
|
260
434
|
}
|
261
|
-
|
262
|
-
|
435
|
+
else if (err.name === 'BodyTimeoutError') {
|
436
|
+
err = new HttpClientRequestTimeoutError(bodyTimeout, { cause: e });
|
263
437
|
}
|
438
|
+
err.opaque = opaque;
|
439
|
+
err.status = res.status;
|
440
|
+
err.headers = res.headers;
|
441
|
+
err.res = res;
|
442
|
+
// make sure requestUrls not empty
|
443
|
+
if (res.requestUrls.length === 0) {
|
444
|
+
res.requestUrls.push(requestUrl.href);
|
445
|
+
}
|
446
|
+
res.rt = performanceTime(requestStartTime);
|
447
|
+
if (args.timing) {
|
448
|
+
res.timing.contentDownload = res.rt;
|
449
|
+
}
|
450
|
+
if (this.listenerCount('response') > 0) {
|
451
|
+
this.emit('response', {
|
452
|
+
requestId,
|
453
|
+
error: err,
|
454
|
+
ctx: args.ctx,
|
455
|
+
req: reqMeta,
|
456
|
+
res,
|
457
|
+
});
|
458
|
+
}
|
459
|
+
throw err;
|
264
460
|
}
|
265
|
-
}
|
461
|
+
};
|
266
462
|
//# sourceMappingURL=HttpClient.js.map
|