superagent = function (method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
return new exports.Request(method, url);
}n/a
function Request(method, url) {
Stream.call(this);
if ('string' != typeof url) url = format(url);
this._agent = false;
this._formData = null;
this.method = method;
this.url = url;
_initHeaders(this);
this.writable = true;
this._redirects = 0;
this.redirects(method === 'HEAD' ? 0 : 5);
this.cookies = '';
this.qs = {};
this.qsRaw = [];
this._redirectList = [];
this._streamRequest = false;
this.once('end', this.clearTimeout.bind(this));
}...
/**
* Expose `request`.
*/
var request = exports = module.exports = function(method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
...function Response(req) {
Stream.call(this);
var res = this.res = req.res;
this.request = req;
this.req = req.req;
this.text = res.text;
this.body = res.body !== undefined ? res.body : {};
this.files = res.files || {};
this.buffered = 'string' == typeof this.text;
this.header = this.headers = res.headers;
this._setStatusProperties(res.statusCode);
this._setHeaderProperties(this.header);
this.setEncoding = res.setEncoding.bind(res);
res.on('data', this.emit.bind(this, 'data'));
res.on('end', this.emit.bind(this, 'end'));
res.on('close', this.emit.bind(this, 'close'));
res.on('error', this.emit.bind(this, 'error'));
}n/a
acl = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
function Agent(options) {
if (!(this instanceof Agent)) return new Agent(options);
if (options) {
this._ca = options.ca;
this._key = options.key;
this._pfx = options.pfx;
this._cert = options.cert;
}
this.jar = new CookieJar;
}n/a
checkout = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
client = function (method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
return new exports.Request(method, url);
}n/a
connect = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
copy = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
del = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
delete = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
get = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...head = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
link = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
lock = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
m-search = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
merge = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
mkactivity = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
mkcalendar = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
mkcol = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
move = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
notify = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
options = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
patch = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
post = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}...
$ npm install superagent
```
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
...propfind = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
proppatch = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
purge = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
put = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
rebind = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
report = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
function RequestBase(obj) {
if (obj) return mixin(obj);
}n/a
function ResponseBase(obj) {
if (obj) return mixin(obj);
}n/a
search = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
subscribe = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
trace = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
unbind = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
unlink = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
unlock = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
unsubscribe = function (url, data, fn){
var req = request(method, url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
fn && req.end(fn);
return req;
}n/a
function Request(method, url) {
Stream.call(this);
if ('string' != typeof url) url = format(url);
this._agent = false;
this._formData = null;
this.method = method;
this.url = url;
_initHeaders(this);
this.writable = true;
this._redirects = 0;
this.redirects(method === 'HEAD' ? 0 : 5);
this.cookies = '';
this.qs = {};
this.qsRaw = [];
this._redirectList = [];
this._streamRequest = false;
this.once('end', this.clearTimeout.bind(this));
}...
/**
* Expose `request`.
*/
var request = exports = module.exports = function(method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
...function Stream() {
EE.call(this);
}n/a
_appendQueryString = function (req){
var query = qs.stringify(this.qs, { indices: false, strictNullHandling: true });
query += ((query.length && this.qsRaw.length) ? '&' : '') + this.qsRaw.join('&');
req.path += query.length ? (~req.path.indexOf('?') ? '&' : '?') + query : '';
if (this._sort) {
var index = req.path.indexOf('?');
if (index >= 0) {
var queryArr = req.path.substring(index + 1).split('&');
if (isFunction(this._sort)) {
queryArr.sort(this._sort);
} else {
queryArr.sort();
}
req.path = req.path.substring(0, index) + '?' + queryArr.join('&');
}
}
}...
}
this._endCalled = true;
// store callback
this._callback = fn || noop;
// querystring
this._appendQueryString();
return this._end();
};
Request.prototype._end = function() {
var self = this;
var xhr = this.xhr = request.getXHR();
..._emitResponse = function (body, files){
var response = new Response(this);
this.response = response;
response.redirects = this._redirectList;
if (undefined !== body) {
response.body = body;
}
response.files = files;
this.emit('response', response);
return response;
}n/a
_end = function () {
var self = this;
var data = this._data;
var req = this.req;
var buffer = this._buffer;
var method = this.method;
this._setTimeouts();
// body
if ('HEAD' != method && !req._headerSent) {
// serialize stuff
if ('string' != typeof data) {
var contentType = req.getHeader('Content-Type')
// Parse out just the content type from the header (ignore the charset)
if (contentType) contentType = contentType.split(';')[0]
var serialize = exports.serialize[contentType];
if (!serialize && isJSON(contentType)) {
serialize = exports.serialize['application/json'];
}
if (serialize) data = serialize(data);
}
// content-length
if (data && !req.getHeader('Content-Length')) {
req.setHeader('Content-Length', Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data));
}
}
// response
req.once('response', function(res){
debug('%s %s -> %s', self.method, self.url, res.statusCode);
if (self._responseTimeoutTimer) {
clearTimeout(self._responseTimeoutTimer);
}
if (self.piped) {
return;
}
var max = self._maxRedirects;
var mime = utils.type(res.headers['content-type'] || '') || 'text/plain';
var type = mime.split('/')[0];
var multipart = 'multipart' == type;
var redirect = isRedirect(res.statusCode);
var parser = self._parser;
var responseType = self._responseType;
self.res = res;
// redirect
if (redirect && self._redirects++ != max) {
return self._redirect(res);
}
if ('HEAD' == self.method) {
self.emit('end');
self.callback(null, self._emitResponse());
return;
}
// zlib support
if (self._shouldUnzip(res)) {
unzip(req, res);
}
if (!parser) {
if (responseType) {
parser = exports.parse.image; // It's actually a generic Buffer
buffer = true;
} else if (multipart) {
var form = new formidable.IncomingForm();
parser = form.parse.bind(form);
buffer = true;
} else if (isImageOrVideo(mime)) {
parser = exports.parse.image;
buffer = true; // For backwards-compatibility buffering default is ad-hoc MIME-dependent
} else if (exports.parse[mime]) {
parser = exports.parse[mime];
} else if ('text' == type) {
parser = exports.parse.text;
buffer = (buffer !== false);
// everyone wants their own white-labeled json
} else if (isJSON(mime)) {
parser = exports.parse['application/json'];
buffer = (buffer !== false);
} else if (buffer) {
parser = exports.parse.text;
}
}
// by default only buffer text/*, json and messed up thing from hell
if (undefined === buffer && isText(mime) || isJSON(mime)) {
buffer = true;
}
var parserHandlesEnd = false;
if (parser) {
try {
// Unbuffered parsers are supposed to emit response early,
// which is weird BTW, because response.body won't be there.
parserHandlesEnd = buffer;
parser(res, function(err, obj, files) {
if (self.timedout) {
// Timeout has already handled all callbacks
return;
}
// Intentional (non-timeout) abort is supposed to preserve partial response,
// even if it doesn't parse.
if (err && !self._aborted) {
return self.callback(err);
}
if (parserHandlesEnd) {
self.emit('end');
self.callback(null, self._emitResponse(obj, files));
}
});
} catch (err) {
self.callback(err);
return;
}
}
self.res = res;
// unbuffered
if (!buffer) {
debug('unbuffered %s %s', self.method, self.url);
self.callback(null, self._emitResponse());
if (multipart) return // allow multipart to handle end event
res.once('end', function(){
debug('end %s %s', self.method, self.url);
self.emit('end');
})
return;
}
// terminating eve ......
// store callback
this._callback = fn || noop;
// querystring
this._appendQueryString();
return this._end();
};
Request.prototype._end = function() {
var self = this;
var xhr = this.xhr = request.getXHR();
var data = this._formData || this._data;
..._getFormData = function () {
if (!this._formData) {
this._formData = new FormData();
var that = this;
this._formData.on('error', function(err) {
that.emit('error', err);
that.abort();
});
}
return this._formData;
}...
Request.prototype.attach = function(field, file, options){
if (file) {
if (this._data) {
throw Error("superagent can't mix .send() and .attach()");
}
this._getFormData().append(field, file, options || file.name);
}
return this;
};
Request.prototype._getFormData = function(){
if (!this._formData) {
this._formData = new root.FormData();
...function _isHost(obj) {
return Buffer.isBuffer(obj) || obj instanceof Stream || obj instanceof FormData;
}...
return this.callback(err);
}
// CORS
if (this._withCredentials) xhr.withCredentials = true;
// body
if (!this._formData && 'GET' != this.method && 'HEAD' != this.method && '
string' != typeof data && !this._isHost(data)) {
// serialize stuff
var contentType = this._header['content-type'];
var serialize = this._serializer || request.serialize[contentType ? contentType.split(';')[0] : ''];
if (!serialize && isJSON(contentType)) {
serialize = request.serialize['application/json'];
}
if (serialize) data = serialize(data);
..._isResponseOK = function (res) {
if (!res) {
return false;
}
if (this._okCallback) {
return this._okCallback(res);
}
return res.status >= 200 && res.status < 300;
}...
return self.callback(err);
}
self.emit('response', res);
var new_err;
try {
if (!self._isResponseOK(res)) {
new_err = new Error(res.statusText || 'Unsuccessful HTTP response');
new_err.original = err;
new_err.response = res;
new_err.status = res.status;
}
} catch(e) {
new_err = e; // #985 touching res may cause INVALID_STATE_ERR on old Android
..._pipeContinue = function (stream, options){
var self = this;
this.req.once('response', function(res){
// redirect
var redirect = isRedirect(res.statusCode);
if (redirect && self._redirects++ != self._maxRedirects) {
return self._redirect(res)._pipeContinue(stream, options);
}
self.res = res;
self._emitResponse();
if (self._aborted) return;
if (self._shouldUnzip(res)) {
res.pipe(zlib.createUnzip()).pipe(stream, options);
} else {
res.pipe(stream, options);
}
res.once('end', function(){
self.emit('end');
});
});
return stream;
}n/a
_redirect = function (res){
var url = res.headers.location;
if (!url) {
return this.callback(new Error('No location header for redirect'), res);
}
debug('redirect %s -> %s', this.url, url);
// location
url = resolve(this.url, url);
// ensure the response is being consumed
// this is required for Node v0.10+
res.resume();
var headers = this.req._headers;
var shouldStripCookie = parse(url).host !== parse(this.url).host;
// implementation of 302 following defacto standard
if (res.statusCode == 301 || res.statusCode == 302){
// strip Content-* related fields
// in case of POST etc
headers = utils.cleanHeader(this.req._headers, shouldStripCookie);
// force GET
this.method = 'HEAD' == this.method
? 'HEAD'
: 'GET';
// clear data
this._data = null;
}
// 303 is always GET
if (res.statusCode == 303) {
// strip Content-* related fields
// in case of POST etc
headers = utils.cleanHeader(this.req._headers, shouldStripCookie);
// force method
this.method = 'GET';
// clear data
this._data = null;
}
// 307 preserves method
// 308 preserves method
delete headers.host;
delete this.req;
delete this._formData;
// remove all add header except User-Agent
_initHeaders(this)
// redirect
this._endCalled = false;
this.url = url;
this.qs = {};
this.qsRaw = [];
this.set(headers);
this.emit('redirect', res);
this._redirectList.push(this.url);
this.end(this._callback);
return this;
}n/a
_retry = function () {
this.clearTimeout();
// node
if (this.req) {
this.req = null;
this.req = this.request();
}
this._aborted = false;
this.timedout = false;
return this._end();
}...
* @param {Response} res
* @api private
*/
Request.prototype.callback = function(err, res){
// console.log(this._retries, this._maxRetries)
if (this._maxRetries && this._retries++ < this._maxRetries && shouldRetry(err, res)) {
return this._retry();
}
var fn = this._callback;
this.clearTimeout();
if (err) {
if (this._maxRetries) err.retries = this._retries - 1;
..._setTimeouts = function () {
var self = this;
// deadline
if (this._timeout && !this._timer) {
this._timer = setTimeout(function(){
self._timeoutError('Timeout of ', self._timeout, 'ETIME');
}, this._timeout);
}
// response timeout
if (this._responseTimeout && !this._responseTimeoutTimer) {
this._responseTimeoutTimer = setTimeout(function(){
self._timeoutError('Response timeout of ', self._responseTimeout, 'ETIMEDOUT');
}, this._responseTimeout);
}
}...
};
Request.prototype._end = function() {
var self = this;
var xhr = this.xhr = request.getXHR();
var data = this._formData || this._data;
this._setTimeouts();
// state change
xhr.onreadystatechange = function(){
var readyState = xhr.readyState;
if (readyState >= 2 && self._responseTimeoutTimer) {
clearTimeout(self._responseTimeoutTimer);
}
..._shouldUnzip = function (res){
if (res.statusCode === 204 || res.statusCode === 304) {
// These aren't supposed to have any body
return false;
}
// header content is a string, and distinction between 0 and no information is crucial
if ('0' === res.headers['content-length']) {
// We know that the body is empty (unfortunately, this check does not cover chunked encoding)
return false;
}
// console.log(res);
return /^\s*(?:deflate|gzip)\s*$/.test(res.headers['content-encoding']);
}n/a
_timeoutError = function (reason, timeout, errno){
if (this._aborted) {
return;
}
var err = new Error(reason + timeout + 'ms exceeded');
err.timeout = timeout;
err.code = 'ECONNABORTED';
err.errno = errno;
this.timedout = true;
this.abort();
this.callback(err);
}...
RequestBase.prototype._setTimeouts = function() {
var self = this;
// deadline
if (this._timeout && !this._timer) {
this._timer = setTimeout(function(){
self._timeoutError('Timeout of ', self._timeout, 'ETIME');
}, this._timeout);
}
// response timeout
if (this._responseTimeout && !this._responseTimeoutTimer) {
this._responseTimeoutTimer = setTimeout(function(){
self._timeoutError('Response timeout of ', self._responseTimeout, 'ETIMEDOUT');
}, this._responseTimeout);
...abort = function (){
if (this._aborted) {
return this;
}
this._aborted = true;
this.xhr && this.xhr.abort(); // browser
this.req && this.req.abort(); // node
this.clearTimeout();
this.emit('abort');
return this;
}...
* @api public
*/
RequestBase.prototype.abort = function(){
if (this._aborted) {
return this;
}
this._aborted = true;
this.xhr && this.xhr.abort(); // browser
this.req && this.req.abort(); // node
this.clearTimeout();
this.emit('abort');
return this;
};
/**
...accept = function (type){
return this.set('Accept', ~type.indexOf('/')
? type
: mime.lookup(type));
}...
* Set Accept to `type`, mapping values from `request.types`.
*
* Examples:
*
* superagent.types.json = 'application/json';
*
* request.get('/agent')
* .accept('json')
* .end(callback);
*
* request.get('/agent')
* .accept('application/json')
* .end(callback);
*
* @param {String} accept
...agent = function (agent){
if (!arguments.length) return this._agent;
this._agent = agent;
return this;
}n/a
attach = function (field, file, options){
if (file) {
if (this._data) {
throw Error("superagent can't mix .send() and .attach()");
}
var o = options || {};
if ('string' == typeof options) {
o = { filename: options };
}
if ('string' == typeof file) {
if (!o.filename) o.filename = file;
debug('creating `fs.ReadStream` instance for file: %s', file);
file = fs.createReadStream(file);
} else if (!o.filename && file.path) {
o.filename = file.path;
}
this._getFormData().append(field, file, o);
}
return this;
}...
/**
* Queue the given `file` as an attachment to the specified `field`,
* with optional `options` (or filename).
*
* ``` js
* request.post('/upload')
* .attach('content', new Blob(['<a id="a"><
b id="b">hey!</b></a>'], { type: "text/html"}))
* .end(callback);
* ```
*
* @param {String} field
* @param {Blob|File} file
* @param {String|Object} options
* @return {Request} for chaining
...auth = function (user, pass, options){
if (1 === arguments.length) pass = '';
if (2 === arguments.length && typeof pass === 'object') options = pass;
if (!options) {
options = { type: 'basic' };
}
switch (options.type) {
case 'bearer':
return this.set('Authorization', 'Bearer ' + user);
default: // 'basic'
if (!~user.indexOf(':')) user = user + ':';
var str = new Buffer(user + pass).toString('base64');
return this.set('Authorization', 'Basic ' + str);
}
}...
break;
case 'auto':
this.username = user;
this.password = pass;
break;
case 'bearer': // usage would be .auth(accessToken, { type: 'bearer
' })
this.set('Authorization', 'Bearer ' + user);
break;
}
return this;
};
/**
...buffer = function (val){
this._buffer = (false !== val);
return this;
}n/a
ca = function (cert){
this._ca = cert;
return this;
}n/a
callback = function (err, res){
// console.log(this._retries, this._maxRetries)
if (this._maxRetries && this._retries++ < this._maxRetries && shouldRetry(err, res)) {
return this._retry();
}
// Avoid the error which is emitted from 'socket hang up' to cause the fn undefined error on JS runtime.
var fn = this._callback || noop;
this.clearTimeout();
if (this.called) return console.warn('superagent: double callback bug');
this.called = true;
if (!err) {
if (this._isResponseOK(res)) {
return fn(err, res);
}
var msg = 'Unsuccessful HTTP response';
if (res) {
msg = http.STATUS_CODES[res.status] || msg;
}
err = new Error(msg);
err.status = res ? res.status : undefined;
}
err.response = res;
if (this._maxRetries) err.retries = this._retries - 1;
// only emit error event if there is a listener
// otherwise we assume the callback to `.end()` will get the error
if (err && this.listeners('error').length > 0) {
this.emit('error', err);
}
fn(err, res);
}...
err.status = self.xhr.status ? self.xhr.status : null;
err.statusCode = err.status; // backwards-compat only
} else {
err.rawResponse = null;
err.status = null;
}
return self.callback(err);
}
self.emit('response', res);
var new_err;
try {
if (!self._isResponseOK(res)) {
...catch = function (cb) {
return this.then(undefined, cb);
}n/a
cert = function (cert){
this._cert = cert;
return this;
}n/a
function _clearTimeout(){
clearTimeout(this._timer);
clearTimeout(this._responseTimeoutTimer);
delete this._timer;
delete this._responseTimeoutTimer;
return this;
}...
Request.prototype.callback = function(err, res){
// console.log(this._retries, this._maxRetries)
if (this._maxRetries && this._retries++ < this._maxRetries && shouldRetry(err, res)) {
return this._retry();
}
var fn = this._callback;
this.clearTimeout();
if (err) {
if (this._maxRetries) err.retries = this._retries - 1;
this.emit('error', err);
}
fn(err, res);
...end = function (fn){
this.request();
debug('%s %s', this.method, this.url);
if (this._endCalled) {
console.warn("Warning: .end() was called twice. This is not supported in superagent");
}
this._endCalled = true;
// store callback
this._callback = fn || noop;
return this._end();
}...
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
## Supported browsers and Node versions
Tested browsers:
...field = function (name, val) {
// name should be either a string or an object.
if (null === name || undefined === name) {
throw new Error('.field(name, val) name can not be empty');
}
if (this._data) {
console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()");
}
if (isObject(name)) {
for (var key in name) {
this.field(key, name[key]);
}
return this;
}
if (Array.isArray(val)) {
for (var i in val) {
this.field(name, val[i]);
}
return this;
}
// val should be defined now
if (null === val || undefined === val) {
throw new Error('.field(name, val) val can not be empty');
}
if ('boolean' === typeof val) {
val = '' + val;
}
this._getFormData().append(name, val);
return this;
}...
Tested browsers:
- Latest Firefox, Chrome, Safari
- Latest Android, iPhone
- IE10 through latest. IE9 with polyfills.
Even though IE9 is supported, a polyfill for `window.FormData` is required for `.field()`.
Node 4 or later is required.
# Plugins
SuperAgent is easily extended via plugins.
...get = function (field){
return this._header[field.toLowerCase()];
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...getHeader = function (field){
return this._header[field.toLowerCase()];
}n/a
key = function (cert){
this._key = cert;
return this;
}n/a
ok = function (cb) {
if ('function' !== typeof cb) throw Error("Callback required");
this._okCallback = cb;
return this;
}n/a
function parse(fn){
this._parser = fn;
return this;
}n/a
pfx = function (cert){
this._pfx = cert;
return this;
}n/a
pipe = function (stream, options){
this.piped = true; // HACK...
this.buffer(false);
this.end();
return this._pipeContinue(stream, options);
}n/a
query = function (val){
if ('string' == typeof val) {
this.qsRaw.push(val);
return this;
}
extend(this.qs, val);
return this;
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...redirects = function (n){
this._maxRedirects = n;
return this;
}n/a
request = function (){
if (this.req) return this.req;
var self = this;
var options = {};
var url = this.url;
var retries = this._retries;
// default to http://
if (0 != url.indexOf('http')) url = 'http://' + url;
url = parse(url);
// support unix sockets
if (/^https?\+unix:/.test(url.protocol) === true) {
// get the protocol
url.protocol = url.protocol.split('+')[0] + ':';
// get the socket, path
var unixParts = url.path.match(/^([^/]+)(.+)$/);
options.socketPath = unixParts[1].replace(/%2F/g, '/');
url.pathname = unixParts[2];
}
// options
options.method = this.method;
options.port = url.port;
options.path = url.pathname;
options.host = url.hostname;
options.ca = this._ca;
options.key = this._key;
options.pfx = this._pfx;
options.cert = this._cert;
options.agent = this._agent;
// initiate request
var mod = exports.protocols[url.protocol];
// request
var req = this.req = mod.request(options);
if ('HEAD' != options.method) {
req.setHeader('Accept-Encoding', 'gzip, deflate');
}
this.protocol = url.protocol;
this.host = url.host;
// expose events
req.once('drain', function(){ self.emit('drain'); });
req.once('error', function(err){
// flag abortion here for out timeouts
// because node will emit a faux-error "socket hang up"
// when request is aborted before a connection is made
if (self._aborted) return;
// if not the same, we are in the **old** (cancelled) request,
// so need to continue (same as for above)
if (self._retries !== retries) return;
// if we've received a response then we don't want to let
// an error in the request blow up the response
if (self.response) return;
self.callback(err);
});
// auth
if (url.auth) {
var auth = url.auth.split(':');
this.auth(auth[0], auth[1]);
}
// query
if (url.search)
this.query(url.search.substr(1));
// add cookies
if (this.cookies) req.setHeader('Cookie', this.cookies);
for (var key in this.header) {
if (this.header.hasOwnProperty(key))
req.setHeader(key, this.header[key]);
}
try {
this._appendQueryString(req);
} catch (e) {
return this.emit('error', e);
}
return req;
}...
RequestBase.prototype._retry = function() {
this.clearTimeout();
// node
if (this.req) {
this.req = null;
this.req = this.request();
}
this._aborted = false;
this.timedout = false;
return this._end();
};
...responseType = function (val){
this._responseType = val;
return this;
}...
* which return Blob and ArrayBuffer, respectively.
*
* In Node all values result in Buffer.
*
* Examples:
*
* req.get('/')
* .responseType('blob')
* .end(callback);
*
* @param {String} val
* @return {Request} for chaining
* @api public
*/
...function retry(count){
// Default to 1 if no count passed or true
if (arguments.length === 0 || count === true) count = 1;
if (count <= 0) count = 0;
this._maxRetries = count;
this._retries = 0;
return this;
}n/a
send = function (data){
var isObj = isObject(data);
var type = this._header['content-type'];
if (this._formData) {
console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()");
}
if (isObj && !this._data) {
if (Array.isArray(data)) {
this._data = [];
} else if (!this._isHost(data)) {
this._data = {};
}
} else if (data && this._data && this._isHost(this._data)) {
throw Error("Can't merge these send calls");
}
// merge
if (isObj && isObject(this._data)) {
for (var key in data) {
this._data[key] = data[key];
}
} else if ('string' == typeof data) {
// default to x-www-form-urlencoded
if (!type) this.type('form');
type = this._header['content-type'];
if ('application/x-www-form-urlencoded' == type) {
this._data = this._data
? this._data + '&' + data
: data;
} else {
this._data = (this._data || '') + data;
}
} else {
this._data = data;
}
if (!isObj || this._isHost(data)) {
return this;
}
// default to json
if (!type) this.type('json');
return this;
}...
```
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
...function serialize(fn){
this._serializer = fn;
return this;
}n/a
set = function (field, val){
if (isObject(field)) {
for (var key in field) {
this.set(key, field[key]);
}
return this;
}
this._header[field.toLowerCase()] = val;
this.header[field] = val;
return this;
}...
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
## Supported browsers and Node versions
...sortQuery = function (sort) {
// _sort default to true but otherwise can be a function or boolean
this._sort = typeof sort === 'undefined' ? true : sort;
return this;
}...
*
* Examples:
*
* // default order
* request.get('/user')
* .query('name=Nick')
* .query('search=Manny')
* .sortQuery()
* .end(callback)
*
* // customized sort function
* request.get('/user')
* .query('name=Nick')
* .query('search=Manny')
* .sortQuery(function(a, b){
...function then(resolve, reject) {
if (!this._fullfilledPromise) {
var self = this;
if (this._endCalled) {
console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if
you use promises");
}
this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
self.end(function(err, res){
if (err) innerReject(err); else innerResolve(res);
});
});
}
return this._fullfilledPromise.then(resolve, reject);
}...
* @return {Request}
*/
RequestBase.prototype.then = function then(resolve, reject) {
if (!this._fullfilledPromise) {
var self = this;
if (this._endCalled) {
console.warn("Warning: superagent request was sent twice, because both .end() and .
then() were called. Never call .end() if you use promises");
}
this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
self.end(function(err, res){
if (err) innerReject(err); else innerResolve(res);
});
});
}
...function timeout(options){
if (!options || 'object' !== typeof options) {
this._timeout = options;
this._responseTimeout = 0;
return this;
}
for(var option in options) {
switch(option) {
case 'deadline':
this._timeout = options.deadline;
break;
case 'response':
this._responseTimeout = options.response;
break;
default:
console.warn("Unknown timeout option", option);
}
}
return this;
}n/a
toJSON = function (){
return {
method: this.method,
url: this.url,
data: this._data,
headers: this._header
};
}n/a
type = function (type){
return this.set('Content-Type', ~type.indexOf('/')
? type
: mime.lookup(type));
}...
* Set Content-Type to `type`, mapping values from `request.types`.
*
* Examples:
*
* superagent.types.xml = 'application/xml';
*
* request.post('/')
* .type('xml')
* .send(xmlstring)
* .end(callback);
*
* request.post('/')
* .type('application/xml')
* .send(xmlstring)
* .end(callback);
...unset = function (field){
delete this._header[field.toLowerCase()];
delete this.header[field];
return this;
}...
/**
* Remove header `field`.
* Case-insensitive.
*
* Example:
*
* req.get('/')
* .unset('User-Agent')
* .end(callback);
*
* @param {String} field
*/
RequestBase.prototype.unset = function(field){
delete this._header[field.toLowerCase()];
delete this.header[field];
...function use(fn) {
fn(this);
return this;
}...
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
Existing plugins:
...withCredentials = function (on){
// This is browser-only functionality. Node side is no-op.
if(on==undefined) on = true;
this._withCredentials = on;
return this;
}n/a
write = function (data, encoding){
var req = this.request();
if (!this._streamRequest) {
this._streamRequest = true;
}
return req.write(data, encoding);
}n/a
function Response(req) {
Stream.call(this);
var res = this.res = req.res;
this.request = req;
this.req = req.req;
this.text = res.text;
this.body = res.body !== undefined ? res.body : {};
this.files = res.files || {};
this.buffered = 'string' == typeof this.text;
this.header = this.headers = res.headers;
this._setStatusProperties(res.statusCode);
this._setHeaderProperties(this.header);
this.setEncoding = res.setEncoding.bind(res);
res.on('data', this.emit.bind(this, 'data'));
res.on('end', this.emit.bind(this, 'end'));
res.on('close', this.emit.bind(this, 'close'));
res.on('error', this.emit.bind(this, 'error'));
}n/a
function Stream() {
EE.call(this);
}n/a
_setHeaderProperties = function (header){
// TODO: moar!
// TODO: make this a util
// content-type
var ct = header['content-type'] || '';
this.type = utils.type(ct);
// params
var params = utils.params(ct);
for (var key in params) this[key] = params[key];
this.links = {};
// links
try {
if (header.link) {
this.links = utils.parseLinks(header.link);
}
} catch (err) {
// ignore
}
}...
}
this._setStatusProperties(status);
this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
// getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
// getResponseHeader still works. so we get content-type even if getting
// other headers fails.
this.header['content-type'] = this.xhr.getResponseHeader('content-type');
this._setHeaderProperties(this.header);
if (null === this.text && req._responseType) {
this.body = this.xhr.response;
} else {
this.body = this.req.method != 'HEAD'
? this._parseBody(this.text ? this.text : this.xhr.response)
: null;
..._setStatusProperties = function (status){
var type = status / 100 | 0;
// status / class
this.status = this.statusCode = status;
this.statusType = type;
// basics
this.info = 1 == type;
this.ok = 2 == type;
this.redirect = 3 == type;
this.clientError = 4 == type;
this.serverError = 5 == type;
this.error = (4 == type || 5 == type)
? this.toError()
: false;
// sugar
this.accepted = 202 == status;
this.noContent = 204 == status;
this.badRequest = 400 == status;
this.unauthorized = 401 == status;
this.notAcceptable = 406 == status;
this.forbidden = 403 == status;
this.notFound = 404 == status;
}...
: null;
this.statusText = this.req.xhr.statusText;
var status = this.xhr.status;
// handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
if (status === 1223) {
status = 204;
}
this._setStatusProperties(status);
this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
// getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
// getResponseHeader still works. so we get content-type even if getting
// other headers fails.
this.header['content-type'] = this.xhr.getResponseHeader('content-type');
this._setHeaderProperties(this.header);
...destroy = function (err){
this.res.destroy(err);
}n/a
get = function (field){
return this.header[field.toLowerCase()];
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...pause = function (){
this.res.pause();
}n/a
resume = function (){
this.res.resume();
}n/a
setStatusProperties = function (status){
console.warn("In superagent 2.x setStatusProperties is a private method");
return this._setStatusProperties(status);
}n/a
toError = function (){
var req = this.req;
var method = req.method;
var path = req.path;
var msg = 'cannot ' + method + ' ' + path + ' (' + this.status + ')';
var err = new Error(msg);
err.status = this.status;
err.text = this.text;
err.method = method;
err.path = path;
return err;
}...
// basics
this.info = 1 == type;
this.ok = 2 == type;
this.redirect = 3 == type;
this.clientError = 4 == type;
this.serverError = 5 == type;
this.error = (4 == type || 5 == type)
? this.toError()
: false;
// sugar
this.accepted = 202 == status;
this.noContent = 204 == status;
this.badRequest = 400 == status;
this.unauthorized = 401 == status;
...toJSON = function (){
return {
req: this.request.toJSON(),
header: this.header,
status: this.status,
text: this.text
};
}n/a
function Agent(options) {
if (!(this instanceof Agent)) return new Agent(options);
if (options) {
this._ca = options.ca;
this._key = options.key;
this._pfx = options.pfx;
this._cert = options.cert;
}
this.jar = new CookieJar;
}n/a
_attachCookies = function (req){
var url = parse(req.url);
var access = CookieAccess(url.hostname, url.pathname, 'https:' == url.protocol);
var cookies = this.jar.getCookies(access).toValueString();
req.cookies = cookies;
}n/a
_saveCookies = function (res){
var cookies = res.headers['set-cookie'];
if (cookies) this.jar.setCookies(cookies);
}n/a
acl = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
bind = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}...
e.percent = e.loaded / e.total * 100;
}
e.direction = direction;
self.emit('progress', e);
}
if (this.hasListeners('progress')) {
try {
xhr.onprogress = handleProgress.bind(null, 'download');
if (xhr.upload) {
xhr.upload.onprogress = handleProgress.bind(null, 'upload');
}
} catch(e) {
// Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist.
// Reported here:
// https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web
-worker-context
...checkout = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
connect = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
copy = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
del = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
delete = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
get = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...head = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
link = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
lock = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
m-search = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
merge = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
mkactivity = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
mkcalendar = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
mkcol = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
move = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
notify = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
options = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
patch = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
post = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}...
$ npm install superagent
```
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
...propfind = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
proppatch = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
purge = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
put = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
rebind = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
report = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
search = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
subscribe = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
trace = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
unbind = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
unlink = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
unlock = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
unsubscribe = function (url, fn){
var req = new request.Request(method, url);
req.ca(this._ca);
req.key(this._key);
req.pfx(this._pfx);
req.cert(this._cert);
req.on('response', this._saveCookies.bind(this));
req.on('redirect', this._saveCookies.bind(this));
req.on('redirect', this._attachCookies.bind(this, req));
this._attachCookies(req);
fn && req.end(fn);
return req;
}n/a
client = function (method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
return new exports.Request(method, url);
}n/a
function Request(method, url) {
var self = this;
this._query = this._query || [];
this.method = method;
this.url = url;
this.header = {}; // preserves header name case
this._header = {}; // coerces header names to lowercase
this.on('end', function(){
var err = null;
var res = null;
try {
res = new Response(self);
} catch(e) {
err = new Error('Parser is unable to parse the response');
err.parse = true;
err.original = e;
// issue #675: return the raw response if the response parsing fails
if (self.xhr) {
// ie9 doesn't have 'response' property
err.rawResponse = typeof self.xhr.responseType == 'undefined' ? self.xhr.responseText : self.xhr.response;
// issue #876: return the http status code if the response parsing fails
err.status = self.xhr.status ? self.xhr.status : null;
err.statusCode = err.status; // backwards-compat only
} else {
err.rawResponse = null;
err.status = null;
}
return self.callback(err);
}
self.emit('response', res);
var new_err;
try {
if (!self._isResponseOK(res)) {
new_err = new Error(res.statusText || 'Unsuccessful HTTP response');
new_err.original = err;
new_err.response = res;
new_err.status = res.status;
}
} catch(e) {
new_err = e; // #985 touching res may cause INVALID_STATE_ERR on old Android
}
// #1000 don't catch errors from the callback to avoid double calling it
if (new_err) {
self.callback(new_err, res);
} else {
self.callback(null, res);
}
});
}...
/**
* Expose `request`.
*/
var request = exports = module.exports = function(method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
...function Response(req) {
this.req = req;
this.xhr = this.req.xhr;
// responseText is accessible only if responseType is '' or 'text' and on older browsers
this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr
.responseType === 'undefined')
? this.xhr.responseText
: null;
this.statusText = this.req.xhr.statusText;
var status = this.xhr.status;
// handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
if (status === 1223) {
status = 204;
}
this._setStatusProperties(status);
this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
// getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
// getResponseHeader still works. so we get content-type even if getting
// other headers fails.
this.header['content-type'] = this.xhr.getResponseHeader('content-type');
this._setHeaderProperties(this.header);
if (null === this.text && req._responseType) {
this.body = this.xhr.response;
} else {
this.body = this.req.method != 'HEAD'
? this._parseBody(this.text ? this.text : this.xhr.response)
: null;
}
}n/a
function del(url, data, fn){
var req = request('DELETE', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
function del(url, data, fn){
var req = request('DELETE', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
get = function (url, data, fn){
var req = request('GET', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.query(data);
if (fn) req.end(fn);
return req;
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...getXHR = function () {
if (root.XMLHttpRequest
&& (!root.location || 'file:' != root.location.protocol
|| !root.ActiveXObject)) {
return new XMLHttpRequest;
} else {
try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
}
throw Error("Browser-only verison of superagent could not find XHR");
}...
this._appendQueryString();
return this._end();
};
Request.prototype._end = function() {
var self = this;
var xhr = this.xhr = request.getXHR();
var data = this._formData || this._data;
this._setTimeouts();
// state change
xhr.onreadystatechange = function(){
var readyState = xhr.readyState;
...head = function (url, data, fn){
var req = request('HEAD', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
options = function (url, data, fn){
var req = request('OPTIONS', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
function parseString(str) {
var obj = {};
var pairs = str.split('&');
var pair;
var pos;
for (var i = 0, len = pairs.length; i < len; ++i) {
pair = pairs[i];
pos = pair.indexOf('=');
if (pos == -1) {
obj[decodeURIComponent(pair)] = '';
} else {
obj[decodeURIComponent(pair.slice(0, pos))] =
decodeURIComponent(pair.slice(pos + 1));
}
}
return obj;
}n/a
patch = function (url, data, fn){
var req = request('PATCH', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
post = function (url, data, fn){
var req = request('POST', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}...
$ npm install superagent
```
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
...put = function (url, data, fn){
var req = request('PUT', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
function serialize(obj) {
if (!isObject(obj)) return obj;
var pairs = [];
for (var key in obj) {
pushEncodedKeyValuePair(pairs, key, obj[key]);
}
return pairs.join('&');
}n/a
image = function (res, fn){
var data = []; // Binary data needs binary storage
res.on('data', function(chunk){
data.push(chunk);
});
res.on('end', function () {
fn(null, Buffer.concat(data));
});
}n/a
text = function (res, fn){
res.text = '';
res.setEncoding('utf8');
res.on('data', function(chunk){ res.text += chunk; });
res.on('end', fn);
}n/a
function RequestBase(obj) {
if (obj) return mixin(obj);
}n/a
_isResponseOK = function (res) {
if (!res) {
return false;
}
if (this._okCallback) {
return this._okCallback(res);
}
return res.status >= 200 && res.status < 300;
}...
return self.callback(err);
}
self.emit('response', res);
var new_err;
try {
if (!self._isResponseOK(res)) {
new_err = new Error(res.statusText || 'Unsuccessful HTTP response');
new_err.original = err;
new_err.response = res;
new_err.status = res.status;
}
} catch(e) {
new_err = e; // #985 touching res may cause INVALID_STATE_ERR on old Android
..._retry = function () {
this.clearTimeout();
// node
if (this.req) {
this.req = null;
this.req = this.request();
}
this._aborted = false;
this.timedout = false;
return this._end();
}...
* @param {Response} res
* @api private
*/
Request.prototype.callback = function(err, res){
// console.log(this._retries, this._maxRetries)
if (this._maxRetries && this._retries++ < this._maxRetries && shouldRetry(err, res)) {
return this._retry();
}
var fn = this._callback;
this.clearTimeout();
if (err) {
if (this._maxRetries) err.retries = this._retries - 1;
..._setTimeouts = function () {
var self = this;
// deadline
if (this._timeout && !this._timer) {
this._timer = setTimeout(function(){
self._timeoutError('Timeout of ', self._timeout, 'ETIME');
}, this._timeout);
}
// response timeout
if (this._responseTimeout && !this._responseTimeoutTimer) {
this._responseTimeoutTimer = setTimeout(function(){
self._timeoutError('Response timeout of ', self._responseTimeout, 'ETIMEDOUT');
}, this._responseTimeout);
}
}...
};
Request.prototype._end = function() {
var self = this;
var xhr = this.xhr = request.getXHR();
var data = this._formData || this._data;
this._setTimeouts();
// state change
xhr.onreadystatechange = function(){
var readyState = xhr.readyState;
if (readyState >= 2 && self._responseTimeoutTimer) {
clearTimeout(self._responseTimeoutTimer);
}
..._timeoutError = function (reason, timeout, errno){
if (this._aborted) {
return;
}
var err = new Error(reason + timeout + 'ms exceeded');
err.timeout = timeout;
err.code = 'ECONNABORTED';
err.errno = errno;
this.timedout = true;
this.abort();
this.callback(err);
}...
RequestBase.prototype._setTimeouts = function() {
var self = this;
// deadline
if (this._timeout && !this._timer) {
this._timer = setTimeout(function(){
self._timeoutError('Timeout of ', self._timeout, 'ETIME');
}, this._timeout);
}
// response timeout
if (this._responseTimeout && !this._responseTimeoutTimer) {
this._responseTimeoutTimer = setTimeout(function(){
self._timeoutError('Response timeout of ', self._responseTimeout, 'ETIMEDOUT');
}, this._responseTimeout);
...abort = function (){
if (this._aborted) {
return this;
}
this._aborted = true;
this.xhr && this.xhr.abort(); // browser
this.req && this.req.abort(); // node
this.clearTimeout();
this.emit('abort');
return this;
}...
* @api public
*/
RequestBase.prototype.abort = function(){
if (this._aborted) {
return this;
}
this._aborted = true;
this.xhr && this.xhr.abort(); // browser
this.req && this.req.abort(); // node
this.clearTimeout();
this.emit('abort');
return this;
};
/**
...catch = function (cb) {
return this.then(undefined, cb);
}n/a
function _clearTimeout(){
clearTimeout(this._timer);
clearTimeout(this._responseTimeoutTimer);
delete this._timer;
delete this._responseTimeoutTimer;
return this;
}...
Request.prototype.callback = function(err, res){
// console.log(this._retries, this._maxRetries)
if (this._maxRetries && this._retries++ < this._maxRetries && shouldRetry(err, res)) {
return this._retry();
}
var fn = this._callback;
this.clearTimeout();
if (err) {
if (this._maxRetries) err.retries = this._retries - 1;
this.emit('error', err);
}
fn(err, res);
...field = function (name, val) {
// name should be either a string or an object.
if (null === name || undefined === name) {
throw new Error('.field(name, val) name can not be empty');
}
if (this._data) {
console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()");
}
if (isObject(name)) {
for (var key in name) {
this.field(key, name[key]);
}
return this;
}
if (Array.isArray(val)) {
for (var i in val) {
this.field(name, val[i]);
}
return this;
}
// val should be defined now
if (null === val || undefined === val) {
throw new Error('.field(name, val) val can not be empty');
}
if ('boolean' === typeof val) {
val = '' + val;
}
this._getFormData().append(name, val);
return this;
}...
Tested browsers:
- Latest Firefox, Chrome, Safari
- Latest Android, iPhone
- IE10 through latest. IE9 with polyfills.
Even though IE9 is supported, a polyfill for `window.FormData` is required for `.field()`.
Node 4 or later is required.
# Plugins
SuperAgent is easily extended via plugins.
...get = function (field){
return this._header[field.toLowerCase()];
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...getHeader = function (field){
return this._header[field.toLowerCase()];
}n/a
ok = function (cb) {
if ('function' !== typeof cb) throw Error("Callback required");
this._okCallback = cb;
return this;
}n/a
function parse(fn){
this._parser = fn;
return this;
}n/a
redirects = function (n){
this._maxRedirects = n;
return this;
}n/a
responseType = function (val){
this._responseType = val;
return this;
}...
* which return Blob and ArrayBuffer, respectively.
*
* In Node all values result in Buffer.
*
* Examples:
*
* req.get('/')
* .responseType('blob')
* .end(callback);
*
* @param {String} val
* @return {Request} for chaining
* @api public
*/
...function retry(count){
// Default to 1 if no count passed or true
if (arguments.length === 0 || count === true) count = 1;
if (count <= 0) count = 0;
this._maxRetries = count;
this._retries = 0;
return this;
}n/a
send = function (data){
var isObj = isObject(data);
var type = this._header['content-type'];
if (this._formData) {
console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()");
}
if (isObj && !this._data) {
if (Array.isArray(data)) {
this._data = [];
} else if (!this._isHost(data)) {
this._data = {};
}
} else if (data && this._data && this._isHost(this._data)) {
throw Error("Can't merge these send calls");
}
// merge
if (isObj && isObject(this._data)) {
for (var key in data) {
this._data[key] = data[key];
}
} else if ('string' == typeof data) {
// default to x-www-form-urlencoded
if (!type) this.type('form');
type = this._header['content-type'];
if ('application/x-www-form-urlencoded' == type) {
this._data = this._data
? this._data + '&' + data
: data;
} else {
this._data = (this._data || '') + data;
}
} else {
this._data = data;
}
if (!isObj || this._isHost(data)) {
return this;
}
// default to json
if (!type) this.type('json');
return this;
}...
```
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
...function serialize(fn){
this._serializer = fn;
return this;
}n/a
set = function (field, val){
if (isObject(field)) {
for (var key in field) {
this.set(key, field[key]);
}
return this;
}
this._header[field.toLowerCase()] = val;
this.header[field] = val;
return this;
}...
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
## Supported browsers and Node versions
...sortQuery = function (sort) {
// _sort default to true but otherwise can be a function or boolean
this._sort = typeof sort === 'undefined' ? true : sort;
return this;
}...
*
* Examples:
*
* // default order
* request.get('/user')
* .query('name=Nick')
* .query('search=Manny')
* .sortQuery()
* .end(callback)
*
* // customized sort function
* request.get('/user')
* .query('name=Nick')
* .query('search=Manny')
* .sortQuery(function(a, b){
...function then(resolve, reject) {
if (!this._fullfilledPromise) {
var self = this;
if (this._endCalled) {
console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if
you use promises");
}
this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
self.end(function(err, res){
if (err) innerReject(err); else innerResolve(res);
});
});
}
return this._fullfilledPromise.then(resolve, reject);
}...
* @return {Request}
*/
RequestBase.prototype.then = function then(resolve, reject) {
if (!this._fullfilledPromise) {
var self = this;
if (this._endCalled) {
console.warn("Warning: superagent request was sent twice, because both .end() and .
then() were called. Never call .end() if you use promises");
}
this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
self.end(function(err, res){
if (err) innerReject(err); else innerResolve(res);
});
});
}
...function timeout(options){
if (!options || 'object' !== typeof options) {
this._timeout = options;
this._responseTimeout = 0;
return this;
}
for(var option in options) {
switch(option) {
case 'deadline':
this._timeout = options.deadline;
break;
case 'response':
this._responseTimeout = options.response;
break;
default:
console.warn("Unknown timeout option", option);
}
}
return this;
}n/a
toJSON = function (){
return {
method: this.method,
url: this.url,
data: this._data,
headers: this._header
};
}n/a
unset = function (field){
delete this._header[field.toLowerCase()];
delete this.header[field];
return this;
}...
/**
* Remove header `field`.
* Case-insensitive.
*
* Example:
*
* req.get('/')
* .unset('User-Agent')
* .end(callback);
*
* @param {String} field
*/
RequestBase.prototype.unset = function(field){
delete this._header[field.toLowerCase()];
delete this.header[field];
...function use(fn) {
fn(this);
return this;
}...
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
Existing plugins:
...withCredentials = function (on){
// This is browser-only functionality. Node side is no-op.
if(on==undefined) on = true;
this._withCredentials = on;
return this;
}n/a
function ResponseBase(obj) {
if (obj) return mixin(obj);
}n/a
_setHeaderProperties = function (header){
// TODO: moar!
// TODO: make this a util
// content-type
var ct = header['content-type'] || '';
this.type = utils.type(ct);
// params
var params = utils.params(ct);
for (var key in params) this[key] = params[key];
this.links = {};
// links
try {
if (header.link) {
this.links = utils.parseLinks(header.link);
}
} catch (err) {
// ignore
}
}...
}
this._setStatusProperties(status);
this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
// getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
// getResponseHeader still works. so we get content-type even if getting
// other headers fails.
this.header['content-type'] = this.xhr.getResponseHeader('content-type');
this._setHeaderProperties(this.header);
if (null === this.text && req._responseType) {
this.body = this.xhr.response;
} else {
this.body = this.req.method != 'HEAD'
? this._parseBody(this.text ? this.text : this.xhr.response)
: null;
..._setStatusProperties = function (status){
var type = status / 100 | 0;
// status / class
this.status = this.statusCode = status;
this.statusType = type;
// basics
this.info = 1 == type;
this.ok = 2 == type;
this.redirect = 3 == type;
this.clientError = 4 == type;
this.serverError = 5 == type;
this.error = (4 == type || 5 == type)
? this.toError()
: false;
// sugar
this.accepted = 202 == status;
this.noContent = 204 == status;
this.badRequest = 400 == status;
this.unauthorized = 401 == status;
this.notAcceptable = 406 == status;
this.forbidden = 403 == status;
this.notFound = 404 == status;
}...
: null;
this.statusText = this.req.xhr.statusText;
var status = this.xhr.status;
// handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
if (status === 1223) {
status = 204;
}
this._setStatusProperties(status);
this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
// getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
// getResponseHeader still works. so we get content-type even if getting
// other headers fails.
this.header['content-type'] = this.xhr.getResponseHeader('content-type');
this._setHeaderProperties(this.header);
...get = function (field){
return this.header[field.toLowerCase()];
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...superagent = function (method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
return new exports.Request(method, url);
}n/a
function Request(method, url) {
var self = this;
this._query = this._query || [];
this.method = method;
this.url = url;
this.header = {}; // preserves header name case
this._header = {}; // coerces header names to lowercase
this.on('end', function(){
var err = null;
var res = null;
try {
res = new Response(self);
} catch(e) {
err = new Error('Parser is unable to parse the response');
err.parse = true;
err.original = e;
// issue #675: return the raw response if the response parsing fails
if (self.xhr) {
// ie9 doesn't have 'response' property
err.rawResponse = typeof self.xhr.responseType == 'undefined' ? self.xhr.responseText : self.xhr.response;
// issue #876: return the http status code if the response parsing fails
err.status = self.xhr.status ? self.xhr.status : null;
err.statusCode = err.status; // backwards-compat only
} else {
err.rawResponse = null;
err.status = null;
}
return self.callback(err);
}
self.emit('response', res);
var new_err;
try {
if (!self._isResponseOK(res)) {
new_err = new Error(res.statusText || 'Unsuccessful HTTP response');
new_err.original = err;
new_err.response = res;
new_err.status = res.status;
}
} catch(e) {
new_err = e; // #985 touching res may cause INVALID_STATE_ERR on old Android
}
// #1000 don't catch errors from the callback to avoid double calling it
if (new_err) {
self.callback(new_err, res);
} else {
self.callback(null, res);
}
});
}...
/**
* Expose `request`.
*/
var request = exports = module.exports = function(method, url) {
// callback
if ('function' == typeof url) {
return new exports.Request('GET', method).end(url);
}
// url first
if (1 == arguments.length) {
return new exports.Request('GET', method);
}
...function Response(req) {
this.req = req;
this.xhr = this.req.xhr;
// responseText is accessible only if responseType is '' or 'text' and on older browsers
this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr
.responseType === 'undefined')
? this.xhr.responseText
: null;
this.statusText = this.req.xhr.statusText;
var status = this.xhr.status;
// handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request
if (status === 1223) {
status = 204;
}
this._setStatusProperties(status);
this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());
// getAllResponseHeaders sometimes falsely returns "" for CORS requests, but
// getResponseHeader still works. so we get content-type even if getting
// other headers fails.
this.header['content-type'] = this.xhr.getResponseHeader('content-type');
this._setHeaderProperties(this.header);
if (null === this.text && req._responseType) {
this.body = this.xhr.response;
} else {
this.body = this.req.method != 'HEAD'
? this._parseBody(this.text ? this.text : this.xhr.response)
: null;
}
}n/a
function del(url, data, fn){
var req = request('DELETE', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
function del(url, data, fn){
var req = request('DELETE', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
get = function (url, data, fn){
var req = request('GET', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.query(data);
if (fn) req.end(fn);
return req;
}...
```js
var nocache = require('superagent-no-cache');
var request = require('superagent');
var prefix = require('superagent-prefix')('/static');
request
.get('/some-url')
.query({ action: 'edit', city: 'London' }) // query string
.use(prefix) // Prefixes *only* this request
.use(nocache) // Prevents caching of *only* this request
.end(function(err, res){
// Do something
});
```
...getXHR = function () {
if (root.XMLHttpRequest
&& (!root.location || 'file:' != root.location.protocol
|| !root.ActiveXObject)) {
return new XMLHttpRequest;
} else {
try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
}
throw Error("Browser-only verison of superagent could not find XHR");
}...
this._appendQueryString();
return this._end();
};
Request.prototype._end = function() {
var self = this;
var xhr = this.xhr = request.getXHR();
var data = this._formData || this._data;
this._setTimeouts();
// state change
xhr.onreadystatechange = function(){
var readyState = xhr.readyState;
...head = function (url, data, fn){
var req = request('HEAD', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
options = function (url, data, fn){
var req = request('OPTIONS', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
function parseString(str) {
var obj = {};
var pairs = str.split('&');
var pair;
var pos;
for (var i = 0, len = pairs.length; i < len; ++i) {
pair = pairs[i];
pos = pair.indexOf('=');
if (pos == -1) {
obj[decodeURIComponent(pair)] = '';
} else {
obj[decodeURIComponent(pair.slice(0, pos))] =
decodeURIComponent(pair.slice(pos + 1));
}
}
return obj;
}n/a
patch = function (url, data, fn){
var req = request('PATCH', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
post = function (url, data, fn){
var req = request('POST', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}...
$ npm install superagent
```
Works with [browserify](https://github.com/substack/node-browserify) and should work with [webpack](https://github.com/visionmedia
/superagent/wiki/SuperAgent-for-Webpack)
```js
request
.post('/api/pet')
.send({ name: 'Manny', species: 'cat' })
.set('X-API-Key', 'foobar')
.set('Accept', 'application/json')
.end(function(err, res){
// Calling the end function will send the request
});
```
...put = function (url, data, fn){
var req = request('PUT', url);
if ('function' == typeof data) fn = data, data = null;
if (data) req.send(data);
if (fn) req.end(fn);
return req;
}n/a
function serialize(obj) {
if (!isObject(obj)) return obj;
var pairs = [];
for (var key in obj) {
pushEncodedKeyValuePair(pairs, key, obj[key]);
}
return pairs.join('&');
}n/a
cleanHeader = function (header, shouldStripCookie){
delete header['content-type'];
delete header['content-length'];
delete header['transfer-encoding'];
delete header['host'];
if (shouldStripCookie) {
delete header['cookie'];
}
return header;
}n/a
params = function (str){
return str.split(/ *; */).reduce(function(obj, str){
var parts = str.split(/ *= */);
var key = parts.shift();
var val = parts.shift();
if (key && val) obj[key] = val;
return obj;
}, {});
}...
// TODO: make this a util
// content-type
var ct = header['content-type'] || '';
this.type = utils.type(ct);
// params
var params = utils.params(ct);
for (var key in params) this[key] = params[key];
this.links = {};
// links
try {
if (header.link) {
...parseLinks = function (str){
return str.split(/ *, */).reduce(function(obj, str){
var parts = str.split(/ *; */);
var url = parts[0].slice(1, -1);
var rel = parts[1].split(/ *= */)[1].slice(1, -1);
obj[rel] = url;
return obj;
}, {});
}...
for (var key in params) this[key] = params[key];
this.links = {};
// links
try {
if (header.link) {
this.links = utils.parseLinks(header.link);
}
} catch (err) {
// ignore
}
};
/**
...type = function (str){
return str.split(/ *; */).shift();
}...
* Set Content-Type to `type`, mapping values from `request.types`.
*
* Examples:
*
* superagent.types.xml = 'application/xml';
*
* request.post('/')
* .type('xml')
* .send(xmlstring)
* .end(callback);
*
* request.post('/')
* .type('application/xml')
* .send(xmlstring)
* .end(callback);
...