commit
This commit is contained in:
parent
70e2f7a8aa
commit
008d2f30d7
675 changed files with 189892 additions and 0 deletions
324
node_modules/requests/index.js
generated
vendored
Normal file
324
node_modules/requests/index.js
generated
vendored
Normal file
|
@ -0,0 +1,324 @@
|
|||
'use strict';
|
||||
|
||||
var Requested = require('./requested')
|
||||
, listeners = require('loads')
|
||||
, send = require('xhr-send')
|
||||
, hang = require('hang')
|
||||
, AXO = require('axo')
|
||||
, XMLHttpRequest = require('node-http-xhr');
|
||||
|
||||
/**
|
||||
* RequestS(tream).
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* - streaming: Should the request be streaming.
|
||||
* - method: Which HTTP method should be used.
|
||||
* - headers: Additional request headers.
|
||||
* - mode: Enable CORS mode.
|
||||
* - body: The payload for the request.
|
||||
*
|
||||
* @constructor
|
||||
* @param {String} url The URL we want to request.
|
||||
* @param {Object} options Various of request options.
|
||||
* @api public
|
||||
*/
|
||||
var Requests = module.exports = Requested.extend({
|
||||
constructor: function bobthebuilder(url, options) {
|
||||
if (!(this instanceof Requests)) return new Requests(url, options);
|
||||
|
||||
Requested.apply(this, arguments);
|
||||
},
|
||||
|
||||
/**
|
||||
* The offset of data that we've already previously read
|
||||
*
|
||||
* @type {Number}
|
||||
* @private
|
||||
*/
|
||||
offset: 0,
|
||||
|
||||
/**
|
||||
* The requests instance has been fully initialized.
|
||||
*
|
||||
* @param {String} url The URL we need to connect to.
|
||||
* @api private
|
||||
*/
|
||||
initialize: function initialize(url) {
|
||||
this.socket = Requests[Requests.method](this);
|
||||
|
||||
//
|
||||
// Open the socket BEFORE adding any properties to the instance as this might
|
||||
// trigger a thrown `InvalidStateError: An attempt was made to use an object
|
||||
// that is not, or is no longer, usable` error in FireFox:
|
||||
//
|
||||
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=707484
|
||||
//
|
||||
this.socket.open(this.method.toUpperCase(), url, true);
|
||||
|
||||
//
|
||||
// Register this as an active HTTP request.
|
||||
//
|
||||
Requests.active[this.id] = this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize and start requesting the supplied resource.
|
||||
*
|
||||
* @param {Object} options Passed in defaults.
|
||||
* @api private
|
||||
*/
|
||||
open: function open() {
|
||||
var what
|
||||
, slice = true
|
||||
, requests = this
|
||||
, socket = requests.socket;
|
||||
|
||||
requests.on('stream', function stream(data) {
|
||||
if (!slice) {
|
||||
return requests.emit('data', data);
|
||||
}
|
||||
|
||||
//
|
||||
// Please note that we need to use a method here that works on both string
|
||||
// as well as ArrayBuffer's as we have no certainty that we're receiving
|
||||
// text.
|
||||
//
|
||||
var chunk = data.slice(requests.offset);
|
||||
requests.offset = data.length;
|
||||
|
||||
requests.emit('data', chunk);
|
||||
});
|
||||
|
||||
requests.on('end', function cleanup() {
|
||||
delete Requests.active[requests.id];
|
||||
});
|
||||
|
||||
if (this.timeout) {
|
||||
socket.timeout = +this.timeout;
|
||||
}
|
||||
|
||||
if ('cors' === this.mode.toLowerCase() && 'withCredentials' in socket) {
|
||||
socket.withCredentials = true;
|
||||
}
|
||||
|
||||
//
|
||||
// ActiveXObject will throw an `Type Mismatch` exception when setting the to
|
||||
// an null-value and to be consistent with all XHR implementations we're going
|
||||
// to cast the value to a string.
|
||||
//
|
||||
// While we don't technically support the XDomainRequest of IE, we do want to
|
||||
// double check that the setRequestHeader is available before adding headers.
|
||||
//
|
||||
// Chrome has a bug where it will actually append values to the header instead
|
||||
// of overriding it. So if you do a double setRequestHeader(Content-Type) with
|
||||
// text/plain and with text/plain again, it will end up as `text/plain,
|
||||
// text/plain` as header value. This is why use a headers object as it
|
||||
// already eliminates duplicate headers.
|
||||
//
|
||||
for (what in this.headers) {
|
||||
if (this.headers[what] !== undefined && this.socket.setRequestHeader) {
|
||||
this.socket.setRequestHeader(what, this.headers[what] +'');
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Set the correct responseType method.
|
||||
//
|
||||
if (requests.streaming) {
|
||||
if (!this.body || 'string' === typeof this.body) {
|
||||
if ('multipart' in socket) {
|
||||
socket.multipart = true;
|
||||
slice = false;
|
||||
} else if (Requests.type.mozchunkedtext) {
|
||||
socket.responseType = 'moz-chunked-text';
|
||||
slice = false;
|
||||
}
|
||||
} else {
|
||||
if (Requests.type.mozchunkedarraybuffer) {
|
||||
socket.responseType = 'moz-chunked-arraybuffer';
|
||||
} else if (Requests.type.msstream) {
|
||||
socket.responseType = 'ms-stream';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listeners(socket, requests, requests.streaming);
|
||||
requests.emit('before', socket);
|
||||
|
||||
send(socket, this.body, hang(function send(err) {
|
||||
if (err) {
|
||||
requests.emit('error', err);
|
||||
requests.emit('end', err);
|
||||
}
|
||||
|
||||
requests.emit('send');
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Completely destroy the running XHR and release of the internal references.
|
||||
*
|
||||
* @returns {Boolean} Successful destruction
|
||||
* @api public
|
||||
*/
|
||||
destroy: function destroy() {
|
||||
if (!this.socket) return false;
|
||||
|
||||
this.emit('destroy');
|
||||
|
||||
this.socket.abort();
|
||||
this.removeAllListeners();
|
||||
|
||||
this.headers = {};
|
||||
this.socket = null;
|
||||
this.body = null;
|
||||
|
||||
delete Requests.active[this.id];
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Create a new XMLHttpRequest.
|
||||
*
|
||||
* @returns {XMLHttpRequest}
|
||||
* @api private
|
||||
*/
|
||||
Requests.XHR = function create() {
|
||||
try { return new XMLHttpRequest(); }
|
||||
catch (e) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new ActiveXObject which can be used for XHR.
|
||||
*
|
||||
* @returns {ActiveXObject}
|
||||
* @api private
|
||||
*/
|
||||
Requests.AXO = function create() {
|
||||
var ids = ['MSXML2.XMLHTTP.6.0', 'MSXML2.XMLHTTP.3.0', 'Microsoft.XMLHTTP']
|
||||
, id;
|
||||
|
||||
while (ids.length) {
|
||||
id = ids.shift();
|
||||
|
||||
try { return new AXO(id); }
|
||||
catch (e) {}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Requests that are currently running.
|
||||
*
|
||||
* @type {Object}
|
||||
* @private
|
||||
*/
|
||||
Requests.active = {};
|
||||
|
||||
/**
|
||||
* The type of technology we are using to establish a working Ajax connection.
|
||||
* This can either be:
|
||||
*
|
||||
* - XHR: XMLHttpRequest
|
||||
* - AXO: ActiveXObject
|
||||
*
|
||||
* This is also used as internal optimization so we can easily get the correct
|
||||
* constructor as we've already feature detected it.
|
||||
*
|
||||
* @type {String}
|
||||
* @public
|
||||
*/
|
||||
Requests.method = !!Requests.XHR() ? 'XHR' : (!!Requests.AXO() ? 'AXO' : '');
|
||||
|
||||
/**
|
||||
* Boolean indicating
|
||||
*
|
||||
* @type {Boolean}
|
||||
* @public
|
||||
*/
|
||||
Requests.supported = !!Requests.method;
|
||||
|
||||
/**
|
||||
* The different type of `responseType` parsers that are supported in this XHR
|
||||
* implementation.
|
||||
*
|
||||
* @type {Object}
|
||||
* @public
|
||||
*/
|
||||
Requests.type = 'XHR' === Requests.method ? (function detect() {
|
||||
var types = 'arraybuffer,blob,document,json,text,moz-blob,moz-chunked-text,moz-chunked-arraybuffer,ms-stream'.split(',')
|
||||
, supported = {}
|
||||
, type, xhr, prop;
|
||||
|
||||
while (types.length) {
|
||||
type = types.pop();
|
||||
prop = type.replace(/-/g, '');
|
||||
xhr = Requests.XHR();
|
||||
|
||||
//
|
||||
// Older versions of Firefox/IE11 will throw an error because previous
|
||||
// version of the specification do not support setting `responseType`
|
||||
// before the request is opened. Thus, we open the request here.
|
||||
//
|
||||
// Note that `open()` does not actually open any connections; it just
|
||||
// initializes the request object.
|
||||
//
|
||||
try {
|
||||
// Try opening a request to current page.
|
||||
xhr.open('get', '/', true);
|
||||
} catch (e) {
|
||||
// In JSDOM the above will fail because it only supports full URLs, so
|
||||
// try opening a request to localhost.
|
||||
try {
|
||||
xhr.open('get', 'http://localhost/', true);
|
||||
} catch (err) {
|
||||
supported[prop] = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
xhr.responseType = type;
|
||||
supported[prop] = 'response' in xhr && xhr.responseType === type;
|
||||
} catch (e) {
|
||||
supported[prop] = false;
|
||||
}
|
||||
|
||||
xhr = null;
|
||||
}
|
||||
|
||||
return supported;
|
||||
}()) : {};
|
||||
|
||||
/**
|
||||
* Do we support streaming response parsing.
|
||||
*
|
||||
* @type {Boolean}
|
||||
* @private
|
||||
*/
|
||||
Requests.streaming = 'XHR' === Requests.method && (
|
||||
'multipart' in XMLHttpRequest.prototype
|
||||
|| Requests.type.mozchunkedarraybuffer
|
||||
|| Requests.type.mozchunkedtext
|
||||
|| Requests.type.msstream
|
||||
|| Requests.type.mozblob
|
||||
);
|
||||
|
||||
//
|
||||
// IE has a bug which causes IE10 to freeze when close WebPage during an XHR
|
||||
// request: https://support.microsoft.com/kb/2856746
|
||||
//
|
||||
// The solution is to completely clean up all active running requests.
|
||||
//
|
||||
if (global.attachEvent) global.attachEvent('onunload', function reap() {
|
||||
for (var id in Requests.active) {
|
||||
Requests.active[id].destroy();
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// Expose the Requests library.
|
||||
//
|
||||
module.exports = Requests;
|
Loading…
Add table
Add a link
Reference in a new issue