got 8.1.0 → 8.3.2
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/index.js +115 -59
- package/package.json +5 -4
- package/readme.md +42 -4
package/index.js
CHANGED
|
@@ -142,59 +142,12 @@ function requestAsEventEmitter(opts) {
|
|
|
142
142
|
return;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
const downloadBodySize = Number(res.headers['content-length']) || null;
|
|
146
|
-
let downloaded = 0;
|
|
147
|
-
|
|
148
145
|
setImmediate(() => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const percent = downloadBodySize ? downloaded / downloadBodySize : 0;
|
|
154
|
-
|
|
155
|
-
// Let flush() be responsible for emitting the last event
|
|
156
|
-
if (percent < 1) {
|
|
157
|
-
ee.emit('downloadProgress', {
|
|
158
|
-
percent,
|
|
159
|
-
transferred: downloaded,
|
|
160
|
-
total: downloadBodySize
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
callback(null, chunk);
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
flush(callback) {
|
|
168
|
-
ee.emit('downloadProgress', {
|
|
169
|
-
percent: 1,
|
|
170
|
-
transferred: downloaded,
|
|
171
|
-
total: downloadBodySize
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
callback();
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
mimicResponse(res, progressStream);
|
|
179
|
-
progressStream.redirectUrls = redirects;
|
|
180
|
-
|
|
181
|
-
const response = opts.decompress === true &&
|
|
182
|
-
is.function(decompressResponse) &&
|
|
183
|
-
opts.method !== 'HEAD' ? decompressResponse(progressStream) : progressStream;
|
|
184
|
-
|
|
185
|
-
if (!opts.decompress && ['gzip', 'deflate'].indexOf(res.headers['content-encoding']) !== -1) {
|
|
186
|
-
opts.encoding = null;
|
|
146
|
+
try {
|
|
147
|
+
getResponse(res, opts, ee, redirects);
|
|
148
|
+
} catch (e) {
|
|
149
|
+
ee.emit('error', e);
|
|
187
150
|
}
|
|
188
|
-
|
|
189
|
-
ee.emit('response', response);
|
|
190
|
-
|
|
191
|
-
ee.emit('downloadProgress', {
|
|
192
|
-
percent: 0,
|
|
193
|
-
transferred: 0,
|
|
194
|
-
total: downloadBodySize
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
res.pipe(progressStream);
|
|
198
151
|
});
|
|
199
152
|
});
|
|
200
153
|
|
|
@@ -207,9 +160,18 @@ function requestAsEventEmitter(opts) {
|
|
|
207
160
|
});
|
|
208
161
|
|
|
209
162
|
cacheReq.once('request', req => {
|
|
163
|
+
let aborted = false;
|
|
164
|
+
req.once('abort', _ => {
|
|
165
|
+
aborted = true;
|
|
166
|
+
});
|
|
167
|
+
|
|
210
168
|
req.once('error', err => {
|
|
211
169
|
clearInterval(progressInterval);
|
|
212
170
|
|
|
171
|
+
if (aborted) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
213
175
|
const backoff = opts.retries(++retryCount, err);
|
|
214
176
|
|
|
215
177
|
if (backoff) {
|
|
@@ -227,14 +189,23 @@ function requestAsEventEmitter(opts) {
|
|
|
227
189
|
total: uploadBodySize
|
|
228
190
|
});
|
|
229
191
|
|
|
230
|
-
|
|
231
|
-
|
|
192
|
+
const socket = req.connection;
|
|
193
|
+
if (socket) {
|
|
194
|
+
// `._connecting` was the old property which was made public in node v6.1.0
|
|
195
|
+
const isConnecting = socket.connecting === undefined ? socket._connecting : socket.connecting;
|
|
196
|
+
|
|
197
|
+
const onSocketConnect = () => {
|
|
232
198
|
const uploadEventFrequency = 150;
|
|
233
199
|
|
|
234
200
|
progressInterval = setInterval(() => {
|
|
201
|
+
if (socket.destroyed) {
|
|
202
|
+
clearInterval(progressInterval);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
235
206
|
const lastUploaded = uploaded;
|
|
236
|
-
const headersSize = Buffer.byteLength(req._header);
|
|
237
|
-
uploaded =
|
|
207
|
+
const headersSize = req._header ? Buffer.byteLength(req._header) : 0;
|
|
208
|
+
uploaded = socket.bytesWritten - headersSize;
|
|
238
209
|
|
|
239
210
|
// Prevent the known issue of `bytesWritten` being larger than body size
|
|
240
211
|
if (uploadBodySize && uploaded > uploadBodySize) {
|
|
@@ -254,7 +225,17 @@ function requestAsEventEmitter(opts) {
|
|
|
254
225
|
total: uploadBodySize
|
|
255
226
|
});
|
|
256
227
|
}, uploadEventFrequency);
|
|
257
|
-
}
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// Only subscribe to 'connect' event if we're actually connecting a new
|
|
231
|
+
// socket, otherwise if we're already connected (because this is a
|
|
232
|
+
// keep-alive connection) do not bother. This is important since we won't
|
|
233
|
+
// get a 'connect' event for an already connected socket.
|
|
234
|
+
if (isConnecting) {
|
|
235
|
+
socket.once('connect', onSocketConnect);
|
|
236
|
+
} else {
|
|
237
|
+
onSocketConnect();
|
|
238
|
+
}
|
|
258
239
|
}
|
|
259
240
|
});
|
|
260
241
|
|
|
@@ -273,6 +254,15 @@ function requestAsEventEmitter(opts) {
|
|
|
273
254
|
Promise.resolve(getBodySize(opts))
|
|
274
255
|
.then(size => {
|
|
275
256
|
uploadBodySize = size;
|
|
257
|
+
|
|
258
|
+
if (
|
|
259
|
+
is.undefined(opts.headers['content-length']) &&
|
|
260
|
+
is.undefined(opts.headers['transfer-encoding']) &&
|
|
261
|
+
isFormData(opts.body)
|
|
262
|
+
) {
|
|
263
|
+
opts.headers['content-length'] = size;
|
|
264
|
+
}
|
|
265
|
+
|
|
276
266
|
get(opts);
|
|
277
267
|
})
|
|
278
268
|
.catch(err => {
|
|
@@ -283,6 +273,61 @@ function requestAsEventEmitter(opts) {
|
|
|
283
273
|
return ee;
|
|
284
274
|
}
|
|
285
275
|
|
|
276
|
+
function getResponse(res, opts, ee, redirects) {
|
|
277
|
+
const downloadBodySize = Number(res.headers['content-length']) || null;
|
|
278
|
+
let downloaded = 0;
|
|
279
|
+
|
|
280
|
+
const progressStream = new Transform({
|
|
281
|
+
transform(chunk, encoding, callback) {
|
|
282
|
+
downloaded += chunk.length;
|
|
283
|
+
|
|
284
|
+
const percent = downloadBodySize ? downloaded / downloadBodySize : 0;
|
|
285
|
+
|
|
286
|
+
// Let flush() be responsible for emitting the last event
|
|
287
|
+
if (percent < 1) {
|
|
288
|
+
ee.emit('downloadProgress', {
|
|
289
|
+
percent,
|
|
290
|
+
transferred: downloaded,
|
|
291
|
+
total: downloadBodySize
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
callback(null, chunk);
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
flush(callback) {
|
|
299
|
+
ee.emit('downloadProgress', {
|
|
300
|
+
percent: 1,
|
|
301
|
+
transferred: downloaded,
|
|
302
|
+
total: downloadBodySize
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
callback();
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
mimicResponse(res, progressStream);
|
|
310
|
+
progressStream.redirectUrls = redirects;
|
|
311
|
+
|
|
312
|
+
const response = opts.decompress === true &&
|
|
313
|
+
is.function(decompressResponse) &&
|
|
314
|
+
opts.method !== 'HEAD' ? decompressResponse(progressStream) : progressStream;
|
|
315
|
+
|
|
316
|
+
if (!opts.decompress && ['gzip', 'deflate'].indexOf(res.headers['content-encoding']) !== -1) {
|
|
317
|
+
opts.encoding = null;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
ee.emit('response', response);
|
|
321
|
+
|
|
322
|
+
ee.emit('downloadProgress', {
|
|
323
|
+
percent: 0,
|
|
324
|
+
transferred: 0,
|
|
325
|
+
total: downloadBodySize
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
res.pipe(progressStream);
|
|
329
|
+
}
|
|
330
|
+
|
|
286
331
|
function asPromise(opts) {
|
|
287
332
|
const timeoutFn = requestPromise => opts.gotTimeout && opts.gotTimeout.request ?
|
|
288
333
|
pTimeout(requestPromise, opts.gotTimeout.request, new got.RequestError({message: 'Request timed out', code: 'ETIMEDOUT'}, opts)) :
|
|
@@ -290,7 +335,7 @@ function asPromise(opts) {
|
|
|
290
335
|
|
|
291
336
|
const proxy = new EventEmitter();
|
|
292
337
|
|
|
293
|
-
const cancelable = new PCancelable((
|
|
338
|
+
const cancelable = new PCancelable((resolve, reject, onCancel) => {
|
|
294
339
|
const ee = requestAsEventEmitter(opts);
|
|
295
340
|
let cancelOnRequest = false;
|
|
296
341
|
|
|
@@ -355,6 +400,14 @@ function asPromise(opts) {
|
|
|
355
400
|
ee.on('downloadProgress', proxy.emit.bind(proxy, 'downloadProgress'));
|
|
356
401
|
});
|
|
357
402
|
|
|
403
|
+
// Preserve backwards-compatibility
|
|
404
|
+
// TODO: Remove this in the next major version
|
|
405
|
+
Object.defineProperty(cancelable, 'canceled', {
|
|
406
|
+
get() {
|
|
407
|
+
return cancelable.isCanceled;
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
|
|
358
411
|
const promise = timeoutFn(cancelable);
|
|
359
412
|
|
|
360
413
|
promise.cancel = cancelable.cancel.bind(cancelable);
|
|
@@ -485,10 +538,13 @@ function normalizeArguments(url, opts) {
|
|
|
485
538
|
}
|
|
486
539
|
|
|
487
540
|
opts.headers = Object.assign({
|
|
488
|
-
'user-agent': `${pkg.name}/${pkg.version} (https://github.com/sindresorhus/got)
|
|
489
|
-
'accept-encoding': 'gzip,deflate'
|
|
541
|
+
'user-agent': `${pkg.name}/${pkg.version} (https://github.com/sindresorhus/got)`
|
|
490
542
|
}, headers);
|
|
491
543
|
|
|
544
|
+
if (opts.decompress && is.undefined(opts.headers['accept-encoding'])) {
|
|
545
|
+
opts.headers['accept-encoding'] = 'gzip, deflate';
|
|
546
|
+
}
|
|
547
|
+
|
|
492
548
|
const query = opts.query;
|
|
493
549
|
|
|
494
550
|
if (query) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "got",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.2",
|
|
4
4
|
"description": "Simplified HTTP requests",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "sindresorhus/got",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"isurl": "^1.0.0-alpha5",
|
|
62
62
|
"lowercase-keys": "^1.0.0",
|
|
63
63
|
"mimic-response": "^1.0.0",
|
|
64
|
-
"p-cancelable": "^0.
|
|
64
|
+
"p-cancelable": "^0.4.0",
|
|
65
65
|
"p-timeout": "^2.0.1",
|
|
66
66
|
"pify": "^3.0.0",
|
|
67
67
|
"safe-buffer": "^5.1.1",
|
|
@@ -70,19 +70,20 @@
|
|
|
70
70
|
"url-to-options": "^1.0.1"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"ava": "^0.
|
|
73
|
+
"ava": "^0.25.0",
|
|
74
74
|
"coveralls": "^3.0.0",
|
|
75
75
|
"form-data": "^2.1.1",
|
|
76
76
|
"get-port": "^3.0.0",
|
|
77
77
|
"nyc": "^11.0.2",
|
|
78
78
|
"p-event": "^1.3.0",
|
|
79
79
|
"pem": "^1.4.4",
|
|
80
|
+
"proxyquire": "^1.8.0",
|
|
80
81
|
"sinon": "^4.0.0",
|
|
81
82
|
"slow-stream": "0.0.4",
|
|
82
83
|
"tempfile": "^2.0.0",
|
|
83
84
|
"tempy": "^0.2.1",
|
|
84
85
|
"universal-url": "1.0.0-alpha",
|
|
85
|
-
"xo": "^0.
|
|
86
|
+
"xo": "^0.20.0"
|
|
86
87
|
},
|
|
87
88
|
"ava": {
|
|
88
89
|
"concurrency": 4
|
package/readme.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<br>
|
|
3
3
|
<br>
|
|
4
|
-
<img width="360" src="
|
|
4
|
+
<img width="360" src="media/logo.svg" alt="Got">
|
|
5
5
|
<br>
|
|
6
6
|
<br>
|
|
7
7
|
<br>
|
|
@@ -129,7 +129,7 @@ If `content-length` or `transfer-encoding` is not set in `options.headers` and `
|
|
|
129
129
|
Type: `string` `null`<br>
|
|
130
130
|
Default: `'utf8'`
|
|
131
131
|
|
|
132
|
-
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. If `null`, the body is returned as a Buffer.
|
|
132
|
+
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. If `null`, the body is returned as a [`Buffer`](https://nodejs.org/api/buffer.html) (binary data).
|
|
133
133
|
|
|
134
134
|
###### form
|
|
135
135
|
|
|
@@ -195,7 +195,7 @@ request the resource pointed to in the location header via `GET`. This is in acc
|
|
|
195
195
|
Type: `boolean`<br>
|
|
196
196
|
Default: `true`
|
|
197
197
|
|
|
198
|
-
Decompress the response automatically.
|
|
198
|
+
Decompress the response automatically. This will set the `accept-encoding` header to `gzip, deflate` unless you set it yourself.
|
|
199
199
|
|
|
200
200
|
If this is disabled, a compressed response is returned as a `Buffer`. This may be useful if you want to handle decompression yourself or stream the raw compressed data.
|
|
201
201
|
|
|
@@ -351,7 +351,7 @@ The promise returned by Got has a [`.cancel()`](https://github.com/sindresorhus/
|
|
|
351
351
|
try {
|
|
352
352
|
await request;
|
|
353
353
|
} catch (error) {
|
|
354
|
-
if (request.
|
|
354
|
+
if (request.isCanceled) { // Or `error instanceof got.CancelError`
|
|
355
355
|
// Handle cancelation
|
|
356
356
|
}
|
|
357
357
|
|
|
@@ -569,6 +569,44 @@ request(`https://${config.host}/production/`, {
|
|
|
569
569
|
```
|
|
570
570
|
|
|
571
571
|
|
|
572
|
+
## Testing
|
|
573
|
+
|
|
574
|
+
You can test your requests by using the [`nock`](https://github.com/node-nock/nock) module to mock an endpoint:
|
|
575
|
+
|
|
576
|
+
```js
|
|
577
|
+
const got = require('got');
|
|
578
|
+
const nock = require('nock');
|
|
579
|
+
|
|
580
|
+
nock('https://sindresorhus.com')
|
|
581
|
+
.get('/')
|
|
582
|
+
.reply(200, 'Hello world!');
|
|
583
|
+
|
|
584
|
+
(async () => {
|
|
585
|
+
const response = await got('sindresorhus.com');
|
|
586
|
+
console.log(response.body);
|
|
587
|
+
//=> 'Hello world!'
|
|
588
|
+
})();
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
If you need real integration tests you can use [`create-test-server`](https://github.com/lukechilds/create-test-server):
|
|
592
|
+
|
|
593
|
+
```js
|
|
594
|
+
const got = require('got');
|
|
595
|
+
const createTestServer = require('create-test-server');
|
|
596
|
+
|
|
597
|
+
(async () => {
|
|
598
|
+
const server = await createTestServer();
|
|
599
|
+
server.get('/', 'Hello world!');
|
|
600
|
+
|
|
601
|
+
const response = await got(server.url);
|
|
602
|
+
console.log(response.body);
|
|
603
|
+
//=> 'Hello world!'
|
|
604
|
+
|
|
605
|
+
await server.close();
|
|
606
|
+
})();
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
|
|
572
610
|
## Tips
|
|
573
611
|
|
|
574
612
|
### User Agent
|