var capability = require('./capability');
							 | 
						|
								var inherits = require('inherits');
							 | 
						|
								var stream = require('readable-stream');
							 | 
						|
								
							 | 
						|
								var rStates = (exports.readyStates = {
							 | 
						|
								  UNSENT: 0,
							 | 
						|
								  OPENED: 1,
							 | 
						|
								  HEADERS_RECEIVED: 2,
							 | 
						|
								  LOADING: 3,
							 | 
						|
								  DONE: 4
							 | 
						|
								});
							 | 
						|
								
							 | 
						|
								var IncomingMessage = (exports.IncomingMessage = function (xhr, response, mode, fetchTimer) {
							 | 
						|
								  var self = this;
							 | 
						|
								  stream.Readable.call(self);
							 | 
						|
								
							 | 
						|
								  self._mode = mode;
							 | 
						|
								  self.headers = {};
							 | 
						|
								  self.rawHeaders = [];
							 | 
						|
								  self.trailers = {};
							 | 
						|
								  self.rawTrailers = [];
							 | 
						|
								
							 | 
						|
								  // Fake the 'close' event, but only once 'end' fires
							 | 
						|
								  self.on('end', function () {
							 | 
						|
								    // The nextTick is necessary to prevent the 'request' module from causing an infinite loop
							 | 
						|
								    process.nextTick(function () {
							 | 
						|
								      self.emit('close');
							 | 
						|
								    });
							 | 
						|
								  });
							 | 
						|
								
							 | 
						|
								  if (mode === 'fetch') {
							 | 
						|
								    self._fetchResponse = response;
							 | 
						|
								
							 | 
						|
								    self.url = response.url;
							 | 
						|
								    self.statusCode = response.status;
							 | 
						|
								    self.statusMessage = response.statusText;
							 | 
						|
								
							 | 
						|
								    response.headers.forEach(function (header, key) {
							 | 
						|
								      self.headers[key.toLowerCase()] = header;
							 | 
						|
								      self.rawHeaders.push(key, header);
							 | 
						|
								    });
							 | 
						|
								
							 | 
						|
								    if (capability.writableStream) {
							 | 
						|
								      var writable = new WritableStream({
							 | 
						|
								        write: function (chunk) {
							 | 
						|
								          return new Promise(function (resolve, reject) {
							 | 
						|
								            if (self._destroyed) {
							 | 
						|
								              reject();
							 | 
						|
								            } else if (self.push(new Buffer(chunk))) {
							 | 
						|
								              resolve();
							 | 
						|
								            } else {
							 | 
						|
								              self._resumeFetch = resolve;
							 | 
						|
								            }
							 | 
						|
								          });
							 | 
						|
								        },
							 | 
						|
								        close: function () {
							 | 
						|
								          global.clearTimeout(fetchTimer);
							 | 
						|
								          if (!self._destroyed) self.push(null);
							 | 
						|
								        },
							 | 
						|
								        abort: function (err) {
							 | 
						|
								          if (!self._destroyed) self.emit('error', err);
							 | 
						|
								        }
							 | 
						|
								      });
							 | 
						|
								
							 | 
						|
								      try {
							 | 
						|
								        response.body.pipeTo(writable).catch(function (err) {
							 | 
						|
								          global.clearTimeout(fetchTimer);
							 | 
						|
								          if (!self._destroyed) self.emit('error', err);
							 | 
						|
								        });
							 | 
						|
								        return;
							 | 
						|
								      } catch (e) {} // pipeTo method isn't defined. Can't find a better way to feature test this
							 | 
						|
								    }
							 | 
						|
								    // fallback for when writableStream or pipeTo aren't available
							 | 
						|
								    var reader = response.body.getReader();
							 | 
						|
								    function read() {
							 | 
						|
								      reader
							 | 
						|
								        .read()
							 | 
						|
								        .then(function (result) {
							 | 
						|
								          if (self._destroyed) return;
							 | 
						|
								          if (result.done) {
							 | 
						|
								            global.clearTimeout(fetchTimer);
							 | 
						|
								            self.push(null);
							 | 
						|
								            return;
							 | 
						|
								          }
							 | 
						|
								          self.push(new Buffer(result.value));
							 | 
						|
								          read();
							 | 
						|
								        })
							 | 
						|
								        .catch(function (err) {
							 | 
						|
								          global.clearTimeout(fetchTimer);
							 | 
						|
								          if (!self._destroyed) self.emit('error', err);
							 | 
						|
								        });
							 | 
						|
								    }
							 | 
						|
								    read();
							 | 
						|
								  } else {
							 | 
						|
								    self._xhr = xhr;
							 | 
						|
								    self._pos = 0;
							 | 
						|
								
							 | 
						|
								    self.url = xhr.responseURL;
							 | 
						|
								    self.statusCode = xhr.status;
							 | 
						|
								    self.statusMessage = xhr.statusText;
							 | 
						|
								    var headers = xhr.getAllResponseHeaders().split(/\r?\n/);
							 | 
						|
								    headers.forEach(function (header) {
							 | 
						|
								      var matches = header.match(/^([^:]+):\s*(.*)/);
							 | 
						|
								      if (matches) {
							 | 
						|
								        var key = matches[1].toLowerCase();
							 | 
						|
								        if (key === 'set-cookie') {
							 | 
						|
								          if (self.headers[key] === undefined) {
							 | 
						|
								            self.headers[key] = [];
							 | 
						|
								          }
							 | 
						|
								          self.headers[key].push(matches[2]);
							 | 
						|
								        } else if (self.headers[key] !== undefined) {
							 | 
						|
								          self.headers[key] += ', ' + matches[2];
							 | 
						|
								        } else {
							 | 
						|
								          self.headers[key] = matches[2];
							 | 
						|
								        }
							 | 
						|
								        self.rawHeaders.push(matches[1], matches[2]);
							 | 
						|
								      }
							 | 
						|
								    });
							 | 
						|
								
							 | 
						|
								    self._charset = 'x-user-defined';
							 | 
						|
								    if (!capability.overrideMimeType) {
							 | 
						|
								      var mimeType = self.rawHeaders['mime-type'];
							 | 
						|
								      if (mimeType) {
							 | 
						|
								        var charsetMatch = mimeType.match(/;\s*charset=([^;])(;|$)/);
							 | 
						|
								        if (charsetMatch) {
							 | 
						|
								          self._charset = charsetMatch[1].toLowerCase();
							 | 
						|
								        }
							 | 
						|
								      }
							 | 
						|
								      if (!self._charset) self._charset = 'utf-8'; // best guess
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								});
							 | 
						|
								
							 | 
						|
								inherits(IncomingMessage, stream.Readable);
							 | 
						|
								
							 | 
						|
								IncomingMessage.prototype._read = function () {
							 | 
						|
								  var self = this;
							 | 
						|
								
							 | 
						|
								  var resolve = self._resumeFetch;
							 | 
						|
								  if (resolve) {
							 | 
						|
								    self._resumeFetch = null;
							 | 
						|
								    resolve();
							 | 
						|
								  }
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								IncomingMessage.prototype._onXHRProgress = function () {
							 | 
						|
								  var self = this;
							 | 
						|
								
							 | 
						|
								  var xhr = self._xhr;
							 | 
						|
								
							 | 
						|
								  var response = null;
							 | 
						|
								  switch (self._mode) {
							 | 
						|
								    case 'text:vbarray': // For IE9
							 | 
						|
								      if (xhr.readyState !== rStates.DONE) break;
							 | 
						|
								      try {
							 | 
						|
								        // This fails in IE8
							 | 
						|
								        response = new global.VBArray(xhr.responseBody).toArray();
							 | 
						|
								      } catch (e) {}
							 | 
						|
								      if (response !== null) {
							 | 
						|
								        self.push(new Buffer(response));
							 | 
						|
								        break;
							 | 
						|
								      }
							 | 
						|
								    // Falls through in IE8
							 | 
						|
								    case 'text':
							 | 
						|
								      try {
							 | 
						|
								        // This will fail when readyState = 3 in IE9. Switch mode and wait for readyState = 4
							 | 
						|
								        response = xhr.responseText;
							 | 
						|
								      } catch (e) {
							 | 
						|
								        self._mode = 'text:vbarray';
							 | 
						|
								        break;
							 | 
						|
								      }
							 | 
						|
								      if (response.length > self._pos) {
							 | 
						|
								        var newData = response.substr(self._pos);
							 | 
						|
								        if (self._charset === 'x-user-defined') {
							 | 
						|
								          var buffer = new Buffer(newData.length);
							 | 
						|
								          for (var i = 0; i < newData.length; i++) buffer[i] = newData.charCodeAt(i) & 0xff;
							 | 
						|
								
							 | 
						|
								          self.push(buffer);
							 | 
						|
								        } else {
							 | 
						|
								          self.push(newData, self._charset);
							 | 
						|
								        }
							 | 
						|
								        self._pos = response.length;
							 | 
						|
								      }
							 | 
						|
								      break;
							 | 
						|
								    case 'arraybuffer':
							 | 
						|
								      if (xhr.readyState !== rStates.DONE || !xhr.response) break;
							 | 
						|
								      response = xhr.response;
							 | 
						|
								      self.push(new Buffer(new Uint8Array(response)));
							 | 
						|
								      break;
							 | 
						|
								    case 'moz-chunked-arraybuffer': // take whole
							 | 
						|
								      response = xhr.response;
							 | 
						|
								      if (xhr.readyState !== rStates.LOADING || !response) break;
							 | 
						|
								      self.push(new Buffer(new Uint8Array(response)));
							 | 
						|
								      break;
							 | 
						|
								    case 'ms-stream':
							 | 
						|
								      response = xhr.response;
							 | 
						|
								      if (xhr.readyState !== rStates.LOADING) break;
							 | 
						|
								      var reader = new global.MSStreamReader();
							 | 
						|
								      reader.onprogress = function () {
							 | 
						|
								        if (reader.result.byteLength > self._pos) {
							 | 
						|
								          self.push(new Buffer(new Uint8Array(reader.result.slice(self._pos))));
							 | 
						|
								          self._pos = reader.result.byteLength;
							 | 
						|
								        }
							 | 
						|
								      };
							 | 
						|
								      reader.onload = function () {
							 | 
						|
								        self.push(null);
							 | 
						|
								      };
							 | 
						|
								      // reader.onerror = ??? // TODO: this
							 | 
						|
								      reader.readAsArrayBuffer(response);
							 | 
						|
								      break;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  // The ms-stream case handles end separately in reader.onload()
							 | 
						|
								  if (self._xhr.readyState === rStates.DONE && self._mode !== 'ms-stream') {
							 | 
						|
								    self.push(null);
							 | 
						|
								  }
							 | 
						|
								};
							 |