5 var Polling = require('./polling')
6 , util = require('../util')
7 , Emitter = require('../emitter')
8 , debug = require('debug')('engine.io-client:polling-xhr');
15 module.exports.Request = Request;
21 var global = 'undefined' != typeof window ? window : global;
24 * Obfuscated key for Blue Coat.
27 var xobject = global[['Active'].concat('Object').join('X')];
36 * XHR Polling constructor.
38 * @param {Object} opts
43 Polling.call(this, opts);
45 if (global.location) {
46 this.xd = opts.host != global.location.hostname ||
47 global.location.port != opts.port;
52 * Inherits from Polling.
55 util.inherits(XHR, Polling);
63 XHR.prototype.doOpen = function(){
65 util.defer(function(){
66 Polling.prototype.doOpen.call(self);
73 * @param {String} method
77 XHR.prototype.request = function(opts){
79 opts.uri = this.uri();
81 return new Request(opts);
87 * @param {String} data to send.
88 * @param {Function} called upon flush.
92 XHR.prototype.doWrite = function(data, fn){
93 var req = this.request({ method: 'POST', data: data });
95 req.on('success', fn);
96 req.on('error', function(err){
97 self.onError('xhr post error', err);
103 * Starts a poll cycle.
108 XHR.prototype.doPoll = function(){
110 var req = this.request();
112 req.on('data', function(data){
115 req.on('error', function(err){
116 self.onError('xhr poll error', err);
122 * Request constructor
124 * @param {Object} options
128 function Request(opts){
129 this.method = opts.method || 'GET';
132 this.async = false !== opts.async;
133 this.data = undefined != opts.data ? opts.data : null;
141 Emitter(Request.prototype);
144 * Creates the XHR object and sends the request.
149 Request.prototype.create = function(){
150 var xhr = this.xhr = util.request(this.xd);
153 xhr.open(this.method, this.uri, this.async);
155 if ('POST' == this.method) {
157 if (xhr.setRequestHeader) {
159 xhr.setRequestHeader('Content-type', 'text/plain;charset=UTF-8');
162 xhr.contentType = 'text/plain';
167 if (this.xd && global.XDomainRequest && xhr instanceof XDomainRequest) {
168 xhr.onerror = function(e){
171 xhr.onload = function(){
172 self.onData(xhr.responseText);
174 xhr.onprogress = empty;
177 if ('withCredentials' in xhr) {
178 xhr.withCredentials = true;
181 xhr.onreadystatechange = function(){
185 if (4 != xhr.readyState) return;
186 if (200 == xhr.status || 1223 == xhr.status) {
187 data = xhr.responseText;
189 self.onError(xhr.status);
195 if (undefined !== data) {
201 debug('sending xhr with url %s | data %s', this.uri, this.data);
205 this.index = Request.requestsCount++;
206 Request.requests[this.index] = this;
211 * Called upon successful response.
216 Request.prototype.onSuccess = function(){
217 this.emit('success');
222 * Called if we have data.
227 Request.prototype.onData = function(data){
228 this.emit('data', data);
238 Request.prototype.onError = function(err){
239 this.emit('error', err);
249 Request.prototype.cleanup = function(){
251 this.xhr.onreadystatechange = empty;
254 this.xhr.onload = this.xhr.onerror = empty;
261 delete Request.requests[this.index];
268 * Aborts the request.
273 Request.prototype.abort = function(){
278 Request.requestsCount = 0;
279 Request.requests = {};
281 global.attachEvent('onunload', function(){
282 for (var i in Request.requests) {
283 if (Request.requests.hasOwnProperty(i)) {
284 Request.requests[i].abort();