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