Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into gh-pages
Browse files Browse the repository at this point in the history
* origin/master: (32 commits)
  Progress event doc
  v3.5.0
  Add errno to distinguish between request timeout and body download timeout (#1184)
  Warn about bogus timeout options (#1185)
  3.4.4
  Treat videos like images
  Avoid renaming module
  3.4.3
  3.4.3
  Add node client support for bearer token authentication
  Add client support for bearer token authentication
  Fixed being able to define own parsers when their mime type starts with text/
  conditional withCredentials
  3.4.2
  Updated dependencies
  Use formData.on instead of .once
  Ignore attach(,null)
  3.4.1
  Simplify check
  Dedupe query string append
  ...
  • Loading branch information
kornelski committed Mar 5, 2017
2 parents 200e8f3 + 9bacdbc commit cbf8923
Show file tree
Hide file tree
Showing 19 changed files with 438 additions and 98 deletions.
28 changes: 28 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,31 @@
# 3.5.0 (2017-02-23)

* Add errno to distinguish between request timeout and body download timeout (#1184) (Kornel Lesiński)
* Warn about bogus timeout options (#1185) (Kornel Lesiński)

# 3.4.4 (2017-02-17)

* Treat videos like images (Kornel Lesiński)
* Avoid renaming module (Kornel Lesiński)

# 3.4.3 (2017-02-14)

* Fixed being able to define own parsers when their mime type starts with `text/` (Damien Clark)
* `withCredentials(false)` (Andy Woods)
* Use `formData.on` instead of `.once` (Kornel Lesiński)
* Ignore `attach("file",null)` (Kornel Lesiński)

# 3.4.1 (2017-01-29)

* Allow `retry()` and `retry(0)` (Alexander Pope)
* Allow optional body/data in DELETE requests (Alpha Shuro)
* Fixed query string on retried requests (Kornel Lesiński)

# 3.4.0 (2017-01-25)

* New `.retry(n)` method and `err.retries` (Alexander Pope)
* Docs for HTTPS request (Jun Wan Goh)

# 3.3.1 (2016-12-17)

* Fixed "double callback bug" warning on timeouts of gzipped responses
Expand Down
17 changes: 17 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,23 @@ Alternatively, you can use the `.ok(callback)` method to decide whether a respon
// reads 404 page as a successful response
})

## Progress tracking

SuperAgent fires `progress` events on upload and download of large files.

request.post(url)
.attach(file)
.on('progress', event => {
/* the event is:
{
direction: "upload" or "download"
percent: 0 to 100 // may be missing if file size is unknown
total: // total file size, may be missing
loaded: // bytes downloaded or uploaded so far
} */
})
.end()

## Promise and Generator support

SuperAgent's request is a "thenable" object that's compatible with JavaScript promises and `async`/`await` syntax. Do not call `.end()` if you're using promises.
Expand Down
14 changes: 14 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,20 @@ <h2 id="cors">CORS</h2>
.then(response =&gt; {
// reads 404 page as a successful response
})
</code></pre><h2 id="progress-tracking">Progress tracking</h2>
<p>SuperAgent fires <code>progress</code> events on upload and download of large files.</p>
<pre><code>request.post(url)
.attach(file)
.on(&#39;progress&#39;, event =&gt; {
/* the event is:
{
direction: &quot;upload&quot; or &quot;download&quot;
percent: 0 to 100 // may be missing if file size is unknown
total: // total file size, may be missing
loaded: // bytes downloaded or uploaded so far
} */
})
.end()
</code></pre><h2 id="promise-and-generator-support">Promise and Generator support</h2>
<p>SuperAgent&#39;s request is a &quot;thenable&quot; object that&#39;s compatible with JavaScript promises and <code>async</code>/<code>await</code> syntax. Do not call <code>.end()</code> if you&#39;re using promises.</p>
<p>Libraries like <a href="https://github.com/tj/co">co</a> or a web framework like <a href="https://github.com/koajs/koa">koa</a> can <code>yield</code> on any SuperAgent method:</p>
Expand Down
33 changes: 22 additions & 11 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if (typeof window !== 'undefined') { // Browser window
root = this;
}

var Emitter = require('emitter');
var Emitter = require('component-emitter');
var RequestBase = require('./request-base');
var isObject = require('./is-object');
var isFunction = require('./is-function');
Expand Down Expand Up @@ -292,8 +292,7 @@ function isJSON(mime) {
* @api private
*/

function Response(req, options) {
options = options || {};
function Response(req) {
this.req = req;
this.xhr = this.req.xhr;
// responseText is accessible only if responseType is '' or 'text' and on older browsers
Expand Down Expand Up @@ -502,13 +501,16 @@ Request.prototype.accept = function(type){
* Set Authorization field value with `user` and `pass`.
*
* @param {String} user
* @param {String} pass
* @param {Object} options with 'type' property 'auto' or 'basic' (default 'basic')
* @param {String} [pass] optional in case of using 'bearer' as type
* @param {Object} options with 'type' property 'auto', 'basic' or 'bearer' (default 'basic')
* @return {Request} for chaining
* @api public
*/

Request.prototype.auth = function(user, pass, options){
if (typeof pass === 'object' && pass !== null) { // pass is optional and can substitute for options
options = pass;
}
if (!options) {
options = {
type: 'function' === typeof btoa ? 'basic' : 'auto',
Expand All @@ -524,6 +526,10 @@ Request.prototype.auth = function(user, pass, options){
this.username = user;
this.password = pass;
break;

case 'bearer': // usage would be .auth(accessToken, { type: 'bearer' })
this.set('Authorization', 'Bearer ' + user);
break;
}
return this;
};
Expand Down Expand Up @@ -566,11 +572,13 @@ Request.prototype.query = function(val){
*/

Request.prototype.attach = function(field, file, options){
if (this._data) {
throw Error("superagent can't mix .send() and .attach()");
}
if (file) {
if (this._data) {
throw Error("superagent can't mix .send() and .attach()");
}

this._getFormData().append(field, file, options || file.name);
this._getFormData().append(field, file, options || file.name);
}
return this;
};

Expand Down Expand Up @@ -848,16 +856,19 @@ request.options = function(url, data, fn){
};

/**
* DELETE `url` with optional callback `fn(res)`.
* DELETE `url` with optional `data` and callback `fn(res)`.
*
* @param {String} url
* @param {Mixed} [data]
* @param {Function} [fn]
* @return {Request}
* @api public
*/

function del(url, fn){
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;
};
Expand Down
109 changes: 54 additions & 55 deletions lib/node/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,34 +183,37 @@ RequestBase(Request.prototype);
*/

Request.prototype.attach = function(field, file, options){
if (this._data) {
throw Error("superagent can't mix .send() and .attach()");
}
if (file) {
if (this._data) {
throw Error("superagent can't mix .send() and .attach()");
}

var o = options || {};
if ('string' == typeof options) {
o = { filename: options };
}
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;
}
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);
this._getFormData().append(field, file, o);
}
return this;
};

Request.prototype._getFormData = function() {
if (!this._formData) {
this._formData = new FormData();
this._formData.once('error', function(err) {
this.emit('error', err);
this.abort();
}.bind(this));
var that = this;
this._formData.on('error', function(err) {
that.emit('error', err);
that.abort();
});
}
return this._formData;
};
Expand Down Expand Up @@ -324,12 +327,6 @@ Request.prototype.write = function(data, encoding){
var req = this.request();
if (!this._streamRequest) {
this._streamRequest = true;
try {
// ensure querystring is appended before headers are sent
this._appendQueryString(req);
} catch (e) {
return this.emit('error', e);
}
}
return req.write(data, encoding);
};
Expand Down Expand Up @@ -471,18 +468,30 @@ Request.prototype._redirect = function(res){
* .auth('tobi', 'learnboost')
* .auth('tobi:learnboost')
* .auth('tobi')
* .auth(accessToken, { type: 'bearer' })
*
* @param {String} user
* @param {String} pass
* @param {String} [pass]
* @param {Object} [options] options with authorization type 'basic' or 'bearer' ('basic' is default)
* @return {Request} for chaining
* @api public
*/

Request.prototype.auth = function(user, pass){
Request.prototype.auth = function(user, pass, options){
if (1 === arguments.length) pass = '';
if (!~user.indexOf(':')) user = user + ':';
var str = new Buffer(user + pass).toString('base64');
return this.set('Authorization', 'Basic ' + str);
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);
}
};

/**
Expand Down Expand Up @@ -600,7 +609,7 @@ Request.prototype.request = function(){
// 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 recieved a response then we don't want to let
// 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);
Expand All @@ -623,6 +632,12 @@ Request.prototype.request = function(){
req.setHeader(key, this.header[key]);
}

try {
this._appendQueryString(req);
} catch (e) {
return this.emit('error', e);
}

return req;
};

Expand Down Expand Up @@ -731,7 +746,7 @@ Request.prototype._emitResponse = function(body, files){
};

Request.prototype.end = function(fn){
var req = this.request();
this.request();
debug('%s %s', this.method, this.url);

if (this._endCalled) {
Expand All @@ -742,13 +757,6 @@ Request.prototype.end = function(fn){
// store callback
this._callback = fn || noop;

// querystring
try {
this._appendQueryString(req);
} catch (e) {
return this.callback(e);
}

return this._end();
};

Expand Down Expand Up @@ -826,14 +834,14 @@ Request.prototype._end = function() {
var form = new formidable.IncomingForm();
parser = form.parse.bind(form);
buffer = true;
} else if (isImage(mime)) {
} 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);
} else if (exports.parse[mime]) {
parser = exports.parse[mime];

// everyone wants their own white-labeled json
} else if (isJSON(mime)) {
Expand Down Expand Up @@ -1012,19 +1020,10 @@ function isText(mime) {
|| 'x-www-form-urlencoded' == subtype;
}

/**
* Check if `mime` is image
*
* @param {String} mime
* @return {Boolean}
* @api public
*/

function isImage(mime) {
var parts = mime.split('/');
var type = parts[0];
function isImageOrVideo(mime) {
var type = mime.split('/')[0];

return 'image' == type;
return 'image' == type || 'video' == type;
}

/**
Expand All @@ -1049,4 +1048,4 @@ function isJSON(mime) {

function isRedirect(code) {
return ~[301, 302, 303, 305, 307, 308].indexOf(code);
}
}
5 changes: 4 additions & 1 deletion lib/node/parsers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
exports['application/x-www-form-urlencoded'] = require('./urlencoded');
exports['application/json'] = require('./json');
exports.text = require('./text');
exports.image = require('./image');

var binary = require('./image');
exports['application/octet-stream'] = binary;
exports.image = binary;
3 changes: 1 addition & 2 deletions lib/node/response.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ module.exports = Response;
* @api private
*/

function Response(req, options) {
function Response(req) {
Stream.call(this);
options = options || {};
var res = this.res = req.res;
this.request = req;
this.req = req.req;
Expand Down
Loading

0 comments on commit cbf8923

Please sign in to comment.