superagent 3.7.0 → 3.8.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/History.md +12 -0
- package/docs/index.md +38 -5
- package/lib/agent-base.js +20 -0
- package/lib/client.js +61 -48
- package/lib/node/agent.js +38 -37
- package/lib/node/index.js +209 -192
- package/lib/node/parsers/image.js +6 -6
- package/lib/node/parsers/index.js +1 -1
- package/lib/node/parsers/json.js +4 -2
- package/lib/node/parsers/text.js +3 -1
- package/lib/node/parsers/urlencoded.js +5 -3
- package/lib/node/response.js +12 -13
- package/lib/node/unzip.js +16 -15
- package/lib/request-base.js +73 -16
- package/lib/response-base.js +2 -2
- package/lib/utils.js +4 -2
- package/package.json +2 -2
- package/superagent.js +166 -99
- package/yarn.lock +163 -393
- package/lib/should-retry.js +0 -25
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
module.exports =
|
|
4
|
-
|
|
3
|
+
module.exports = (res, fn) => {
|
|
4
|
+
const data = []; // Binary data needs binary storage
|
|
5
5
|
|
|
6
|
-
res.on('data',
|
|
7
|
-
|
|
6
|
+
res.on('data', chunk => {
|
|
7
|
+
data.push(chunk);
|
|
8
8
|
});
|
|
9
|
-
res.on('end',
|
|
10
|
-
|
|
9
|
+
res.on('end', () => {
|
|
10
|
+
fn(null, Buffer.concat(data));
|
|
11
11
|
});
|
|
12
12
|
};
|
|
@@ -4,7 +4,7 @@ exports['application/x-www-form-urlencoded'] = require('./urlencoded');
|
|
|
4
4
|
exports['application/json'] = require('./json');
|
|
5
5
|
exports.text = require('./text');
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const binary = require('./image');
|
|
8
8
|
exports['application/octet-stream'] = binary;
|
|
9
9
|
exports['application/pdf'] = binary;
|
|
10
10
|
exports.image = binary;
|
package/lib/node/parsers/json.js
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
module.exports = function parseJSON(res, fn){
|
|
4
4
|
res.text = '';
|
|
5
5
|
res.setEncoding('utf8');
|
|
6
|
-
res.on('data',
|
|
7
|
-
|
|
6
|
+
res.on('data', chunk => {
|
|
7
|
+
res.text += chunk;
|
|
8
|
+
});
|
|
9
|
+
res.on('end', () => {
|
|
8
10
|
try {
|
|
9
11
|
var body = res.text && JSON.parse(res.text);
|
|
10
12
|
} catch (e) {
|
package/lib/node/parsers/text.js
CHANGED
|
@@ -4,13 +4,15 @@
|
|
|
4
4
|
* Module dependencies.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const qs = require('qs');
|
|
8
8
|
|
|
9
9
|
module.exports = function(res, fn){
|
|
10
10
|
res.text = '';
|
|
11
11
|
res.setEncoding('ascii');
|
|
12
|
-
res.on('data',
|
|
13
|
-
|
|
12
|
+
res.on('data', chunk => {
|
|
13
|
+
res.text += chunk;
|
|
14
|
+
});
|
|
15
|
+
res.on('end', () => {
|
|
14
16
|
try {
|
|
15
17
|
fn(null, qs.parse(res.text));
|
|
16
18
|
} catch (err) {
|
package/lib/node/response.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Module dependencies.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const util = require('util');
|
|
8
|
+
const Stream = require('stream');
|
|
9
|
+
const ResponseBase = require('../response-base');
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Expose `Response`.
|
|
@@ -30,7 +30,7 @@ module.exports = Response;
|
|
|
30
30
|
|
|
31
31
|
function Response(req) {
|
|
32
32
|
Stream.call(this);
|
|
33
|
-
|
|
33
|
+
const res = (this.res = req.res);
|
|
34
34
|
this.request = req;
|
|
35
35
|
this.req = req.req;
|
|
36
36
|
this.text = res.text;
|
|
@@ -54,7 +54,6 @@ function Response(req) {
|
|
|
54
54
|
util.inherits(Response, Stream);
|
|
55
55
|
ResponseBase(Response.prototype);
|
|
56
56
|
|
|
57
|
-
|
|
58
57
|
/**
|
|
59
58
|
* Implements methods of a `ReadableStream`
|
|
60
59
|
*/
|
|
@@ -86,13 +85,13 @@ Response.prototype.resume = function(){
|
|
|
86
85
|
* @api public
|
|
87
86
|
*/
|
|
88
87
|
|
|
89
|
-
Response.prototype.toError = function(){
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
Response.prototype.toError = function() {
|
|
89
|
+
const req = this.req;
|
|
90
|
+
const method = req.method;
|
|
91
|
+
const path = req.path;
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
|
|
93
|
+
const msg = `cannot ${method} ${path} (${this.status})`;
|
|
94
|
+
const err = new Error(msg);
|
|
96
95
|
err.status = this.status;
|
|
97
96
|
err.text = this.text;
|
|
98
97
|
err.method = method;
|
|
@@ -114,11 +113,11 @@ Response.prototype.setStatusProperties = function(status){
|
|
|
114
113
|
* @api public
|
|
115
114
|
*/
|
|
116
115
|
|
|
117
|
-
Response.prototype.toJSON = function(){
|
|
116
|
+
Response.prototype.toJSON = function() {
|
|
118
117
|
return {
|
|
119
118
|
req: this.request.toJSON(),
|
|
120
119
|
header: this.header,
|
|
121
120
|
status: this.status,
|
|
122
|
-
text: this.text
|
|
121
|
+
text: this.text,
|
|
123
122
|
};
|
|
124
123
|
};
|
package/lib/node/unzip.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Module dependencies.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const StringDecoder = require('string_decoder').StringDecoder;
|
|
8
|
+
const Stream = require('stream');
|
|
9
|
+
const zlib = require('zlib');
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Buffers response data events and re-emits when they're unzipped.
|
|
@@ -16,16 +16,17 @@ var zlib = require('zlib');
|
|
|
16
16
|
* @api private
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
exports.unzip =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
exports.unzip = (req, res) => {
|
|
20
|
+
const unzip = zlib.createUnzip();
|
|
21
|
+
const stream = new Stream();
|
|
22
|
+
let decoder;
|
|
23
23
|
|
|
24
24
|
// make node responseOnEnd() happy
|
|
25
25
|
stream.req = req;
|
|
26
26
|
|
|
27
|
-
unzip.on('error',
|
|
28
|
-
if (err && err.code === 'Z_BUF_ERROR') {
|
|
27
|
+
unzip.on('error', err => {
|
|
28
|
+
if (err && err.code === 'Z_BUF_ERROR') {
|
|
29
|
+
// unexpected end of file is ignored by browsers and curl
|
|
29
30
|
stream.emit('end');
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
@@ -36,27 +37,27 @@ exports.unzip = function(req, res){
|
|
|
36
37
|
res.pipe(unzip);
|
|
37
38
|
|
|
38
39
|
// override `setEncoding` to capture encoding
|
|
39
|
-
res.setEncoding =
|
|
40
|
+
res.setEncoding = type => {
|
|
40
41
|
decoder = new StringDecoder(type);
|
|
41
42
|
};
|
|
42
43
|
|
|
43
44
|
// decode upon decompressing with captured encoding
|
|
44
|
-
unzip.on('data',
|
|
45
|
+
unzip.on('data', buf => {
|
|
45
46
|
if (decoder) {
|
|
46
|
-
|
|
47
|
+
const str = decoder.write(buf);
|
|
47
48
|
if (str.length) stream.emit('data', str);
|
|
48
49
|
} else {
|
|
49
50
|
stream.emit('data', buf);
|
|
50
51
|
}
|
|
51
52
|
});
|
|
52
53
|
|
|
53
|
-
unzip.on('end',
|
|
54
|
+
unzip.on('end', () => {
|
|
54
55
|
stream.emit('end');
|
|
55
56
|
});
|
|
56
57
|
|
|
57
58
|
// override `on` to capture data listeners
|
|
58
|
-
|
|
59
|
-
res.on = function(type, fn){
|
|
59
|
+
const _on = res.on;
|
|
60
|
+
res.on = function(type, fn) {
|
|
60
61
|
if ('data' == type || 'end' == type) {
|
|
61
62
|
stream.on(type, fn);
|
|
62
63
|
} else if ('error' == type) {
|
package/lib/request-base.js
CHANGED
|
@@ -143,19 +143,60 @@ RequestBase.prototype.timeout = function timeout(options){
|
|
|
143
143
|
* Failed requests will be retried 'count' times if timeout or err.code >= 500.
|
|
144
144
|
*
|
|
145
145
|
* @param {Number} count
|
|
146
|
+
* @param {Function} [fn]
|
|
146
147
|
* @return {Request} for chaining
|
|
147
148
|
* @api public
|
|
148
149
|
*/
|
|
149
150
|
|
|
150
|
-
RequestBase.prototype.retry = function retry(count){
|
|
151
|
+
RequestBase.prototype.retry = function retry(count, fn){
|
|
151
152
|
// Default to 1 if no count passed or true
|
|
152
153
|
if (arguments.length === 0 || count === true) count = 1;
|
|
153
154
|
if (count <= 0) count = 0;
|
|
154
155
|
this._maxRetries = count;
|
|
155
156
|
this._retries = 0;
|
|
157
|
+
this._retryCallback = fn;
|
|
156
158
|
return this;
|
|
157
159
|
};
|
|
158
160
|
|
|
161
|
+
var ERROR_CODES = [
|
|
162
|
+
'ECONNRESET',
|
|
163
|
+
'ETIMEDOUT',
|
|
164
|
+
'EADDRINFO',
|
|
165
|
+
'ESOCKETTIMEDOUT'
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Determine if a request should be retried.
|
|
170
|
+
* (Borrowed from segmentio/superagent-retry)
|
|
171
|
+
*
|
|
172
|
+
* @param {Error} err
|
|
173
|
+
* @param {Response} [res]
|
|
174
|
+
* @returns {Boolean}
|
|
175
|
+
*/
|
|
176
|
+
RequestBase.prototype._shouldRetry = function(err, res) {
|
|
177
|
+
if (!this._maxRetries || this._retries++ >= this._maxRetries) {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
if (this._retryCallback) {
|
|
181
|
+
try {
|
|
182
|
+
var override = this._retryCallback(err, res);
|
|
183
|
+
if (override === true) return true;
|
|
184
|
+
if (override === false) return false;
|
|
185
|
+
// undefined falls back to defaults
|
|
186
|
+
} catch(e) {
|
|
187
|
+
console.error(e);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (res && res.status && res.status >= 500 && res.status != 501) return true;
|
|
191
|
+
if (err) {
|
|
192
|
+
if (err.code && ~ERROR_CODES.indexOf(err.code)) return true;
|
|
193
|
+
// Superagent timeout
|
|
194
|
+
if (err.timeout && err.code == 'ECONNABORTED') return true;
|
|
195
|
+
if (err.crossDomain) return true;
|
|
196
|
+
}
|
|
197
|
+
return false;
|
|
198
|
+
};
|
|
199
|
+
|
|
159
200
|
/**
|
|
160
201
|
* Retry request
|
|
161
202
|
*
|
|
@@ -164,6 +205,7 @@ RequestBase.prototype.retry = function retry(count){
|
|
|
164
205
|
*/
|
|
165
206
|
|
|
166
207
|
RequestBase.prototype._retry = function() {
|
|
208
|
+
|
|
167
209
|
this.clearTimeout();
|
|
168
210
|
|
|
169
211
|
// node
|
|
@@ -192,14 +234,15 @@ RequestBase.prototype.then = function then(resolve, reject) {
|
|
|
192
234
|
if (this._endCalled) {
|
|
193
235
|
console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises");
|
|
194
236
|
}
|
|
195
|
-
this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
|
|
196
|
-
self.end(function(err, res){
|
|
197
|
-
if (err) innerReject(err);
|
|
237
|
+
this._fullfilledPromise = new Promise(function(innerResolve, innerReject) {
|
|
238
|
+
self.end(function(err, res) {
|
|
239
|
+
if (err) innerReject(err);
|
|
240
|
+
else innerResolve(res);
|
|
198
241
|
});
|
|
199
242
|
});
|
|
200
243
|
}
|
|
201
244
|
return this._fullfilledPromise.then(resolve, reject);
|
|
202
|
-
}
|
|
245
|
+
};
|
|
203
246
|
|
|
204
247
|
RequestBase.prototype.catch = function(cb) {
|
|
205
248
|
return this.then(undefined, cb);
|
|
@@ -212,7 +255,7 @@ RequestBase.prototype.catch = function(cb) {
|
|
|
212
255
|
RequestBase.prototype.use = function use(fn) {
|
|
213
256
|
fn(this);
|
|
214
257
|
return this;
|
|
215
|
-
}
|
|
258
|
+
};
|
|
216
259
|
|
|
217
260
|
RequestBase.prototype.ok = function(cb) {
|
|
218
261
|
if ('function' !== typeof cb) throw Error("Callback required");
|
|
@@ -232,7 +275,6 @@ RequestBase.prototype._isResponseOK = function(res) {
|
|
|
232
275
|
return res.status >= 200 && res.status < 300;
|
|
233
276
|
};
|
|
234
277
|
|
|
235
|
-
|
|
236
278
|
/**
|
|
237
279
|
* Get request header `field`.
|
|
238
280
|
* Case-insensitive.
|
|
@@ -331,9 +373,8 @@ RequestBase.prototype.unset = function(field){
|
|
|
331
373
|
* @api public
|
|
332
374
|
*/
|
|
333
375
|
RequestBase.prototype.field = function(name, val) {
|
|
334
|
-
|
|
335
376
|
// name should be either a string or an object.
|
|
336
|
-
if (null === name ||
|
|
377
|
+
if (null === name || undefined === name) {
|
|
337
378
|
throw new Error('.field(name, val) name can not be empty');
|
|
338
379
|
}
|
|
339
380
|
|
|
@@ -384,6 +425,24 @@ RequestBase.prototype.abort = function(){
|
|
|
384
425
|
return this;
|
|
385
426
|
};
|
|
386
427
|
|
|
428
|
+
RequestBase.prototype._auth = function(user, pass, options, base64Encoder) {
|
|
429
|
+
switch (options.type) {
|
|
430
|
+
case 'basic':
|
|
431
|
+
this.set('Authorization', 'Basic ' + base64Encoder(user + ':' + pass));
|
|
432
|
+
break;
|
|
433
|
+
|
|
434
|
+
case 'auto':
|
|
435
|
+
this.username = user;
|
|
436
|
+
this.password = pass;
|
|
437
|
+
break;
|
|
438
|
+
|
|
439
|
+
case 'bearer': // usage would be .auth(accessToken, { type: 'bearer' })
|
|
440
|
+
this.set('Authorization', 'Bearer ' + user);
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
return this;
|
|
444
|
+
};
|
|
445
|
+
|
|
387
446
|
/**
|
|
388
447
|
* Enable transmission of cookies with x-domain requests.
|
|
389
448
|
*
|
|
@@ -395,9 +454,9 @@ RequestBase.prototype.abort = function(){
|
|
|
395
454
|
* @api public
|
|
396
455
|
*/
|
|
397
456
|
|
|
398
|
-
RequestBase.prototype.withCredentials = function(on){
|
|
457
|
+
RequestBase.prototype.withCredentials = function(on) {
|
|
399
458
|
// This is browser-only functionality. Node side is no-op.
|
|
400
|
-
if(on==undefined) on = true;
|
|
459
|
+
if (on == undefined) on = true;
|
|
401
460
|
this._withCredentials = on;
|
|
402
461
|
return this;
|
|
403
462
|
};
|
|
@@ -439,16 +498,15 @@ RequestBase.prototype.maxResponseSize = function(n){
|
|
|
439
498
|
* @api public
|
|
440
499
|
*/
|
|
441
500
|
|
|
442
|
-
RequestBase.prototype.toJSON = function(){
|
|
501
|
+
RequestBase.prototype.toJSON = function() {
|
|
443
502
|
return {
|
|
444
503
|
method: this.method,
|
|
445
504
|
url: this.url,
|
|
446
505
|
data: this._data,
|
|
447
|
-
headers: this._header
|
|
506
|
+
headers: this._header,
|
|
448
507
|
};
|
|
449
508
|
};
|
|
450
509
|
|
|
451
|
-
|
|
452
510
|
/**
|
|
453
511
|
* Send `data` as the request body, defaulting the `.type()` to "json" when
|
|
454
512
|
* an object is given.
|
|
@@ -536,7 +594,6 @@ RequestBase.prototype.send = function(data){
|
|
|
536
594
|
return this;
|
|
537
595
|
};
|
|
538
596
|
|
|
539
|
-
|
|
540
597
|
/**
|
|
541
598
|
* Sort `querystring` by the sort function
|
|
542
599
|
*
|
|
@@ -634,4 +691,4 @@ RequestBase.prototype._setTimeouts = function() {
|
|
|
634
691
|
self._timeoutError('Response timeout of ', self._responseTimeout, 'ETIMEDOUT');
|
|
635
692
|
}, this._responseTimeout);
|
|
636
693
|
}
|
|
637
|
-
}
|
|
694
|
+
};
|
package/lib/response-base.js
CHANGED
package/lib/utils.js
CHANGED
|
@@ -57,12 +57,14 @@ exports.parseLinks = function(str){
|
|
|
57
57
|
* @api private
|
|
58
58
|
*/
|
|
59
59
|
|
|
60
|
-
exports.cleanHeader = function(header,
|
|
60
|
+
exports.cleanHeader = function(header, changesOrigin){
|
|
61
61
|
delete header['content-type'];
|
|
62
62
|
delete header['content-length'];
|
|
63
63
|
delete header['transfer-encoding'];
|
|
64
64
|
delete header['host'];
|
|
65
|
-
|
|
65
|
+
// secuirty
|
|
66
|
+
if (changesOrigin) {
|
|
67
|
+
delete header['authorization'];
|
|
66
68
|
delete header['cookie'];
|
|
67
69
|
}
|
|
68
70
|
return header;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superagent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.2",
|
|
4
4
|
"description": "elegant & feature rich browser / node HTTP with a fluent API",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"
|
|
6
|
+
"prepare": "make all",
|
|
7
7
|
"test": "make test"
|
|
8
8
|
},
|
|
9
9
|
"keywords": [
|