| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 | 'use strict';var EventEmitter = require('events').EventEmitter  , inherits = require('inherits')  , utils = require('../../utils/event')  , urlUtils = require('../../utils/url')  , XHR = global.XMLHttpRequest  ;var debug = function() {};if (process.env.NODE_ENV !== 'production') {  debug = require('debug')('sockjs-client:browser:xhr');}function AbstractXHRObject(method, url, payload, opts) {  debug(method, url);  var self = this;  EventEmitter.call(this);  setTimeout(function () {    self._start(method, url, payload, opts);  }, 0);}inherits(AbstractXHRObject, EventEmitter);AbstractXHRObject.prototype._start = function(method, url, payload, opts) {  var self = this;  try {    this.xhr = new XHR();  } catch (x) {    // intentionally empty  }  if (!this.xhr) {    debug('no xhr');    this.emit('finish', 0, 'no xhr support');    this._cleanup();    return;  }  // several browsers cache POSTs  url = urlUtils.addQuery(url, 't=' + (+new Date()));  // Explorer tends to keep connection open, even after the  // tab gets closed: http://bugs.jquery.com/ticket/5280  this.unloadRef = utils.unloadAdd(function() {    debug('unload cleanup');    self._cleanup(true);  });  try {    this.xhr.open(method, url, true);    if (this.timeout && 'timeout' in this.xhr) {      this.xhr.timeout = this.timeout;      this.xhr.ontimeout = function() {        debug('xhr timeout');        self.emit('finish', 0, '');        self._cleanup(false);      };    }  } catch (e) {    debug('exception', e);    // IE raises an exception on wrong port.    this.emit('finish', 0, '');    this._cleanup(false);    return;  }  if ((!opts || !opts.noCredentials) && AbstractXHRObject.supportsCORS) {    debug('withCredentials');    // Mozilla docs says https://developer.mozilla.org/en/XMLHttpRequest :    // "This never affects same-site requests."    this.xhr.withCredentials = true;  }  if (opts && opts.headers) {    for (var key in opts.headers) {      this.xhr.setRequestHeader(key, opts.headers[key]);    }  }  this.xhr.onreadystatechange = function() {    if (self.xhr) {      var x = self.xhr;      var text, status;      debug('readyState', x.readyState);      switch (x.readyState) {      case 3:        // IE doesn't like peeking into responseText or status        // on Microsoft.XMLHTTP and readystate=3        try {          status = x.status;          text = x.responseText;        } catch (e) {          // intentionally empty        }        debug('status', status);        // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450        if (status === 1223) {          status = 204;        }        // IE does return readystate == 3 for 404 answers.        if (status === 200 && text && text.length > 0) {          debug('chunk');          self.emit('chunk', status, text);        }        break;      case 4:        status = x.status;        debug('status', status);        // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450        if (status === 1223) {          status = 204;        }        // IE returns this for a bad port        // http://msdn.microsoft.com/en-us/library/windows/desktop/aa383770(v=vs.85).aspx        if (status === 12005 || status === 12029) {          status = 0;        }        debug('finish', status, x.responseText);        self.emit('finish', status, x.responseText);        self._cleanup(false);        break;      }    }  };  try {    self.xhr.send(payload);  } catch (e) {    self.emit('finish', 0, '');    self._cleanup(false);  }};AbstractXHRObject.prototype._cleanup = function(abort) {  debug('cleanup');  if (!this.xhr) {    return;  }  this.removeAllListeners();  utils.unloadDel(this.unloadRef);  // IE needs this field to be a function  this.xhr.onreadystatechange = function() {};  if (this.xhr.ontimeout) {    this.xhr.ontimeout = null;  }  if (abort) {    try {      this.xhr.abort();    } catch (x) {      // intentionally empty    }  }  this.unloadRef = this.xhr = null;};AbstractXHRObject.prototype.close = function() {  debug('close');  this._cleanup(true);};AbstractXHRObject.enabled = !!XHR;// override XMLHttpRequest for IE6/7// obfuscate to avoid firewallsvar axo = ['Active'].concat('Object').join('X');if (!AbstractXHRObject.enabled && (axo in global)) {  debug('overriding xmlhttprequest');  XHR = function() {    try {      return new global[axo]('Microsoft.XMLHTTP');    } catch (e) {      return null;    }  };  AbstractXHRObject.enabled = !!new XHR();}var cors = false;try {  cors = 'withCredentials' in new XHR();} catch (ignored) {  // intentionally empty}AbstractXHRObject.supportsCORS = cors;module.exports = AbstractXHRObject;
 |