superagent 2.0.0 → 2.3.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/.travis.yml +3 -4
- package/History.md +20 -0
- package/Readme.md +7 -9
- package/component.json +2 -3
- package/docs/index.md +29 -16
- package/docs/tail.html +19 -4
- package/lib/client.js +63 -65
- package/lib/node/agent.js +8 -2
- package/lib/node/index.js +88 -81
- package/lib/node/utils.js +5 -0
- package/lib/request-base.js +30 -4
- package/package.json +1 -3
- package/superagent.js +94 -95
- package/docs/highlight.js +0 -17
- package/docs/jquery-ui.min.js +0 -6
- package/docs/jquery.js +0 -4
- package/docs/jquery.tocify.min.js +0 -4
package/lib/node/index.js
CHANGED
|
@@ -352,10 +352,7 @@ Request.prototype.pipe = function(stream, options){
|
|
|
352
352
|
}
|
|
353
353
|
|
|
354
354
|
self.res = res;
|
|
355
|
-
|
|
356
|
-
self.response = response;
|
|
357
|
-
self.emit('response', response);
|
|
358
|
-
response.redirects = self._redirectList;
|
|
355
|
+
self._emitResponse();
|
|
359
356
|
if (self._aborted) return;
|
|
360
357
|
|
|
361
358
|
if (self._shouldUnzip(res)) {
|
|
@@ -379,9 +376,7 @@ Request.prototype.pipe = function(stream, options){
|
|
|
379
376
|
*/
|
|
380
377
|
|
|
381
378
|
Request.prototype.buffer = function(val){
|
|
382
|
-
this._buffer = false
|
|
383
|
-
? false
|
|
384
|
-
: true;
|
|
379
|
+
this._buffer = (false !== val);
|
|
385
380
|
return this;
|
|
386
381
|
};
|
|
387
382
|
|
|
@@ -494,6 +489,32 @@ Request.prototype.ca = function(cert){
|
|
|
494
489
|
return this;
|
|
495
490
|
};
|
|
496
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Set the client certificate key option for https request.
|
|
494
|
+
*
|
|
495
|
+
* @param {Buffer | String} cert
|
|
496
|
+
* @return {Request} for chaining
|
|
497
|
+
* @api public
|
|
498
|
+
*/
|
|
499
|
+
|
|
500
|
+
Request.prototype.key = function(cert){
|
|
501
|
+
this._key = cert;
|
|
502
|
+
return this;
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Set the client certificate option for https request.
|
|
507
|
+
*
|
|
508
|
+
* @param {Buffer | String} cert
|
|
509
|
+
* @return {Request} for chaining
|
|
510
|
+
* @api public
|
|
511
|
+
*/
|
|
512
|
+
|
|
513
|
+
Request.prototype.cert = function(cert){
|
|
514
|
+
this._cert = cert;
|
|
515
|
+
return this;
|
|
516
|
+
};
|
|
517
|
+
|
|
497
518
|
/**
|
|
498
519
|
* Return an http[s] request.
|
|
499
520
|
*
|
|
@@ -519,6 +540,8 @@ Request.prototype.request = function(){
|
|
|
519
540
|
options.path = url.pathname;
|
|
520
541
|
options.host = url.hostname;
|
|
521
542
|
options.ca = this._ca;
|
|
543
|
+
options.key = this._key;
|
|
544
|
+
options.cert = this._cert;
|
|
522
545
|
options.agent = this._agent;
|
|
523
546
|
|
|
524
547
|
// initiate request
|
|
@@ -616,7 +639,7 @@ Request.prototype.callback = function(err, res){
|
|
|
616
639
|
*/
|
|
617
640
|
|
|
618
641
|
Request.prototype._appendQueryString = function(req){
|
|
619
|
-
var querystring = qs.stringify(this.qs, { indices: false });
|
|
642
|
+
var querystring = qs.stringify(this.qs, { indices: false, strictNullHandling: true });
|
|
620
643
|
querystring += ((querystring.length && this.qsRaw.length) ? '&' : '') + this.qsRaw.join('&');
|
|
621
644
|
req.path += querystring.length
|
|
622
645
|
? (~req.path.indexOf('?') ? '&' : '?') + querystring
|
|
@@ -632,6 +655,18 @@ Request.prototype._appendQueryString = function(req){
|
|
|
632
655
|
* @api public
|
|
633
656
|
*/
|
|
634
657
|
|
|
658
|
+
Request.prototype._emitResponse = function(body, files){
|
|
659
|
+
var response = new Response(this);
|
|
660
|
+
this.response = response;
|
|
661
|
+
response.redirects = this._redirectList;
|
|
662
|
+
if (undefined !== body) {
|
|
663
|
+
response.body = body;
|
|
664
|
+
}
|
|
665
|
+
response.files = files;
|
|
666
|
+
this.emit('response', response);
|
|
667
|
+
return response;
|
|
668
|
+
};
|
|
669
|
+
|
|
635
670
|
Request.prototype.end = function(fn){
|
|
636
671
|
var self = this;
|
|
637
672
|
var data = this._data;
|
|
@@ -658,6 +693,7 @@ Request.prototype.end = function(fn){
|
|
|
658
693
|
var err = new Error('timeout of ' + timeout + 'ms exceeded');
|
|
659
694
|
err.timeout = timeout;
|
|
660
695
|
err.code = 'ECONNABORTED';
|
|
696
|
+
self.timedout = true;
|
|
661
697
|
self.abort();
|
|
662
698
|
self.callback(err);
|
|
663
699
|
}, timeout);
|
|
@@ -691,10 +727,7 @@ Request.prototype.end = function(fn){
|
|
|
691
727
|
|
|
692
728
|
var max = self._maxRedirects;
|
|
693
729
|
var mime = utils.type(res.headers['content-type'] || '') || 'text/plain';
|
|
694
|
-
var
|
|
695
|
-
var type = mime.split('/');
|
|
696
|
-
var subtype = type[1];
|
|
697
|
-
var type = type[0];
|
|
730
|
+
var type = mime.split('/')[0];
|
|
698
731
|
var multipart = 'multipart' == type;
|
|
699
732
|
var redirect = isRedirect(res.statusCode);
|
|
700
733
|
var parser = self._parser;
|
|
@@ -707,12 +740,8 @@ Request.prototype.end = function(fn){
|
|
|
707
740
|
}
|
|
708
741
|
|
|
709
742
|
if ('HEAD' == self.method) {
|
|
710
|
-
var response = new Response(self);
|
|
711
|
-
self.response = response;
|
|
712
|
-
response.redirects = self._redirectList;
|
|
713
|
-
self.emit('response', response);
|
|
714
|
-
self.callback(null, response);
|
|
715
743
|
self.emit('end');
|
|
744
|
+
self.callback(null, self._emitResponse());
|
|
716
745
|
return;
|
|
717
746
|
}
|
|
718
747
|
|
|
@@ -721,64 +750,50 @@ Request.prototype.end = function(fn){
|
|
|
721
750
|
utils.unzip(req, res);
|
|
722
751
|
}
|
|
723
752
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
// check for images, one more special treatment
|
|
746
|
-
if (!parser && isImage(mime)) {
|
|
747
|
-
exports.parse.image(res, function(err, obj){
|
|
748
|
-
if (err) return self.callback(err);
|
|
749
|
-
var response = new Response(self);
|
|
750
|
-
self.response = response;
|
|
751
|
-
response.body = obj;
|
|
752
|
-
response.redirects = self._redirectList;
|
|
753
|
-
self.emit('end');
|
|
754
|
-
self.callback(null, response);
|
|
755
|
-
});
|
|
756
|
-
return;
|
|
753
|
+
if (!parser) {
|
|
754
|
+
if (multipart) {
|
|
755
|
+
var form = new formidable.IncomingForm();
|
|
756
|
+
parser = form.parse.bind(form);
|
|
757
|
+
buffer = true;
|
|
758
|
+
} else if (isImage(mime)) {
|
|
759
|
+
parser = exports.parse.image;
|
|
760
|
+
buffer = true; // For backwards-compatibility buffering default is ad-hoc MIME-dependent
|
|
761
|
+
} else if ('text' == type) {
|
|
762
|
+
parser = exports.parse.text;
|
|
763
|
+
buffer = (buffer !== false);
|
|
764
|
+
} else if (exports.parse[mime]) {
|
|
765
|
+
parser = exports.parse[mime];
|
|
766
|
+
|
|
767
|
+
// everyone wants their own white-labeled json
|
|
768
|
+
} else if (isJSON(mime)) {
|
|
769
|
+
parser = exports.parse['application/json'];
|
|
770
|
+
buffer = (buffer !== false);
|
|
771
|
+
} else if (buffer) {
|
|
772
|
+
parser = exports.parse.text;
|
|
773
|
+
}
|
|
757
774
|
}
|
|
758
775
|
|
|
759
776
|
// by default only buffer text/*, json and messed up thing from hell
|
|
760
|
-
if (
|
|
761
|
-
|
|
762
|
-
// parser
|
|
763
|
-
var parse = 'text' == type
|
|
764
|
-
? exports.parse.text
|
|
765
|
-
: exports.parse[mime];
|
|
777
|
+
if (undefined === buffer && isText(mime) || isJSON(mime)) buffer = true;
|
|
766
778
|
|
|
767
|
-
|
|
768
|
-
if (
|
|
779
|
+
var parserHandlesEnd = false;
|
|
780
|
+
if (parser) {
|
|
781
|
+
try {
|
|
782
|
+
// Unbuffered parsers are supposed to emit response early,
|
|
783
|
+
// which is weird BTW, because response.body won't be there.
|
|
784
|
+
parserHandlesEnd = buffer;
|
|
769
785
|
|
|
770
|
-
|
|
771
|
-
|
|
786
|
+
parser(res, function(err, obj, files) {
|
|
787
|
+
if (err && !self._aborted) {
|
|
788
|
+
return self.callback(err);
|
|
789
|
+
}
|
|
772
790
|
|
|
773
|
-
|
|
774
|
-
if (parser) parse = parser;
|
|
791
|
+
res.body = obj; // Deprecated. For backwards compat only. It's not the response object user sees.
|
|
775
792
|
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
if (err && !self._aborted) self.callback(err);
|
|
781
|
-
res.body = obj;
|
|
793
|
+
if (parserHandlesEnd) {
|
|
794
|
+
self.emit('end');
|
|
795
|
+
self.callback(null, self._emitResponse(obj, files));
|
|
796
|
+
}
|
|
782
797
|
});
|
|
783
798
|
} catch (err) {
|
|
784
799
|
self.callback(err);
|
|
@@ -786,15 +801,12 @@ Request.prototype.end = function(fn){
|
|
|
786
801
|
}
|
|
787
802
|
}
|
|
788
803
|
|
|
804
|
+
self.res = res;
|
|
805
|
+
|
|
789
806
|
// unbuffered
|
|
790
807
|
if (!buffer) {
|
|
791
808
|
debug('unbuffered %s %s', self.method, self.url);
|
|
792
|
-
self.
|
|
793
|
-
var response = new Response(self);
|
|
794
|
-
self.response = response;
|
|
795
|
-
response.redirects = self._redirectList;
|
|
796
|
-
self.emit('response', response);
|
|
797
|
-
self.callback(null, response);
|
|
809
|
+
self.callback(null, self._emitResponse());
|
|
798
810
|
if (multipart) return // allow multipart to handle end event
|
|
799
811
|
res.on('end', function(){
|
|
800
812
|
debug('end %s %s', self.method, self.url);
|
|
@@ -804,19 +816,14 @@ Request.prototype.end = function(fn){
|
|
|
804
816
|
}
|
|
805
817
|
|
|
806
818
|
// terminating events
|
|
807
|
-
self.res = res;
|
|
808
819
|
res.on('error', function(err){
|
|
809
820
|
self.callback(err, null);
|
|
810
821
|
});
|
|
811
|
-
res.on('end', function(){
|
|
822
|
+
if (!parserHandlesEnd) res.on('end', function(){
|
|
812
823
|
debug('end %s %s', self.method, self.url);
|
|
813
824
|
// TODO: unless buffering emit earlier to stream
|
|
814
|
-
var response = new Response(self);
|
|
815
|
-
self.response = response;
|
|
816
|
-
response.redirects = self._redirectList;
|
|
817
|
-
self.emit('response', response);
|
|
818
|
-
self.callback(null, response);
|
|
819
825
|
self.emit('end');
|
|
826
|
+
self.callback(null, self._emitResponse());
|
|
820
827
|
});
|
|
821
828
|
});
|
|
822
829
|
|
package/lib/node/utils.js
CHANGED
|
@@ -83,6 +83,10 @@ exports.unzip = function(req, res){
|
|
|
83
83
|
stream.req = req;
|
|
84
84
|
|
|
85
85
|
unzip.on('error', function(err){
|
|
86
|
+
if (err && err.code === 'Z_BUF_ERROR') { // unexpected end of file is ignored by browsers and curl
|
|
87
|
+
stream.emit('end');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
86
90
|
stream.emit('error', err);
|
|
87
91
|
});
|
|
88
92
|
|
|
@@ -119,6 +123,7 @@ exports.unzip = function(req, res){
|
|
|
119
123
|
} else {
|
|
120
124
|
_on.call(res, type, fn);
|
|
121
125
|
}
|
|
126
|
+
return this;
|
|
122
127
|
};
|
|
123
128
|
};
|
|
124
129
|
|
package/lib/request-base.js
CHANGED
|
@@ -77,6 +77,10 @@ exports.then = function then(resolve, reject) {
|
|
|
77
77
|
return this._fullfilledPromise.then(resolve, reject);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
exports.catch = function(cb) {
|
|
81
|
+
return this.then(undefined, cb);
|
|
82
|
+
};
|
|
83
|
+
|
|
80
84
|
/**
|
|
81
85
|
* Allow for extension
|
|
82
86
|
*/
|
|
@@ -166,21 +170,42 @@ exports.unset = function(field){
|
|
|
166
170
|
};
|
|
167
171
|
|
|
168
172
|
/**
|
|
169
|
-
* Write the field `name` and `val
|
|
170
|
-
* request bodies.
|
|
173
|
+
* Write the field `name` and `val`, or multiple fields with one object
|
|
174
|
+
* for "multipart/form-data" request bodies.
|
|
171
175
|
*
|
|
172
176
|
* ``` js
|
|
173
177
|
* request.post('/upload')
|
|
174
178
|
* .field('foo', 'bar')
|
|
175
179
|
* .end(callback);
|
|
180
|
+
*
|
|
181
|
+
* request.post('/upload')
|
|
182
|
+
* .field({ foo: 'bar', baz: 'qux' })
|
|
183
|
+
* .end(callback);
|
|
176
184
|
* ```
|
|
177
185
|
*
|
|
178
|
-
* @param {String} name
|
|
186
|
+
* @param {String|Object} name
|
|
179
187
|
* @param {String|Blob|File|Buffer|fs.ReadStream} val
|
|
180
188
|
* @return {Request} for chaining
|
|
181
189
|
* @api public
|
|
182
190
|
*/
|
|
183
191
|
exports.field = function(name, val) {
|
|
192
|
+
|
|
193
|
+
// name should be either a string or an object.
|
|
194
|
+
if (null === name || undefined === name) {
|
|
195
|
+
throw new Error('.field(name, val) name can not be empty');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (isObject(name)) {
|
|
199
|
+
for (var key in name) {
|
|
200
|
+
this.field(key, name[key]);
|
|
201
|
+
}
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// val should be defined now
|
|
206
|
+
if (null === val || undefined === val) {
|
|
207
|
+
throw new Error('.field(name, val) val can not be empty');
|
|
208
|
+
}
|
|
184
209
|
this._getFormData().append(name, val);
|
|
185
210
|
return this;
|
|
186
211
|
};
|
|
@@ -246,7 +271,8 @@ exports.toJSON = function(){
|
|
|
246
271
|
return {
|
|
247
272
|
method: this.method,
|
|
248
273
|
url: this.url,
|
|
249
|
-
data: this._data
|
|
274
|
+
data: this._data,
|
|
275
|
+
headers: this._header
|
|
250
276
|
};
|
|
251
277
|
};
|
|
252
278
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superagent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "elegant & feature rich browser / node HTTP with a fluent API",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"prepublish": "make all",
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
"methods": "^1.1.1",
|
|
32
32
|
"cookiejar": "^2.0.6",
|
|
33
33
|
"debug": "^2.2.0",
|
|
34
|
-
"reduce-component": "^1.0.1",
|
|
35
34
|
"extend": "^3.0.0",
|
|
36
35
|
"form-data": "1.0.0-rc4",
|
|
37
36
|
"readable-stream": "^2.0.5"
|
|
@@ -54,7 +53,6 @@
|
|
|
54
53
|
"browser": {
|
|
55
54
|
"./lib/node/index.js": "./lib/client.js",
|
|
56
55
|
"emitter": "component-emitter",
|
|
57
|
-
"reduce": "reduce-component",
|
|
58
56
|
"./test/support/server.js": "./test/support/blank.js"
|
|
59
57
|
},
|
|
60
58
|
"component": {
|