superagent 1.8.1 → 1.8.5

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 CHANGED
@@ -1,3 +1,10 @@
1
+ # 1.8.2 (2016-03-20)
2
+
3
+ * Fixed handling of HTTP status 204 with content-encoding: gzip (Andrew Shelton)
4
+ * Handling of FormData error events (scriptype)
5
+ * Fixed parsing of `vnd+json` MIME types (Kornel Lesiński)
6
+ * Aliased browser implementation of `.parse()` as `.serialize()` for forward compatibility
7
+
1
8
  # 1.8.1 (2016-03-14)
2
9
 
3
10
  * Fixed form-data incompatibility with IE9
package/bower.json CHANGED
@@ -1,7 +1,4 @@
1
1
  {
2
2
  "name": "superagent",
3
- "main": "lib/client.js",
4
- "dependencies": {
5
- "form-data": "form-data-superagent#^1.0.0"
6
- }
3
+ "main": "lib/client.js"
7
4
  }
package/component.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "superagent",
3
3
  "repo": "visionmedia/superagent",
4
- "description": "awesome http requests",
5
- "version": "1.2.0",
4
+ "version": "1.8.2",
5
+ "description": "elegant & feature rich browser / node HTTP with a fluent API",
6
6
  "keywords": [
7
7
  "http",
8
8
  "ajax",
package/lib/client.js CHANGED
@@ -390,6 +390,9 @@ Response.prototype.setHeaderProperties = function(header){
390
390
 
391
391
  Response.prototype.parseBody = function(str){
392
392
  var parse = request.parse[this.type];
393
+ if (!parse && isJSON(this.type)) {
394
+ parse = request.parse['application/json'];
395
+ }
393
396
  return parse && str && (str.length || str instanceof Object)
394
397
  ? parse(str)
395
398
  : null;
@@ -544,7 +547,7 @@ for (var key in requestBase) {
544
547
  Request.prototype.abort = function(){
545
548
  if (this.aborted) return;
546
549
  this.aborted = true;
547
- this.xhr.abort();
550
+ this.xhr && this.xhr.abort();
548
551
  this.clearTimeout();
549
552
  this.emit('abort');
550
553
  return this;
@@ -691,11 +694,17 @@ Request.prototype.query = function(val){
691
694
  */
692
695
 
693
696
  Request.prototype.attach = function(field, file, filename){
694
- if (!this._formData) this._formData = new root.FormData();
695
- this._formData.append(field, file, filename || file.name);
697
+ this._getFormData().append(field, file, filename || file.name);
696
698
  return this;
697
699
  };
698
700
 
701
+ Request.prototype._getFormData = function(){
702
+ if (!this._formData) {
703
+ this._formData = new root.FormData();
704
+ }
705
+ return this._formData;
706
+ };
707
+
699
708
  /**
700
709
  * Send `data` as the request body, defaulting the `.type()` to "json" when
701
710
  * an object is given.
@@ -764,6 +773,22 @@ Request.prototype.send = function(data){
764
773
  return this;
765
774
  };
766
775
 
776
+ /**
777
+ * @deprecated
778
+ */
779
+ Response.prototype.parse = function serialize(fn){
780
+ if (root.console) {
781
+ console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0");
782
+ }
783
+ this.serialize(fn);
784
+ return this;
785
+ };
786
+
787
+ Response.prototype.serialize = function serialize(fn){
788
+ this._parser = fn;
789
+ return this;
790
+ };
791
+
767
792
  /**
768
793
  * Invoke the callback with `err` and `res`
769
794
  * and handle arity check.
package/lib/node/index.js CHANGED
@@ -177,18 +177,28 @@ for (var key in requestBase) {
177
177
  */
178
178
 
179
179
  Request.prototype.attach = function(field, file, filename){
180
- if (!this._formData) this._formData = new FormData();
181
180
  if ('string' == typeof file) {
182
181
  if (!filename) filename = file;
183
182
  debug('creating `fs.ReadStream` instance for file: %s', file);
184
183
  file = fs.createReadStream(file);
185
- } else if(!filename && file.path) {
184
+ } else if (!filename && file.path) {
186
185
  filename = file.path;
187
186
  }
188
- this._formData.append(field, file, { filename: filename });
187
+ this._getFormData().append(field, file, { filename: filename });
189
188
  return this;
190
189
  };
191
190
 
191
+ Request.prototype._getFormData = function() {
192
+ if (!this._formData) {
193
+ this._formData = new FormData();
194
+ this._formData.on('error', function(err) {
195
+ this.emit('error', err);
196
+ this.abort();
197
+ }.bind(this));
198
+ }
199
+ return this._formData;
200
+ };
201
+
192
202
  /**
193
203
  * Set the max redirects to `n`.
194
204
  *
@@ -429,7 +439,7 @@ Request.prototype.pipe = function(stream, options){
429
439
  return self.redirect(res).pipe(stream, options);
430
440
  }
431
441
 
432
- if (/^(deflate|gzip)$/.test(res.headers['content-encoding'])) {
442
+ if (self._shouldUnzip(res)) {
433
443
  res.pipe(zlib.createUnzip()).pipe(stream, options);
434
444
  } else {
435
445
  res.pipe(stream, options);
@@ -662,7 +672,7 @@ Request.prototype.callback = function(err, res){
662
672
  // Avoid the error which is emitted from 'socket hang up' to cause the fn undefined error on JS runtime.
663
673
  var fn = this._callback || noop;
664
674
  this.clearTimeout();
665
- if (this.called) return console.warn('double callback!');
675
+ if (this.called) return console.warn('superagent: double callback bug. Upgrade to v3.2+ to fix this');
666
676
  this.called = true;
667
677
 
668
678
  if (err) {
@@ -811,10 +821,11 @@ Request.prototype.end = function(fn){
811
821
  }
812
822
 
813
823
  // zlib support
814
- if (/^(deflate|gzip)$/.test(res.headers['content-encoding'])) {
824
+ if (self._shouldUnzip(res)) {
815
825
  utils.unzip(req, res);
816
826
  }
817
827
 
828
+
818
829
  // don't buffer multipart
819
830
  if (multipart) buffer = false;
820
831
 
@@ -962,6 +973,25 @@ Request.prototype.end = function(fn){
962
973
  return this;
963
974
  };
964
975
 
976
+ /**
977
+ * Check whether response has a non-0-sized gzip-encoded body
978
+ */
979
+ Request.prototype._shouldUnzip = function(res){
980
+ if (res.statusCode === 204 || res.statusCode === 304) {
981
+ // These aren't supposed to have any body
982
+ return false;
983
+ }
984
+
985
+ // header content is a string, and distinction between 0 and no information is crucial
986
+ if ('0' === res.headers['content-length']) {
987
+ // We know that the body is empty (unfortunately, this check does not cover chunked encoding)
988
+ return false;
989
+ }
990
+
991
+ // console.log(res);
992
+ return /^\s*(?:deflate|gzip)\s*$/.test(res.headers['content-encoding']);
993
+ };
994
+
965
995
  /**
966
996
  * To json.
967
997
  *
package/lib/node/part.js CHANGED
@@ -125,8 +125,7 @@ Part.prototype._attach = function(){
125
125
  if (!this._name) throw new Error('must call `Part#name()` first!');
126
126
 
127
127
  // add `this` Stream's readable side as a stream for this Part
128
- if (!this._req._formData) this._req._formData = new FormData();
129
- this._req._formData.append(this._name, this, {
128
+ this._req._getFormData().append(this._name, this, {
130
129
  contentType: this._type,
131
130
  filename: this._filename
132
131
  });
@@ -161,10 +161,6 @@ exports.unset = function(field){
161
161
  * @api public
162
162
  */
163
163
  exports.field = function(name, val) {
164
- if (!this._formData) {
165
- var FormData = require('form-data'); // browserify compatible. May throw if FormData is not supported natively.
166
- this._formData = new FormData();
167
- }
168
- this._formData.append(name, val);
164
+ this._getFormData().append(name, val);
169
165
  return this;
170
166
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superagent",
3
- "version": "1.8.1",
3
+ "version": "1.8.5",
4
4
  "description": "elegant & feature rich browser / node HTTP with a fluent API",
5
5
  "scripts": {
6
6
  "prepublish": "make all",
@@ -15,6 +15,8 @@
15
15
  "license": "MIT",
16
16
  "author": "TJ Holowaychuk <tj@vision-media.ca>",
17
17
  "contributors": [
18
+ "Kornel Lesiński <kornel@geekhood.net>",
19
+ "Peter Lyons <pete@peterlyons.com>",
18
20
  "Hunter Loftis <hunter@hunterloftis.com>"
19
21
  ],
20
22
  "repository": {
package/superagent.js CHANGED
@@ -177,15 +177,11 @@ exports.unset = function(field){
177
177
  * @api public
178
178
  */
179
179
  exports.field = function(name, val) {
180
- if (!this._formData) {
181
- var FormData = require('form-data'); // browserify compatible. May throw if FormData is not supported natively.
182
- this._formData = new FormData();
183
- }
184
- this._formData.append(name, val);
180
+ this._getFormData().append(name, val);
185
181
  return this;
186
182
  };
187
183
 
188
- },{"./is-object":1,"form-data":5}],3:[function(require,module,exports){
184
+ },{"./is-object":1}],3:[function(require,module,exports){
189
185
  // The node and browser modules expose versions of this with the
190
186
  // appropriate constructor function bound as first argument
191
187
  /**
@@ -220,171 +216,171 @@ function request(RequestConstructor, method, url) {
220
216
  module.exports = request;
221
217
 
222
218
  },{}],4:[function(require,module,exports){
223
-
224
- /**
225
- * Expose `Emitter`.
226
- */
227
-
228
- module.exports = Emitter;
229
-
230
- /**
231
- * Initialize a new `Emitter`.
232
- *
233
- * @api public
234
- */
235
-
236
- function Emitter(obj) {
237
- if (obj) return mixin(obj);
238
- };
239
-
240
- /**
241
- * Mixin the emitter properties.
242
- *
243
- * @param {Object} obj
244
- * @return {Object}
245
- * @api private
246
- */
247
-
248
- function mixin(obj) {
249
- for (var key in Emitter.prototype) {
250
- obj[key] = Emitter.prototype[key];
251
- }
252
- return obj;
253
- }
254
-
255
- /**
256
- * Listen on the given `event` with `fn`.
257
- *
258
- * @param {String} event
259
- * @param {Function} fn
260
- * @return {Emitter}
261
- * @api public
262
- */
263
-
264
- Emitter.prototype.on =
265
- Emitter.prototype.addEventListener = function(event, fn){
266
- this._callbacks = this._callbacks || {};
267
- (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
268
- .push(fn);
269
- return this;
270
- };
271
-
272
- /**
273
- * Adds an `event` listener that will be invoked a single
274
- * time then automatically removed.
275
- *
276
- * @param {String} event
277
- * @param {Function} fn
278
- * @return {Emitter}
279
- * @api public
280
- */
281
-
282
- Emitter.prototype.once = function(event, fn){
283
- function on() {
284
- this.off(event, on);
285
- fn.apply(this, arguments);
286
- }
287
-
288
- on.fn = fn;
289
- this.on(event, on);
290
- return this;
291
- };
292
-
293
- /**
294
- * Remove the given callback for `event` or all
295
- * registered callbacks.
296
- *
297
- * @param {String} event
298
- * @param {Function} fn
299
- * @return {Emitter}
300
- * @api public
301
- */
302
-
303
- Emitter.prototype.off =
304
- Emitter.prototype.removeListener =
305
- Emitter.prototype.removeAllListeners =
306
- Emitter.prototype.removeEventListener = function(event, fn){
307
- this._callbacks = this._callbacks || {};
308
-
309
- // all
310
- if (0 == arguments.length) {
311
- this._callbacks = {};
312
- return this;
313
- }
314
-
315
- // specific event
316
- var callbacks = this._callbacks['$' + event];
317
- if (!callbacks) return this;
318
-
319
- // remove all handlers
320
- if (1 == arguments.length) {
321
- delete this._callbacks['$' + event];
322
- return this;
323
- }
324
-
325
- // remove specific handler
326
- var cb;
327
- for (var i = 0; i < callbacks.length; i++) {
328
- cb = callbacks[i];
329
- if (cb === fn || cb.fn === fn) {
330
- callbacks.splice(i, 1);
331
- break;
332
- }
333
- }
334
- return this;
335
- };
336
-
337
- /**
338
- * Emit `event` with the given args.
339
- *
340
- * @param {String} event
341
- * @param {Mixed} ...
342
- * @return {Emitter}
343
- */
344
-
345
- Emitter.prototype.emit = function(event){
346
- this._callbacks = this._callbacks || {};
347
- var args = [].slice.call(arguments, 1)
348
- , callbacks = this._callbacks['$' + event];
349
-
350
- if (callbacks) {
351
- callbacks = callbacks.slice(0);
352
- for (var i = 0, len = callbacks.length; i < len; ++i) {
353
- callbacks[i].apply(this, args);
354
- }
355
- }
356
-
357
- return this;
358
- };
359
-
360
- /**
361
- * Return array of callbacks for `event`.
362
- *
363
- * @param {String} event
364
- * @return {Array}
365
- * @api public
366
- */
367
-
368
- Emitter.prototype.listeners = function(event){
369
- this._callbacks = this._callbacks || {};
370
- return this._callbacks['$' + event] || [];
371
- };
372
-
373
- /**
374
- * Check if this emitter has `event` handlers.
375
- *
376
- * @param {String} event
377
- * @return {Boolean}
378
- * @api public
379
- */
380
-
381
- Emitter.prototype.hasListeners = function(event){
382
- return !! this.listeners(event).length;
383
- };
219
+
220
+ /**
221
+ * Expose `Emitter`.
222
+ */
223
+
224
+ if (typeof module !== 'undefined') {
225
+ module.exports = Emitter;
226
+ }
227
+
228
+ /**
229
+ * Initialize a new `Emitter`.
230
+ *
231
+ * @api public
232
+ */
233
+
234
+ function Emitter(obj) {
235
+ if (obj) return mixin(obj);
236
+ };
237
+
238
+ /**
239
+ * Mixin the emitter properties.
240
+ *
241
+ * @param {Object} obj
242
+ * @return {Object}
243
+ * @api private
244
+ */
245
+
246
+ function mixin(obj) {
247
+ for (var key in Emitter.prototype) {
248
+ obj[key] = Emitter.prototype[key];
249
+ }
250
+ return obj;
251
+ }
252
+
253
+ /**
254
+ * Listen on the given `event` with `fn`.
255
+ *
256
+ * @param {String} event
257
+ * @param {Function} fn
258
+ * @return {Emitter}
259
+ * @api public
260
+ */
261
+
262
+ Emitter.prototype.on =
263
+ Emitter.prototype.addEventListener = function(event, fn){
264
+ this._callbacks = this._callbacks || {};
265
+ (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
266
+ .push(fn);
267
+ return this;
268
+ };
269
+
270
+ /**
271
+ * Adds an `event` listener that will be invoked a single
272
+ * time then automatically removed.
273
+ *
274
+ * @param {String} event
275
+ * @param {Function} fn
276
+ * @return {Emitter}
277
+ * @api public
278
+ */
279
+
280
+ Emitter.prototype.once = function(event, fn){
281
+ function on() {
282
+ this.off(event, on);
283
+ fn.apply(this, arguments);
284
+ }
285
+
286
+ on.fn = fn;
287
+ this.on(event, on);
288
+ return this;
289
+ };
290
+
291
+ /**
292
+ * Remove the given callback for `event` or all
293
+ * registered callbacks.
294
+ *
295
+ * @param {String} event
296
+ * @param {Function} fn
297
+ * @return {Emitter}
298
+ * @api public
299
+ */
300
+
301
+ Emitter.prototype.off =
302
+ Emitter.prototype.removeListener =
303
+ Emitter.prototype.removeAllListeners =
304
+ Emitter.prototype.removeEventListener = function(event, fn){
305
+ this._callbacks = this._callbacks || {};
306
+
307
+ // all
308
+ if (0 == arguments.length) {
309
+ this._callbacks = {};
310
+ return this;
311
+ }
312
+
313
+ // specific event
314
+ var callbacks = this._callbacks['$' + event];
315
+ if (!callbacks) return this;
316
+
317
+ // remove all handlers
318
+ if (1 == arguments.length) {
319
+ delete this._callbacks['$' + event];
320
+ return this;
321
+ }
322
+
323
+ // remove specific handler
324
+ var cb;
325
+ for (var i = 0; i < callbacks.length; i++) {
326
+ cb = callbacks[i];
327
+ if (cb === fn || cb.fn === fn) {
328
+ callbacks.splice(i, 1);
329
+ break;
330
+ }
331
+ }
332
+ return this;
333
+ };
334
+
335
+ /**
336
+ * Emit `event` with the given args.
337
+ *
338
+ * @param {String} event
339
+ * @param {Mixed} ...
340
+ * @return {Emitter}
341
+ */
342
+
343
+ Emitter.prototype.emit = function(event){
344
+ this._callbacks = this._callbacks || {};
345
+ var args = [].slice.call(arguments, 1)
346
+ , callbacks = this._callbacks['$' + event];
347
+
348
+ if (callbacks) {
349
+ callbacks = callbacks.slice(0);
350
+ for (var i = 0, len = callbacks.length; i < len; ++i) {
351
+ callbacks[i].apply(this, args);
352
+ }
353
+ }
354
+
355
+ return this;
356
+ };
357
+
358
+ /**
359
+ * Return array of callbacks for `event`.
360
+ *
361
+ * @param {String} event
362
+ * @return {Array}
363
+ * @api public
364
+ */
365
+
366
+ Emitter.prototype.listeners = function(event){
367
+ this._callbacks = this._callbacks || {};
368
+ return this._callbacks['$' + event] || [];
369
+ };
370
+
371
+ /**
372
+ * Check if this emitter has `event` handlers.
373
+ *
374
+ * @param {String} event
375
+ * @return {Boolean}
376
+ * @api public
377
+ */
378
+
379
+ Emitter.prototype.hasListeners = function(event){
380
+ return !! this.listeners(event).length;
381
+ };
384
382
 
385
383
  },{}],5:[function(require,module,exports){
386
- module.exports = FormData;
387
- },{}],6:[function(require,module,exports){
388
384
 
389
385
  /**
390
386
  * Reduce `arr` with `fn`.
@@ -409,7 +405,7 @@ module.exports = function(arr, fn, initial){
409
405
 
410
406
  return curr;
411
407
  };
412
- },{}],7:[function(require,module,exports){
408
+ },{}],6:[function(require,module,exports){
413
409
  /**
414
410
  * Module dependencies.
415
411
  */
@@ -802,6 +798,9 @@ Response.prototype.setHeaderProperties = function(header){
802
798
 
803
799
  Response.prototype.parseBody = function(str){
804
800
  var parse = request.parse[this.type];
801
+ if (!parse && isJSON(this.type)) {
802
+ parse = request.parse['application/json'];
803
+ }
805
804
  return parse && str && (str.length || str instanceof Object)
806
805
  ? parse(str)
807
806
  : null;
@@ -956,7 +955,7 @@ for (var key in requestBase) {
956
955
  Request.prototype.abort = function(){
957
956
  if (this.aborted) return;
958
957
  this.aborted = true;
959
- this.xhr.abort();
958
+ this.xhr && this.xhr.abort();
960
959
  this.clearTimeout();
961
960
  this.emit('abort');
962
961
  return this;
@@ -1103,11 +1102,17 @@ Request.prototype.query = function(val){
1103
1102
  */
1104
1103
 
1105
1104
  Request.prototype.attach = function(field, file, filename){
1106
- if (!this._formData) this._formData = new root.FormData();
1107
- this._formData.append(field, file, filename || file.name);
1105
+ this._getFormData().append(field, file, filename || file.name);
1108
1106
  return this;
1109
1107
  };
1110
1108
 
1109
+ Request.prototype._getFormData = function(){
1110
+ if (!this._formData) {
1111
+ this._formData = new root.FormData();
1112
+ }
1113
+ return this._formData;
1114
+ };
1115
+
1111
1116
  /**
1112
1117
  * Send `data` as the request body, defaulting the `.type()` to "json" when
1113
1118
  * an object is given.
@@ -1176,6 +1181,22 @@ Request.prototype.send = function(data){
1176
1181
  return this;
1177
1182
  };
1178
1183
 
1184
+ /**
1185
+ * @deprecated
1186
+ */
1187
+ Response.prototype.parse = function serialize(fn){
1188
+ if (root.console) {
1189
+ console.warn("Client-side parse() method has been renamed to serialize(). This method is not compatible with superagent v2.0");
1190
+ }
1191
+ this.serialize(fn);
1192
+ return this;
1193
+ };
1194
+
1195
+ Response.prototype.serialize = function serialize(fn){
1196
+ this._parser = fn;
1197
+ return this;
1198
+ };
1199
+
1179
1200
  /**
1180
1201
  * Invoke the callback with `err` and `res`
1181
1202
  * and handle arity check.
@@ -1463,5 +1484,5 @@ request.put = function(url, data, fn){
1463
1484
  return req;
1464
1485
  };
1465
1486
 
1466
- },{"./is-object":1,"./request":3,"./request-base":2,"emitter":4,"reduce":6}]},{},[7])(7)
1487
+ },{"./is-object":1,"./request":3,"./request-base":2,"emitter":4,"reduce":5}]},{},[6])(6)
1467
1488
  });