UNPKG

44.2 kBJavaScriptView Raw
1(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.superagent = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2/**
3 * Check if `fn` is a function.
4 *
5 * @param {Function} fn
6 * @return {Boolean}
7 * @api private
8 */
9var isObject = require('./is-object');
10
11function isFunction(fn) {
12 var tag = isObject(fn) ? Object.prototype.toString.call(fn) : '';
13 return tag === '[object Function]';
14}
15
16module.exports = isFunction;
17
18},{"./is-object":2}],2:[function(require,module,exports){
19/**
20 * Check if `obj` is an object.
21 *
22 * @param {Object} obj
23 * @return {Boolean}
24 * @api private
25 */
26
27function isObject(obj) {
28 return null !== obj && 'object' === typeof obj;
29}
30
31module.exports = isObject;
32
33},{}],3:[function(require,module,exports){
34/**
35 * Module of mixed-in functions shared between node and client code
36 */
37var isObject = require('./is-object');
38
39/**
40 * Expose `RequestBase`.
41 */
42
43module.exports = RequestBase;
44
45/**
46 * Initialize a new `RequestBase`.
47 *
48 * @api public
49 */
50
51function RequestBase(obj) {
52 if (obj) return mixin(obj);
53}
54
55/**
56 * Mixin the prototype properties.
57 *
58 * @param {Object} obj
59 * @return {Object}
60 * @api private
61 */
62
63function mixin(obj) {
64 for (var key in RequestBase.prototype) {
65 obj[key] = RequestBase.prototype[key];
66 }
67 return obj;
68}
69
70/**
71 * Clear previous timeout.
72 *
73 * @return {Request} for chaining
74 * @api public
75 */
76
77RequestBase.prototype.clearTimeout = function _clearTimeout(){
78 clearTimeout(this._timer);
79 clearTimeout(this._responseTimeoutTimer);
80 delete this._timer;
81 delete this._responseTimeoutTimer;
82 return this;
83};
84
85/**
86 * Override default response body parser
87 *
88 * This function will be called to convert incoming data into request.body
89 *
90 * @param {Function}
91 * @api public
92 */
93
94RequestBase.prototype.parse = function parse(fn){
95 this._parser = fn;
96 return this;
97};
98
99/**
100 * Set format of binary response body.
101 * In browser valid formats are 'blob' and 'arraybuffer',
102 * which return Blob and ArrayBuffer, respectively.
103 *
104 * In Node all values result in Buffer.
105 *
106 * Examples:
107 *
108 * req.get('/')
109 * .responseType('blob')
110 * .end(callback);
111 *
112 * @param {String} val
113 * @return {Request} for chaining
114 * @api public
115 */
116
117RequestBase.prototype.responseType = function(val){
118 this._responseType = val;
119 return this;
120};
121
122/**
123 * Override default request body serializer
124 *
125 * This function will be called to convert data set via .send or .attach into payload to send
126 *
127 * @param {Function}
128 * @api public
129 */
130
131RequestBase.prototype.serialize = function serialize(fn){
132 this._serializer = fn;
133 return this;
134};
135
136/**
137 * Set timeouts.
138 *
139 * - response timeout is time between sending request and receiving the first byte of the response. Includes DNS and connection time.
140 * - deadline is the time from start of the request to receiving response body in full. If the deadline is too short large files may not load at all on slow connections.
141 *
142 * Value of 0 or false means no timeout.
143 *
144 * @param {Number|Object} ms or {response, read, deadline}
145 * @return {Request} for chaining
146 * @api public
147 */
148
149RequestBase.prototype.timeout = function timeout(options){
150 if (!options || 'object' !== typeof options) {
151 this._timeout = options;
152 this._responseTimeout = 0;
153 return this;
154 }
155
156 if ('undefined' !== typeof options.deadline) {
157 this._timeout = options.deadline;
158 }
159 if ('undefined' !== typeof options.response) {
160 this._responseTimeout = options.response;
161 }
162 return this;
163};
164
165/**
166 * Set number of retry attempts on error.
167 *
168 * Failed requests will be retried 'count' times if timeout or err.code >= 500.
169 *
170 * @param {Number} count
171 * @return {Request} for chaining
172 * @api public
173 */
174
175RequestBase.prototype.retry = function retry(count){
176 // Default to 1 if no count passed or true
177 if (arguments.length === 0 || count === true) count = 1;
178 if (count <= 0) count = 0;
179 this._maxRetries = count;
180 this._retries = 0;
181 return this;
182};
183
184/**
185 * Retry request
186 *
187 * @return {Request} for chaining
188 * @api private
189 */
190
191RequestBase.prototype._retry = function() {
192 this.clearTimeout();
193
194 // node
195 if (this.req) {
196 this.req = null;
197 this.req = this.request();
198 }
199
200 this._aborted = false;
201 this.timedout = false;
202
203 return this._end();
204};
205
206/**
207 * Promise support
208 *
209 * @param {Function} resolve
210 * @param {Function} [reject]
211 * @return {Request}
212 */
213
214RequestBase.prototype.then = function then(resolve, reject) {
215 if (!this._fullfilledPromise) {
216 var self = this;
217 if (this._endCalled) {
218 console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises");
219 }
220 this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
221 self.end(function(err, res){
222 if (err) innerReject(err); else innerResolve(res);
223 });
224 });
225 }
226 return this._fullfilledPromise.then(resolve, reject);
227}
228
229RequestBase.prototype.catch = function(cb) {
230 return this.then(undefined, cb);
231};
232
233/**
234 * Allow for extension
235 */
236
237RequestBase.prototype.use = function use(fn) {
238 fn(this);
239 return this;
240}
241
242RequestBase.prototype.ok = function(cb) {
243 if ('function' !== typeof cb) throw Error("Callback required");
244 this._okCallback = cb;
245 return this;
246};
247
248RequestBase.prototype._isResponseOK = function(res) {
249 if (!res) {
250 return false;
251 }
252
253 if (this._okCallback) {
254 return this._okCallback(res);
255 }
256
257 return res.status >= 200 && res.status < 300;
258};
259
260
261/**
262 * Get request header `field`.
263 * Case-insensitive.
264 *
265 * @param {String} field
266 * @return {String}
267 * @api public
268 */
269
270RequestBase.prototype.get = function(field){
271 return this._header[field.toLowerCase()];
272};
273
274/**
275 * Get case-insensitive header `field` value.
276 * This is a deprecated internal API. Use `.get(field)` instead.
277 *
278 * (getHeader is no longer used internally by the superagent code base)
279 *
280 * @param {String} field
281 * @return {String}
282 * @api private
283 * @deprecated
284 */
285
286RequestBase.prototype.getHeader = RequestBase.prototype.get;
287
288/**
289 * Set header `field` to `val`, or multiple fields with one object.
290 * Case-insensitive.
291 *
292 * Examples:
293 *
294 * req.get('/')
295 * .set('Accept', 'application/json')
296 * .set('X-API-Key', 'foobar')
297 * .end(callback);
298 *
299 * req.get('/')
300 * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
301 * .end(callback);
302 *
303 * @param {String|Object} field
304 * @param {String} val
305 * @return {Request} for chaining
306 * @api public
307 */
308
309RequestBase.prototype.set = function(field, val){
310 if (isObject(field)) {
311 for (var key in field) {
312 this.set(key, field[key]);
313 }
314 return this;
315 }
316 this._header[field.toLowerCase()] = val;
317 this.header[field] = val;
318 return this;
319};
320
321/**
322 * Remove header `field`.
323 * Case-insensitive.
324 *
325 * Example:
326 *
327 * req.get('/')
328 * .unset('User-Agent')
329 * .end(callback);
330 *
331 * @param {String} field
332 */
333RequestBase.prototype.unset = function(field){
334 delete this._header[field.toLowerCase()];
335 delete this.header[field];
336 return this;
337};
338
339/**
340 * Write the field `name` and `val`, or multiple fields with one object
341 * for "multipart/form-data" request bodies.
342 *
343 * ``` js
344 * request.post('/upload')
345 * .field('foo', 'bar')
346 * .end(callback);
347 *
348 * request.post('/upload')
349 * .field({ foo: 'bar', baz: 'qux' })
350 * .end(callback);
351 * ```
352 *
353 * @param {String|Object} name
354 * @param {String|Blob|File|Buffer|fs.ReadStream} val
355 * @return {Request} for chaining
356 * @api public
357 */
358RequestBase.prototype.field = function(name, val) {
359
360 // name should be either a string or an object.
361 if (null === name || undefined === name) {
362 throw new Error('.field(name, val) name can not be empty');
363 }
364
365 if (this._data) {
366 console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()");
367 }
368
369 if (isObject(name)) {
370 for (var key in name) {
371 this.field(key, name[key]);
372 }
373 return this;
374 }
375
376 if (Array.isArray(val)) {
377 for (var i in val) {
378 this.field(name, val[i]);
379 }
380 return this;
381 }
382
383 // val should be defined now
384 if (null === val || undefined === val) {
385 throw new Error('.field(name, val) val can not be empty');
386 }
387 if ('boolean' === typeof val) {
388 val = '' + val;
389 }
390 this._getFormData().append(name, val);
391 return this;
392};
393
394/**
395 * Abort the request, and clear potential timeout.
396 *
397 * @return {Request}
398 * @api public
399 */
400RequestBase.prototype.abort = function(){
401 if (this._aborted) {
402 return this;
403 }
404 this._aborted = true;
405 this.xhr && this.xhr.abort(); // browser
406 this.req && this.req.abort(); // node
407 this.clearTimeout();
408 this.emit('abort');
409 return this;
410};
411
412/**
413 * Enable transmission of cookies with x-domain requests.
414 *
415 * Note that for this to work the origin must not be
416 * using "Access-Control-Allow-Origin" with a wildcard,
417 * and also must set "Access-Control-Allow-Credentials"
418 * to "true".
419 *
420 * @api public
421 */
422
423RequestBase.prototype.withCredentials = function(){
424 // This is browser-only functionality. Node side is no-op.
425 this._withCredentials = true;
426 return this;
427};
428
429/**
430 * Set the max redirects to `n`. Does noting in browser XHR implementation.
431 *
432 * @param {Number} n
433 * @return {Request} for chaining
434 * @api public
435 */
436
437RequestBase.prototype.redirects = function(n){
438 this._maxRedirects = n;
439 return this;
440};
441
442/**
443 * Convert to a plain javascript object (not JSON string) of scalar properties.
444 * Note as this method is designed to return a useful non-this value,
445 * it cannot be chained.
446 *
447 * @return {Object} describing method, url, and data of this request
448 * @api public
449 */
450
451RequestBase.prototype.toJSON = function(){
452 return {
453 method: this.method,
454 url: this.url,
455 data: this._data,
456 headers: this._header
457 };
458};
459
460
461/**
462 * Send `data` as the request body, defaulting the `.type()` to "json" when
463 * an object is given.
464 *
465 * Examples:
466 *
467 * // manual json
468 * request.post('/user')
469 * .type('json')
470 * .send('{"name":"tj"}')
471 * .end(callback)
472 *
473 * // auto json
474 * request.post('/user')
475 * .send({ name: 'tj' })
476 * .end(callback)
477 *
478 * // manual x-www-form-urlencoded
479 * request.post('/user')
480 * .type('form')
481 * .send('name=tj')
482 * .end(callback)
483 *
484 * // auto x-www-form-urlencoded
485 * request.post('/user')
486 * .type('form')
487 * .send({ name: 'tj' })
488 * .end(callback)
489 *
490 * // defaults to x-www-form-urlencoded
491 * request.post('/user')
492 * .send('name=tobi')
493 * .send('species=ferret')
494 * .end(callback)
495 *
496 * @param {String|Object} data
497 * @return {Request} for chaining
498 * @api public
499 */
500
501RequestBase.prototype.send = function(data){
502 var isObj = isObject(data);
503 var type = this._header['content-type'];
504
505 if (this._formData) {
506 console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()");
507 }
508
509 if (isObj && !this._data) {
510 if (Array.isArray(data)) {
511 this._data = [];
512 } else if (!this._isHost(data)) {
513 this._data = {};
514 }
515 } else if (data && this._data && this._isHost(this._data)) {
516 throw Error("Can't merge these send calls");
517 }
518
519 // merge
520 if (isObj && isObject(this._data)) {
521 for (var key in data) {
522 this._data[key] = data[key];
523 }
524 } else if ('string' == typeof data) {
525 // default to x-www-form-urlencoded
526 if (!type) this.type('form');
527 type = this._header['content-type'];
528 if ('application/x-www-form-urlencoded' == type) {
529 this._data = this._data
530 ? this._data + '&' + data
531 : data;
532 } else {
533 this._data = (this._data || '') + data;
534 }
535 } else {
536 this._data = data;
537 }
538
539 if (!isObj || this._isHost(data)) {
540 return this;
541 }
542
543 // default to json
544 if (!type) this.type('json');
545 return this;
546};
547
548
549/**
550 * Sort `querystring` by the sort function
551 *
552 *
553 * Examples:
554 *
555 * // default order
556 * request.get('/user')
557 * .query('name=Nick')
558 * .query('search=Manny')
559 * .sortQuery()
560 * .end(callback)
561 *
562 * // customized sort function
563 * request.get('/user')
564 * .query('name=Nick')
565 * .query('search=Manny')
566 * .sortQuery(function(a, b){
567 * return a.length - b.length;
568 * })
569 * .end(callback)
570 *
571 *
572 * @param {Function} sort
573 * @return {Request} for chaining
574 * @api public
575 */
576
577RequestBase.prototype.sortQuery = function(sort) {
578 // _sort default to true but otherwise can be a function or boolean
579 this._sort = typeof sort === 'undefined' ? true : sort;
580 return this;
581};
582
583/**
584 * Invoke callback with timeout error.
585 *
586 * @api private
587 */
588
589RequestBase.prototype._timeoutError = function(reason, timeout){
590 if (this._aborted) {
591 return;
592 }
593 var err = new Error(reason + timeout + 'ms exceeded');
594 err.timeout = timeout;
595 err.code = 'ECONNABORTED';
596 this.timedout = true;
597 this.abort();
598 this.callback(err);
599};
600
601RequestBase.prototype._setTimeouts = function() {
602 var self = this;
603
604 // deadline
605 if (this._timeout && !this._timer) {
606 this._timer = setTimeout(function(){
607 self._timeoutError('Timeout of ', self._timeout);
608 }, this._timeout);
609 }
610 // response timeout
611 if (this._responseTimeout && !this._responseTimeoutTimer) {
612 this._responseTimeoutTimer = setTimeout(function(){
613 self._timeoutError('Response timeout of ', self._responseTimeout);
614 }, this._responseTimeout);
615 }
616}
617
618},{"./is-object":2}],4:[function(require,module,exports){
619
620/**
621 * Module dependencies.
622 */
623
624var utils = require('./utils');
625
626/**
627 * Expose `ResponseBase`.
628 */
629
630module.exports = ResponseBase;
631
632/**
633 * Initialize a new `ResponseBase`.
634 *
635 * @api public
636 */
637
638function ResponseBase(obj) {
639 if (obj) return mixin(obj);
640}
641
642/**
643 * Mixin the prototype properties.
644 *
645 * @param {Object} obj
646 * @return {Object}
647 * @api private
648 */
649
650function mixin(obj) {
651 for (var key in ResponseBase.prototype) {
652 obj[key] = ResponseBase.prototype[key];
653 }
654 return obj;
655}
656
657/**
658 * Get case-insensitive `field` value.
659 *
660 * @param {String} field
661 * @return {String}
662 * @api public
663 */
664
665ResponseBase.prototype.get = function(field){
666 return this.header[field.toLowerCase()];
667};
668
669/**
670 * Set header related properties:
671 *
672 * - `.type` the content type without params
673 *
674 * A response of "Content-Type: text/plain; charset=utf-8"
675 * will provide you with a `.type` of "text/plain".
676 *
677 * @param {Object} header
678 * @api private
679 */
680
681ResponseBase.prototype._setHeaderProperties = function(header){
682 // TODO: moar!
683 // TODO: make this a util
684
685 // content-type
686 var ct = header['content-type'] || '';
687 this.type = utils.type(ct);
688
689 // params
690 var params = utils.params(ct);
691 for (var key in params) this[key] = params[key];
692
693 this.links = {};
694
695 // links
696 try {
697 if (header.link) {
698 this.links = utils.parseLinks(header.link);
699 }
700 } catch (err) {
701 // ignore
702 }
703};
704
705/**
706 * Set flags such as `.ok` based on `status`.
707 *
708 * For example a 2xx response will give you a `.ok` of __true__
709 * whereas 5xx will be __false__ and `.error` will be __true__. The
710 * `.clientError` and `.serverError` are also available to be more
711 * specific, and `.statusType` is the class of error ranging from 1..5
712 * sometimes useful for mapping respond colors etc.
713 *
714 * "sugar" properties are also defined for common cases. Currently providing:
715 *
716 * - .noContent
717 * - .badRequest
718 * - .unauthorized
719 * - .notAcceptable
720 * - .notFound
721 *
722 * @param {Number} status
723 * @api private
724 */
725
726ResponseBase.prototype._setStatusProperties = function(status){
727 var type = status / 100 | 0;
728
729 // status / class
730 this.status = this.statusCode = status;
731 this.statusType = type;
732
733 // basics
734 this.info = 1 == type;
735 this.ok = 2 == type;
736 this.redirect = 3 == type;
737 this.clientError = 4 == type;
738 this.serverError = 5 == type;
739 this.error = (4 == type || 5 == type)
740 ? this.toError()
741 : false;
742
743 // sugar
744 this.accepted = 202 == status;
745 this.noContent = 204 == status;
746 this.badRequest = 400 == status;
747 this.unauthorized = 401 == status;
748 this.notAcceptable = 406 == status;
749 this.forbidden = 403 == status;
750 this.notFound = 404 == status;
751};
752
753},{"./utils":6}],5:[function(require,module,exports){
754var ERROR_CODES = [
755 'ECONNRESET',
756 'ETIMEDOUT',
757 'EADDRINFO',
758 'ESOCKETTIMEDOUT'
759];
760
761/**
762 * Determine if a request should be retried.
763 * (Borrowed from segmentio/superagent-retry)
764 *
765 * @param {Error} err
766 * @param {Response} [res]
767 * @returns {Boolean}
768 */
769module.exports = function shouldRetry(err, res) {
770 if (err && err.code && ~ERROR_CODES.indexOf(err.code)) return true;
771 if (res && res.status && res.status >= 500) return true;
772 // Superagent timeout
773 if (err && 'timeout' in err && err.code == 'ECONNABORTED') return true;
774 return false;
775};
776},{}],6:[function(require,module,exports){
777
778/**
779 * Return the mime type for the given `str`.
780 *
781 * @param {String} str
782 * @return {String}
783 * @api private
784 */
785
786exports.type = function(str){
787 return str.split(/ *; */).shift();
788};
789
790/**
791 * Return header field parameters.
792 *
793 * @param {String} str
794 * @return {Object}
795 * @api private
796 */
797
798exports.params = function(str){
799 return str.split(/ *; */).reduce(function(obj, str){
800 var parts = str.split(/ *= */);
801 var key = parts.shift();
802 var val = parts.shift();
803
804 if (key && val) obj[key] = val;
805 return obj;
806 }, {});
807};
808
809/**
810 * Parse Link header fields.
811 *
812 * @param {String} str
813 * @return {Object}
814 * @api private
815 */
816
817exports.parseLinks = function(str){
818 return str.split(/ *, */).reduce(function(obj, str){
819 var parts = str.split(/ *; */);
820 var url = parts[0].slice(1, -1);
821 var rel = parts[1].split(/ *= */)[1].slice(1, -1);
822 obj[rel] = url;
823 return obj;
824 }, {});
825};
826
827/**
828 * Strip content related fields from `header`.
829 *
830 * @param {Object} header
831 * @return {Object} header
832 * @api private
833 */
834
835exports.cleanHeader = function(header, shouldStripCookie){
836 delete header['content-type'];
837 delete header['content-length'];
838 delete header['transfer-encoding'];
839 delete header['host'];
840 if (shouldStripCookie) {
841 delete header['cookie'];
842 }
843 return header;
844};
845},{}],7:[function(require,module,exports){
846
847/**
848 * Expose `Emitter`.
849 */
850
851if (typeof module !== 'undefined') {
852 module.exports = Emitter;
853}
854
855/**
856 * Initialize a new `Emitter`.
857 *
858 * @api public
859 */
860
861function Emitter(obj) {
862 if (obj) return mixin(obj);
863};
864
865/**
866 * Mixin the emitter properties.
867 *
868 * @param {Object} obj
869 * @return {Object}
870 * @api private
871 */
872
873function mixin(obj) {
874 for (var key in Emitter.prototype) {
875 obj[key] = Emitter.prototype[key];
876 }
877 return obj;
878}
879
880/**
881 * Listen on the given `event` with `fn`.
882 *
883 * @param {String} event
884 * @param {Function} fn
885 * @return {Emitter}
886 * @api public
887 */
888
889Emitter.prototype.on =
890Emitter.prototype.addEventListener = function(event, fn){
891 this._callbacks = this._callbacks || {};
892 (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
893 .push(fn);
894 return this;
895};
896
897/**
898 * Adds an `event` listener that will be invoked a single
899 * time then automatically removed.
900 *
901 * @param {String} event
902 * @param {Function} fn
903 * @return {Emitter}
904 * @api public
905 */
906
907Emitter.prototype.once = function(event, fn){
908 function on() {
909 this.off(event, on);
910 fn.apply(this, arguments);
911 }
912
913 on.fn = fn;
914 this.on(event, on);
915 return this;
916};
917
918/**
919 * Remove the given callback for `event` or all
920 * registered callbacks.
921 *
922 * @param {String} event
923 * @param {Function} fn
924 * @return {Emitter}
925 * @api public
926 */
927
928Emitter.prototype.off =
929Emitter.prototype.removeListener =
930Emitter.prototype.removeAllListeners =
931Emitter.prototype.removeEventListener = function(event, fn){
932 this._callbacks = this._callbacks || {};
933
934 // all
935 if (0 == arguments.length) {
936 this._callbacks = {};
937 return this;
938 }
939
940 // specific event
941 var callbacks = this._callbacks['$' + event];
942 if (!callbacks) return this;
943
944 // remove all handlers
945 if (1 == arguments.length) {
946 delete this._callbacks['$' + event];
947 return this;
948 }
949
950 // remove specific handler
951 var cb;
952 for (var i = 0; i < callbacks.length; i++) {
953 cb = callbacks[i];
954 if (cb === fn || cb.fn === fn) {
955 callbacks.splice(i, 1);
956 break;
957 }
958 }
959 return this;
960};
961
962/**
963 * Emit `event` with the given args.
964 *
965 * @param {String} event
966 * @param {Mixed} ...
967 * @return {Emitter}
968 */
969
970Emitter.prototype.emit = function(event){
971 this._callbacks = this._callbacks || {};
972 var args = [].slice.call(arguments, 1)
973 , callbacks = this._callbacks['$' + event];
974
975 if (callbacks) {
976 callbacks = callbacks.slice(0);
977 for (var i = 0, len = callbacks.length; i < len; ++i) {
978 callbacks[i].apply(this, args);
979 }
980 }
981
982 return this;
983};
984
985/**
986 * Return array of callbacks for `event`.
987 *
988 * @param {String} event
989 * @return {Array}
990 * @api public
991 */
992
993Emitter.prototype.listeners = function(event){
994 this._callbacks = this._callbacks || {};
995 return this._callbacks['$' + event] || [];
996};
997
998/**
999 * Check if this emitter has `event` handlers.
1000 *
1001 * @param {String} event
1002 * @return {Boolean}
1003 * @api public
1004 */
1005
1006Emitter.prototype.hasListeners = function(event){
1007 return !! this.listeners(event).length;
1008};
1009
1010},{}],8:[function(require,module,exports){
1011/**
1012 * Root reference for iframes.
1013 */
1014
1015var root;
1016if (typeof window !== 'undefined') { // Browser window
1017 root = window;
1018} else if (typeof self !== 'undefined') { // Web Worker
1019 root = self;
1020} else { // Other environments
1021 console.warn("Using browser-only version of superagent in non-browser environment");
1022 root = this;
1023}
1024
1025var Emitter = require('emitter');
1026var RequestBase = require('./request-base');
1027var isObject = require('./is-object');
1028var isFunction = require('./is-function');
1029var ResponseBase = require('./response-base');
1030var shouldRetry = require('./should-retry');
1031
1032/**
1033 * Noop.
1034 */
1035
1036function noop(){};
1037
1038/**
1039 * Expose `request`.
1040 */
1041
1042var request = exports = module.exports = function(method, url) {
1043 // callback
1044 if ('function' == typeof url) {
1045 return new exports.Request('GET', method).end(url);
1046 }
1047
1048 // url first
1049 if (1 == arguments.length) {
1050 return new exports.Request('GET', method);
1051 }
1052
1053 return new exports.Request(method, url);
1054}
1055
1056exports.Request = Request;
1057
1058/**
1059 * Determine XHR.
1060 */
1061
1062request.getXHR = function () {
1063 if (root.XMLHttpRequest
1064 && (!root.location || 'file:' != root.location.protocol
1065 || !root.ActiveXObject)) {
1066 return new XMLHttpRequest;
1067 } else {
1068 try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
1069 try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
1070 try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
1071 try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
1072 }
1073 throw Error("Browser-only verison of superagent could not find XHR");
1074};
1075
1076/**
1077 * Removes leading and trailing whitespace, added to support IE.
1078 *
1079 * @param {String} s
1080 * @return {String}
1081 * @api private
1082 */
1083
1084var trim = ''.trim
1085 ? function(s) { return s.trim(); }
1086 : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); };
1087
1088/**
1089 * Serialize the given `obj`.
1090 *
1091 * @param {Object} obj
1092 * @return {String}
1093 * @api private
1094 */
1095
1096function serialize(obj) {
1097 if (!isObject(obj)) return obj;
1098 var pairs = [];
1099 for (var key in obj) {
1100 pushEncodedKeyValuePair(pairs, key, obj[key]);
1101 }
1102 return pairs.join('&');
1103}
1104
1105/**
1106 * Helps 'serialize' with serializing arrays.
1107 * Mutates the pairs array.
1108 *
1109 * @param {Array} pairs
1110 * @param {String} key
1111 * @param {Mixed} val
1112 */
1113
1114function pushEncodedKeyValuePair(pairs, key, val) {
1115 if (val != null) {
1116 if (Array.isArray(val)) {
1117 val.forEach(function(v) {
1118 pushEncodedKeyValuePair(pairs, key, v);
1119 });
1120 } else if (isObject(val)) {
1121 for(var subkey in val) {
1122 pushEncodedKeyValuePair(pairs, key + '[' + subkey + ']', val[subkey]);
1123 }
1124 } else {
1125 pairs.push(encodeURIComponent(key)
1126 + '=' + encodeURIComponent(val));
1127 }
1128 } else if (val === null) {
1129 pairs.push(encodeURIComponent(key));
1130 }
1131}
1132
1133/**
1134 * Expose serialization method.
1135 */
1136
1137 request.serializeObject = serialize;
1138
1139 /**
1140 * Parse the given x-www-form-urlencoded `str`.
1141 *
1142 * @param {String} str
1143 * @return {Object}
1144 * @api private
1145 */
1146
1147function parseString(str) {
1148 var obj = {};
1149 var pairs = str.split('&');
1150 var pair;
1151 var pos;
1152
1153 for (var i = 0, len = pairs.length; i < len; ++i) {
1154 pair = pairs[i];
1155 pos = pair.indexOf('=');
1156 if (pos == -1) {
1157 obj[decodeURIComponent(pair)] = '';
1158 } else {
1159 obj[decodeURIComponent(pair.slice(0, pos))] =
1160 decodeURIComponent(pair.slice(pos + 1));
1161 }
1162 }
1163
1164 return obj;
1165}
1166
1167/**
1168 * Expose parser.
1169 */
1170
1171request.parseString = parseString;
1172
1173/**
1174 * Default MIME type map.
1175 *
1176 * superagent.types.xml = 'application/xml';
1177 *
1178 */
1179
1180request.types = {
1181 html: 'text/html',
1182 json: 'application/json',
1183 xml: 'application/xml',
1184 urlencoded: 'application/x-www-form-urlencoded',
1185 'form': 'application/x-www-form-urlencoded',
1186 'form-data': 'application/x-www-form-urlencoded'
1187};
1188
1189/**
1190 * Default serialization map.
1191 *
1192 * superagent.serialize['application/xml'] = function(obj){
1193 * return 'generated xml here';
1194 * };
1195 *
1196 */
1197
1198 request.serialize = {
1199 'application/x-www-form-urlencoded': serialize,
1200 'application/json': JSON.stringify
1201 };
1202
1203 /**
1204 * Default parsers.
1205 *
1206 * superagent.parse['application/xml'] = function(str){
1207 * return { object parsed from str };
1208 * };
1209 *
1210 */
1211
1212request.parse = {
1213 'application/x-www-form-urlencoded': parseString,
1214 'application/json': JSON.parse
1215};
1216
1217/**
1218 * Parse the given header `str` into
1219 * an object containing the mapped fields.
1220 *
1221 * @param {String} str
1222 * @return {Object}
1223 * @api private
1224 */
1225
1226function parseHeader(str) {
1227 var lines = str.split(/\r?\n/);
1228 var fields = {};
1229 var index;
1230 var line;
1231 var field;
1232 var val;
1233
1234 lines.pop(); // trailing CRLF
1235
1236 for (var i = 0, len = lines.length; i < len; ++i) {
1237 line = lines[i];
1238 index = line.indexOf(':');
1239 field = line.slice(0, index).toLowerCase();
1240 val = trim(line.slice(index + 1));
1241 fields[field] = val;
1242 }
1243
1244 return fields;
1245}
1246
1247/**
1248 * Check if `mime` is json or has +json structured syntax suffix.
1249 *
1250 * @param {String} mime
1251 * @return {Boolean}
1252 * @api private
1253 */
1254
1255function isJSON(mime) {
1256 return /[\/+]json\b/.test(mime);
1257}
1258
1259/**
1260 * Initialize a new `Response` with the given `xhr`.
1261 *
1262 * - set flags (.ok, .error, etc)
1263 * - parse header
1264 *
1265 * Examples:
1266 *
1267 * Aliasing `superagent` as `request` is nice:
1268 *
1269 * request = superagent;
1270 *
1271 * We can use the promise-like API, or pass callbacks:
1272 *
1273 * request.get('/').end(function(res){});
1274 * request.get('/', function(res){});
1275 *
1276 * Sending data can be chained:
1277 *
1278 * request
1279 * .post('/user')
1280 * .send({ name: 'tj' })
1281 * .end(function(res){});
1282 *
1283 * Or passed to `.send()`:
1284 *
1285 * request
1286 * .post('/user')
1287 * .send({ name: 'tj' }, function(res){});
1288 *
1289 * Or passed to `.post()`:
1290 *
1291 * request
1292 * .post('/user', { name: 'tj' })
1293 * .end(function(res){});
1294 *
1295 * Or further reduced to a single call for simple cases:
1296 *
1297 * request
1298 * .post('/user', { name: 'tj' }, function(res){});
1299 *
1300 * @param {XMLHTTPRequest} xhr
1301 * @param {Object} options
1302 * @api private
1303 */
1304
1305function Response(req) {
1306 this.req = req;
1307 this.xhr = this.req.xhr;
1308 // responseText is accessible only if responseType is '' or 'text' and on older browsers
1309 this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr.responseType === 'undefined')
1310 ? this.xhr.responseText
1311 : null;
1312 this.statusText = this.req.xhr.statusText;
1313 var status = this.xhr.status;
1314 // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
1315 if (status === 1223) {
1316 status = 204;
1317 }
1318 this._setStatusProperties(status);
1319 this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
1320 // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
1321 // getResponseHeader still works. so we get content-type even if getting
1322 // other headers fails.
1323 this.header['content-type'] = this.xhr.getResponseHeader('content-type');
1324 this._setHeaderProperties(this.header);
1325
1326 if (null === this.text && req._responseType) {
1327 this.body = this.xhr.response;
1328 } else {
1329 this.body = this.req.method != 'HEAD'
1330 ? this._parseBody(this.text ? this.text : this.xhr.response)
1331 : null;
1332 }
1333}
1334
1335ResponseBase(Response.prototype);
1336
1337/**
1338 * Parse the given body `str`.
1339 *
1340 * Used for auto-parsing of bodies. Parsers
1341 * are defined on the `superagent.parse` object.
1342 *
1343 * @param {String} str
1344 * @return {Mixed}
1345 * @api private
1346 */
1347
1348Response.prototype._parseBody = function(str){
1349 var parse = request.parse[this.type];
1350 if(this.req._parser) {
1351 return this.req._parser(this, str);
1352 }
1353 if (!parse && isJSON(this.type)) {
1354 parse = request.parse['application/json'];
1355 }
1356 return parse && str && (str.length || str instanceof Object)
1357 ? parse(str)
1358 : null;
1359};
1360
1361/**
1362 * Return an `Error` representative of this response.
1363 *
1364 * @return {Error}
1365 * @api public
1366 */
1367
1368Response.prototype.toError = function(){
1369 var req = this.req;
1370 var method = req.method;
1371 var url = req.url;
1372
1373 var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')';
1374 var err = new Error(msg);
1375 err.status = this.status;
1376 err.method = method;
1377 err.url = url;
1378
1379 return err;
1380};
1381
1382/**
1383 * Expose `Response`.
1384 */
1385
1386request.Response = Response;
1387
1388/**
1389 * Initialize a new `Request` with the given `method` and `url`.
1390 *
1391 * @param {String} method
1392 * @param {String} url
1393 * @api public
1394 */
1395
1396function Request(method, url) {
1397 var self = this;
1398 this._query = this._query || [];
1399 this.method = method;
1400 this.url = url;
1401 this.header = {}; // preserves header name case
1402 this._header = {}; // coerces header names to lowercase
1403 this.on('end', function(){
1404 var err = null;
1405 var res = null;
1406
1407 try {
1408 res = new Response(self);
1409 } catch(e) {
1410 err = new Error('Parser is unable to parse the response');
1411 err.parse = true;
1412 err.original = e;
1413 // issue #675: return the raw response if the response parsing fails
1414 if (self.xhr) {
1415 // ie9 doesn't have 'response' property
1416 err.rawResponse = typeof self.xhr.responseType == 'undefined' ? self.xhr.responseText : self.xhr.response;
1417 // issue #876: return the http status code if the response parsing fails
1418 err.status = self.xhr.status ? self.xhr.status : null;
1419 err.statusCode = err.status; // backwards-compat only
1420 } else {
1421 err.rawResponse = null;
1422 err.status = null;
1423 }
1424
1425 return self.callback(err);
1426 }
1427
1428 self.emit('response', res);
1429
1430 var new_err;
1431 try {
1432 if (!self._isResponseOK(res)) {
1433 new_err = new Error(res.statusText || 'Unsuccessful HTTP response');
1434 new_err.original = err;
1435 new_err.response = res;
1436 new_err.status = res.status;
1437 }
1438 } catch(e) {
1439 new_err = e; // #985 touching res may cause INVALID_STATE_ERR on old Android
1440 }
1441
1442 // #1000 don't catch errors from the callback to avoid double calling it
1443 if (new_err) {
1444 self.callback(new_err, res);
1445 } else {
1446 self.callback(null, res);
1447 }
1448 });
1449}
1450
1451/**
1452 * Mixin `Emitter` and `RequestBase`.
1453 */
1454
1455Emitter(Request.prototype);
1456RequestBase(Request.prototype);
1457
1458/**
1459 * Set Content-Type to `type`, mapping values from `request.types`.
1460 *
1461 * Examples:
1462 *
1463 * superagent.types.xml = 'application/xml';
1464 *
1465 * request.post('/')
1466 * .type('xml')
1467 * .send(xmlstring)
1468 * .end(callback);
1469 *
1470 * request.post('/')
1471 * .type('application/xml')
1472 * .send(xmlstring)
1473 * .end(callback);
1474 *
1475 * @param {String} type
1476 * @return {Request} for chaining
1477 * @api public
1478 */
1479
1480Request.prototype.type = function(type){
1481 this.set('Content-Type', request.types[type] || type);
1482 return this;
1483};
1484
1485/**
1486 * Set Accept to `type`, mapping values from `request.types`.
1487 *
1488 * Examples:
1489 *
1490 * superagent.types.json = 'application/json';
1491 *
1492 * request.get('/agent')
1493 * .accept('json')
1494 * .end(callback);
1495 *
1496 * request.get('/agent')
1497 * .accept('application/json')
1498 * .end(callback);
1499 *
1500 * @param {String} accept
1501 * @return {Request} for chaining
1502 * @api public
1503 */
1504
1505Request.prototype.accept = function(type){
1506 this.set('Accept', request.types[type] || type);
1507 return this;
1508};
1509
1510/**
1511 * Set Authorization field value with `user` and `pass`.
1512 *
1513 * @param {String} user
1514 * @param {String} pass
1515 * @param {Object} options with 'type' property 'auto' or 'basic' (default 'basic')
1516 * @return {Request} for chaining
1517 * @api public
1518 */
1519
1520Request.prototype.auth = function(user, pass, options){
1521 if (!options) {
1522 options = {
1523 type: 'function' === typeof btoa ? 'basic' : 'auto',
1524 }
1525 }
1526
1527 switch (options.type) {
1528 case 'basic':
1529 this.set('Authorization', 'Basic ' + btoa(user + ':' + pass));
1530 break;
1531
1532 case 'auto':
1533 this.username = user;
1534 this.password = pass;
1535 break;
1536 }
1537 return this;
1538};
1539
1540/**
1541 * Add query-string `val`.
1542 *
1543 * Examples:
1544 *
1545 * request.get('/shoes')
1546 * .query('size=10')
1547 * .query({ color: 'blue' })
1548 *
1549 * @param {Object|String} val
1550 * @return {Request} for chaining
1551 * @api public
1552 */
1553
1554Request.prototype.query = function(val){
1555 if ('string' != typeof val) val = serialize(val);
1556 if (val) this._query.push(val);
1557 return this;
1558};
1559
1560/**
1561 * Queue the given `file` as an attachment to the specified `field`,
1562 * with optional `options` (or filename).
1563 *
1564 * ``` js
1565 * request.post('/upload')
1566 * .attach('content', new Blob(['<a id="a"><b id="b">hey!</b></a>'], { type: "text/html"}))
1567 * .end(callback);
1568 * ```
1569 *
1570 * @param {String} field
1571 * @param {Blob|File} file
1572 * @param {String|Object} options
1573 * @return {Request} for chaining
1574 * @api public
1575 */
1576
1577Request.prototype.attach = function(field, file, options){
1578 if (file) {
1579 if (this._data) {
1580 throw Error("superagent can't mix .send() and .attach()");
1581 }
1582
1583 this._getFormData().append(field, file, options || file.name);
1584 }
1585 return this;
1586};
1587
1588Request.prototype._getFormData = function(){
1589 if (!this._formData) {
1590 this._formData = new root.FormData();
1591 }
1592 return this._formData;
1593};
1594
1595/**
1596 * Invoke the callback with `err` and `res`
1597 * and handle arity check.
1598 *
1599 * @param {Error} err
1600 * @param {Response} res
1601 * @api private
1602 */
1603
1604Request.prototype.callback = function(err, res){
1605 // console.log(this._retries, this._maxRetries)
1606 if (this._maxRetries && this._retries++ < this._maxRetries && shouldRetry(err, res)) {
1607 return this._retry();
1608 }
1609
1610 var fn = this._callback;
1611 this.clearTimeout();
1612
1613 if (err) {
1614 if (this._maxRetries) err.retries = this._retries - 1;
1615 this.emit('error', err);
1616 }
1617
1618 fn(err, res);
1619};
1620
1621/**
1622 * Invoke callback with x-domain error.
1623 *
1624 * @api private
1625 */
1626
1627Request.prototype.crossDomainError = function(){
1628 var err = new Error('Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.');
1629 err.crossDomain = true;
1630
1631 err.status = this.status;
1632 err.method = this.method;
1633 err.url = this.url;
1634
1635 this.callback(err);
1636};
1637
1638// This only warns, because the request is still likely to work
1639Request.prototype.buffer = Request.prototype.ca = Request.prototype.agent = function(){
1640 console.warn("This is not supported in browser version of superagent");
1641 return this;
1642};
1643
1644// This throws, because it can't send/receive data as expected
1645Request.prototype.pipe = Request.prototype.write = function(){
1646 throw Error("Streaming is not supported in browser version of superagent");
1647};
1648
1649/**
1650 * Compose querystring to append to req.url
1651 *
1652 * @api private
1653 */
1654
1655Request.prototype._appendQueryString = function(){
1656 var query = this._query.join('&');
1657 if (query) {
1658 this.url += (this.url.indexOf('?') >= 0 ? '&' : '?') + query;
1659 }
1660
1661 if (this._sort) {
1662 var index = this.url.indexOf('?');
1663 if (index >= 0) {
1664 var queryArr = this.url.substring(index + 1).split('&');
1665 if (isFunction(this._sort)) {
1666 queryArr.sort(this._sort);
1667 } else {
1668 queryArr.sort();
1669 }
1670 this.url = this.url.substring(0, index) + '?' + queryArr.join('&');
1671 }
1672 }
1673};
1674
1675/**
1676 * Check if `obj` is a host object,
1677 * we don't want to serialize these :)
1678 *
1679 * @param {Object} obj
1680 * @return {Boolean}
1681 * @api private
1682 */
1683Request.prototype._isHost = function _isHost(obj) {
1684 // Native objects stringify to [object File], [object Blob], [object FormData], etc.
1685 return obj && 'object' === typeof obj && !Array.isArray(obj) && Object.prototype.toString.call(obj) !== '[object Object]';
1686}
1687
1688/**
1689 * Initiate request, invoking callback `fn(res)`
1690 * with an instanceof `Response`.
1691 *
1692 * @param {Function} fn
1693 * @return {Request} for chaining
1694 * @api public
1695 */
1696
1697Request.prototype.end = function(fn){
1698 if (this._endCalled) {
1699 console.warn("Warning: .end() was called twice. This is not supported in superagent");
1700 }
1701 this._endCalled = true;
1702
1703 // store callback
1704 this._callback = fn || noop;
1705
1706 // querystring
1707 this._appendQueryString();
1708
1709 return this._end();
1710};
1711
1712Request.prototype._end = function() {
1713 var self = this;
1714 var xhr = this.xhr = request.getXHR();
1715 var data = this._formData || this._data;
1716
1717 this._setTimeouts();
1718
1719 // state change
1720 xhr.onreadystatechange = function(){
1721 var readyState = xhr.readyState;
1722 if (readyState >= 2 && self._responseTimeoutTimer) {
1723 clearTimeout(self._responseTimeoutTimer);
1724 }
1725 if (4 != readyState) {
1726 return;
1727 }
1728
1729 // In IE9, reads to any property (e.g. status) off of an aborted XHR will
1730 // result in the error "Could not complete the operation due to error c00c023f"
1731 var status;
1732 try { status = xhr.status } catch(e) { status = 0; }
1733
1734 if (!status) {
1735 if (self.timedout || self._aborted) return;
1736 return self.crossDomainError();
1737 }
1738 self.emit('end');
1739 };
1740
1741 // progress
1742 var handleProgress = function(direction, e) {
1743 if (e.total > 0) {
1744 e.percent = e.loaded / e.total * 100;
1745 }
1746 e.direction = direction;
1747 self.emit('progress', e);
1748 }
1749 if (this.hasListeners('progress')) {
1750 try {
1751 xhr.onprogress = handleProgress.bind(null, 'download');
1752 if (xhr.upload) {
1753 xhr.upload.onprogress = handleProgress.bind(null, 'upload');
1754 }
1755 } catch(e) {
1756 // Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist.
1757 // Reported here:
1758 // https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context
1759 }
1760 }
1761
1762 // initiate request
1763 try {
1764 if (this.username && this.password) {
1765 xhr.open(this.method, this.url, true, this.username, this.password);
1766 } else {
1767 xhr.open(this.method, this.url, true);
1768 }
1769 } catch (err) {
1770 // see #1149
1771 return this.callback(err);
1772 }
1773
1774 // CORS
1775 if (this._withCredentials) xhr.withCredentials = true;
1776
1777 // body
1778 if (!this._formData && 'GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !this._isHost(data)) {
1779 // serialize stuff
1780 var contentType = this._header['content-type'];
1781 var serialize = this._serializer || request.serialize[contentType ? contentType.split(';')[0] : ''];
1782 if (!serialize && isJSON(contentType)) {
1783 serialize = request.serialize['application/json'];
1784 }
1785 if (serialize) data = serialize(data);
1786 }
1787
1788 // set header fields
1789 for (var field in this.header) {
1790 if (null == this.header[field]) continue;
1791 xhr.setRequestHeader(field, this.header[field]);
1792 }
1793
1794 if (this._responseType) {
1795 xhr.responseType = this._responseType;
1796 }
1797
1798 // send stuff
1799 this.emit('request', this);
1800
1801 // IE11 xhr.send(undefined) sends 'undefined' string as POST payload (instead of nothing)
1802 // We need null here if data is undefined
1803 xhr.send(typeof data !== 'undefined' ? data : null);
1804 return this;
1805};
1806
1807/**
1808 * GET `url` with optional callback `fn(res)`.
1809 *
1810 * @param {String} url
1811 * @param {Mixed|Function} [data] or fn
1812 * @param {Function} [fn]
1813 * @return {Request}
1814 * @api public
1815 */
1816
1817request.get = function(url, data, fn){
1818 var req = request('GET', url);
1819 if ('function' == typeof data) fn = data, data = null;
1820 if (data) req.query(data);
1821 if (fn) req.end(fn);
1822 return req;
1823};
1824
1825/**
1826 * HEAD `url` with optional callback `fn(res)`.
1827 *
1828 * @param {String} url
1829 * @param {Mixed|Function} [data] or fn
1830 * @param {Function} [fn]
1831 * @return {Request}
1832 * @api public
1833 */
1834
1835request.head = function(url, data, fn){
1836 var req = request('HEAD', url);
1837 if ('function' == typeof data) fn = data, data = null;
1838 if (data) req.send(data);
1839 if (fn) req.end(fn);
1840 return req;
1841};
1842
1843/**
1844 * OPTIONS query to `url` with optional callback `fn(res)`.
1845 *
1846 * @param {String} url
1847 * @param {Mixed|Function} [data] or fn
1848 * @param {Function} [fn]
1849 * @return {Request}
1850 * @api public
1851 */
1852
1853request.options = function(url, data, fn){
1854 var req = request('OPTIONS', url);
1855 if ('function' == typeof data) fn = data, data = null;
1856 if (data) req.send(data);
1857 if (fn) req.end(fn);
1858 return req;
1859};
1860
1861/**
1862 * DELETE `url` with optional `data` and callback `fn(res)`.
1863 *
1864 * @param {String} url
1865 * @param {Mixed} [data]
1866 * @param {Function} [fn]
1867 * @return {Request}
1868 * @api public
1869 */
1870
1871function del(url, data, fn){
1872 var req = request('DELETE', url);
1873 if ('function' == typeof data) fn = data, data = null;
1874 if (data) req.send(data);
1875 if (fn) req.end(fn);
1876 return req;
1877};
1878
1879request['del'] = del;
1880request['delete'] = del;
1881
1882/**
1883 * PATCH `url` with optional `data` and callback `fn(res)`.
1884 *
1885 * @param {String} url
1886 * @param {Mixed} [data]
1887 * @param {Function} [fn]
1888 * @return {Request}
1889 * @api public
1890 */
1891
1892request.patch = function(url, data, fn){
1893 var req = request('PATCH', url);
1894 if ('function' == typeof data) fn = data, data = null;
1895 if (data) req.send(data);
1896 if (fn) req.end(fn);
1897 return req;
1898};
1899
1900/**
1901 * POST `url` with optional `data` and callback `fn(res)`.
1902 *
1903 * @param {String} url
1904 * @param {Mixed} [data]
1905 * @param {Function} [fn]
1906 * @return {Request}
1907 * @api public
1908 */
1909
1910request.post = function(url, data, fn){
1911 var req = request('POST', url);
1912 if ('function' == typeof data) fn = data, data = null;
1913 if (data) req.send(data);
1914 if (fn) req.end(fn);
1915 return req;
1916};
1917
1918/**
1919 * PUT `url` with optional `data` and callback `fn(res)`.
1920 *
1921 * @param {String} url
1922 * @param {Mixed|Function} [data] or fn
1923 * @param {Function} [fn]
1924 * @return {Request}
1925 * @api public
1926 */
1927
1928request.put = function(url, data, fn){
1929 var req = request('PUT', url);
1930 if ('function' == typeof data) fn = data, data = null;
1931 if (data) req.send(data);
1932 if (fn) req.end(fn);
1933 return req;
1934};
1935
1936},{"./is-function":1,"./is-object":2,"./request-base":3,"./response-base":4,"./should-retry":5,"emitter":7}]},{},[8])(8)
1937});
\No newline at end of file