text: 
  /**
   * Module dependencies.
   */
  
  var Emitter = require('emitter');
  
  /**
   * Root reference for iframes.
   */
  
  var root = 'undefined' == typeof window
    ? this
    : window;
  
  /**
   * Noop.
   */
  
  function noop(){};
  
  /**
   * Determine XHR.
   */
  
  function getXHR() {
    if (root.XMLHttpRequest
      && ('file:' != root.location.protocol || !root.ActiveXObject)) {
      return new XMLHttpRequest;
    } else {
      try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}
      try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}
      try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}
      try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}
    }
    return false;
  }
  
  /**
   * Removes leading and trailing whitespace, added to support IE.
   *
   * @param {String} s
   * @return {String}
   * @api private
   */
  
  var trim = ''.trim
    ? function(s) { return s.trim(); }
    : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); };
  
  /**
   * Check if `obj` is an object.
   *
   * @param {Object} obj
   * @return {Boolean}
   * @api private
   */
  
  function isObject(obj) {
    return obj === Object(obj);
  }
  
  /**
   * Serialize the given `obj`.
   *
   * @param {Object} obj
   * @return {String}
   * @api private
   */
  
  function serialize(obj) {
    if (!isObject(obj)) return obj;
    var pairs = [];
    for (var key in obj) {
      pairs.push(encodeURIComponent(key)
        + '=' + encodeURIComponent(obj[key]));
    }
    return pairs.join('&');
  }
  
  /**
   * Expose serialization method.
   */
  
   request.serializeObject = serialize;
  
   /**
    * Parse the given x-www-form-urlencoded `str`.
    *
    * @param {String} str
    * @return {Object}
    * @api private
    */
  
  function parseString(str) {
    var obj = {};
    var pairs = str.split('&');
    var parts;
    var pair;
  
    for (var i = 0, len = pairs.length; i < len; ++i) {
      pair = pairs[i];
      parts = pair.split('=');
      obj[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
    }
  
    return obj;
  }
  
  /**
   * Expose parser.
   */
  
  request.parseString = parseString;
  
  /**
   * Default MIME type map.
   *
   *     superagent.types.xml = 'application/xml';
   *
   */
  
  request.types = {
    html: 'text/html',
    json: 'application/json',
    urlencoded: 'application/x-www-form-urlencoded',
    'form': 'application/x-www-form-urlencoded',
    'form-data': 'application/x-www-form-urlencoded'
  };
  
  /**
   * Default serialization map.
   *
   *     superagent.serialize['application/xml'] = function(obj){
   *       return 'generated xml here';
   *     };
   *
   */
  
   request.serialize = {
     'application/x-www-form-urlencoded': serialize,
     'application/json': JSON.stringify
   };
  
   /**
    * Default parsers.
    *
    *     superagent.parse['application/xml'] = function(str){
    *       return { object parsed from str };
    *     };
    *
    */
  
  request.parse = {
    'application/x-www-form-urlencoded': parseString,
    'application/json': JSON.parse
  };
  
  /**
   * Parse the given header `str` into
   * an object containing the mapped fields.
   *
   * @param {String} str
   * @return {Object}
   * @api private
   */
  
  function parseHeader(str) {
    var lines = str.split(/\r?\n/);
    var fields = {};
    var index;
    var line;
    var field;
    var val;
  
    lines.pop(); // trailing CRLF
  
    for (var i = 0, len = lines.length; i < len; ++i) {
      line = lines[i];
      index = line.indexOf(':');
      field = line.slice(0, index).toLowerCase();
      val = trim(line.slice(index + 1));
      fields[field] = val;
    }
  
    return fields;
  }
  
  /**
   * Return the mime type for the given `str`.
   *
   * @param {String} str
   * @return {String}
   * @api private
   */
  
  function type(str){
    return str.split(/ *; */).shift();
  };
  
  /**
   * Return header field parameters.
   *
   * @param {String} str
   * @return {Object}
   * @api private
   */
  
  function params(str){
    return str.split(/ *; */).reduce(function(obj, str){
      var parts = str.split(/ *= */)
        , key = parts.shift()
        , val = parts.shift();
  
      if (key && val) obj[key] = val;
      return obj;
    }, {});
  };
  
  /**
   * Initialize a new `Response` with the given `xhr`.
   *
   *  - set flags (.ok, .error, etc)
   *  - parse header
   *
   * Examples:
   *
   *  Aliasing `superagent` as `request` is nice:
   *
   *      request = superagent;
   *
   *  We can use the promise-like API, or pass callbacks:
   *
   *      request.get('/').end(function(res){});
   *      request.get('/', function(res){});
   *
   *  Sending data can be chained:
   *
   *      request
   *        .post('/user')
   *        .send({ name: 'tj' })
   *        .end(function(res){});
   *
   *  Or passed to `.send()`:
   *
   *      request
   *        .post('/user')
   *        .send({ name: 'tj' }, function(res){});
   *
   *  Or passed to `.post()`:
   *
   *      request
   *        .post('/user', { name: 'tj' })
   *        .end(function(res){});
   *
   * Or further reduced to a single call for simple cases:
   *
   *      request
   *        .post('/user', { name: 'tj' }, function(res){});
   *
   * @param {XMLHTTPRequest} xhr
   * @param {Object} options
   * @api private
   */
  
  function Response(xhr, options) {
    options = options || {};
    this.xhr = xhr;
    this.text = xhr.responseText;
    this.setStatusProperties(xhr.status);
    this.header = parseHeader(xhr.getAllResponseHeaders());
    this.setHeaderProperties(this.header);
    this.body = this.parseBody(this.text);
  }
  
  /**
   * Set header related properties:
   *
   *   - `.type` the content type without params
   *
   * A response of "Content-Type: text/plain; charset=utf-8"
   * will provide you with a `.type` of "text/plain".
   *
   * @param {Object} header
   * @api private
   */
  
  Response.prototype.setHeaderProperties = function(header){
    // content-type
    var ct = this.header['content-type'] || '';
    this.type = type(ct);
  
    // params
    var obj = params(ct);
    for (var key in obj) this[key] = obj[key];
  };
  
  /**
   * Parse the given body `str`.
   *
   * Used for auto-parsing of bodies. Parsers
   * are defined on the `superagent.parse` object.
   *
   * @param {String} str
   * @return {Mixed}
   * @api private
   */
  
  Response.prototype.parseBody = function(str){
    var parse = request.parse[this.type];
    return parse
      ? parse(str)
      : null;
  };
  
  /**
   * Set flags such as `.ok` based on `status`.
   *
   * For example a 2xx response will give you a `.ok` of __true__
   * whereas 5xx will be __false__ and `.error` will be __true__. The
   * `.clientError` and `.serverError` are also available to be more
   * specific, and `.statusType` is the class of error ranging from 1..5
   * sometimes useful for mapping respond colors etc.
   *
   * "sugar" properties are also defined for common cases. Currently providing:
   *
   *   - .noContent
   *   - .badRequest
   *   - .unauthorized
   *   - .notAcceptable
   *   - .notFound
   *
   * @param {Number} status
   * @api private
   */
  
  Response.prototype.setStatusProperties = function(status){
    var type = status / 100 | 0;
  
    // status / class
    this.status = status;
    this.statusType = type;
  
    // basics
    this.info = 1 == type;
    this.ok = 2 == type;
    this.clientError = 4 == type;
    this.serverError = 5 == type;
    this.error = 4 == type || 5 == type;
  
    // sugar
    this.accepted = 202 == status;
    this.noContent = 204 == status || 1223 == status;
    this.badRequest = 400 == status;
    this.unauthorized = 401 == status;
    this.notAcceptable = 406 == status;
    this.notFound = 404 == status;
    this.forbidden = 403 == status;
  };
  
  /**
   * Return an `Error` representative of this response.
   *
   * @return {Error}
   * @api public
   */
  
  Response.prototype.toError = function(){
    var msg = 'got ' + this.status + ' response';
    var err = new Error(msg);
    err.status = this.status;
    return err;
  };
  
  /**
   * Expose `Response`.
   */
  
  request.Response = Response;
  
  /**
   * Initialize a new `Request` with the given `method` and `url`.
   *
   * @param {String} method
   * @param {String} url
   * @api public
   */
  
  function Request(method, url) {
    var self = this;
    Emitter.call(this);
    this._query = this._query || [];
    this.method = method;
    this.url = url;
    this.header = {};
    this.set('X-Requested-With', 'XMLHttpRequest');
    this.on('end', function(){
      self.callback(null, new Response(self.xhr));
    });
  }
  
  /**
   * Inherit from `Emitter.prototype`.
   */
  
  Request.prototype = new Emitter;
  Request.prototype.constructor = Request;
  
  /**
   * Set timeout to `ms`.
   *
   * @param {Number} ms
   * @return {Request} for chaining
   * @api public
   */
  
  Request.prototype.timeout = function(ms){
    this._timeout = ms;
    return this;
  };
  
  /**
   * Clear previous timeout.
   *
   * @return {Request} for chaining
   * @api public
   */
  
  Request.prototype.clearTimeout = function(){
    this._timeout = 0;
    clearTimeout(this._timer);
    return this;
  };
  
  /**
   * Abort the request, and clear potential timeout.
   *
   * @return {Request}
   * @api public
   */
  
  Request.prototype.abort = function(){
    if (this.aborted) return;
    this.xhr.abort();
    this.emit('abort');
    this.aborted = true;
    this.clearTimeout();
    return this;
  };
  
  /**
   * Set header `field` to `val`, or multiple fields with one object.
   *
   * Examples:
   *
   *      req.get('/')
   *        .set('Accept', 'application/json')
   *        .set('X-API-Key', 'foobar')
   *        .end(callback);
   *
   *      req.get('/')
   *        .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
   *        .end(callback);
   *
   * @param {String|Object} field
   * @param {String} val
   * @return {Request} for chaining
   * @api public
   */
  
  Request.prototype.set = function(field, val){
    if (isObject(field)) {
      for (var key in field) {
        this.set(key, field[key]);
      }
      return this;
    }
    this.header[field.toLowerCase()] = val;
    return this;
  };
  
  /**
   * Set Content-Type to `type`, mapping values from `request.types`.
   *
   * Examples:
   *
   *      superagent.types.xml = 'application/xml';
   *
   *      request.post('/')
   *        .type('xml')
   *        .send(xmlstring)
   *        .end(callback);
   *
   *      request.post('/')
   *        .type('application/xml')
   *        .send(xmlstring)
   *        .end(callback);
   *
   * @param {String} type
   * @return {Request} for chaining
   * @api public
   */
  
  Request.prototype.type = function(type){
    this.set('Content-Type', request.types[type] || type);
    return this;
  };
  
  /**
  * Add query-string `val`.
  *
  * Examples:
  *
  *   request.get('/shoes')
  *     .query('size=10')
  *     .query({ color: 'blue' })
  *
  * @param {Object|String} val
  * @return {Request} for chaining
  * @api public
  */
  
  Request.prototype.query = function(val){
    if ('string' != typeof val) val = serialize(val);
    this._query.push(val);
    return this;
  };
  
  /**
   * Send `data`, defaulting the `.type()` to "json" when
   * an object is given.
   *
   * Examples:
   *
   *       // querystring
   *       request.get('/search')
   *         .end(callback)
   *
   *       // multiple data "writes"
   *       request.get('/search')
   *         .send({ search: 'query' })
   *         .send({ range: '1..5' })
   *         .send({ order: 'desc' })
   *         .end(callback)
   *
   *       // manual json
   *       request.post('/user')
   *         .type('json')
   *         .send('{"name":"tj"})
   *         .end(callback)
   *
   *       // auto json
   *       request.post('/user')
   *         .send({ name: 'tj' })
   *         .end(callback)
   *
   *       // manual x-www-form-urlencoded
   *       request.post('/user')
   *         .type('form')
   *         .send('name=tj')
   *         .end(callback)
   *
   *       // auto x-www-form-urlencoded
   *       request.post('/user')
   *         .type('form')
   *         .send({ name: 'tj' })
   *         .end(callback)
   *
   *       // defaults to x-www-form-urlencoded
    *      request.post('/user')
    *        .send('name=tobi')
    *        .send('species=ferret')
    *        .end(callback)
   *
   * @param {String|Object} data
   * @return {Request} for chaining
   * @api public
   */
  
  Request.prototype.send = function(data){
    var obj = isObject(data);
    var type = this.header['content-type'];
  
    // merge
    if (obj && isObject(this._data)) {
      for (var key in data) {
        this._data[key] = data[key];
      }
    } else if ('string' == typeof data) {
      if (!type) this.type('form');
      type = this.header['content-type'];
      if ('application/x-www-form-urlencoded' == type) {
        this._data = this._data
          ? this._data + '&' + data
          : data;
      } else {
        this._data = (this._data || '') + data;
      }
    } else {
      this._data = data;
    }
  
    if (!obj) return this;
    if (!type) this.type('json');
    return this;
  };
  
  /**
   * Invoke the callback with `err` and `res`
   * and handle arity check.
   *
   * @param {Error} err
   * @param {Response} res
   * @api private
   */
  
  Request.prototype.callback = function(err, res){
    var fn = this._callback;
    if (2 == fn.length) return fn(err, res);
    if (err) return this.emit('error', err);
    fn(res);
  };
  
  /**
   * Initiate request, invoking callback `fn(res)`
   * with an instanceof `Response`.
   *
   * @param {Function} fn
   * @return {Request} for chaining
   * @api public
   */
  
  Request.prototype.end = function(fn){
    var self = this;
    var xhr = this.xhr = getXHR();
    var query = this._query.join('&');
    var timeout = this._timeout;
    var data = this._data;
  
    // store callback
    this._callback = fn || noop;
  
    // state change
    xhr.onreadystatechange = function(){
      if (4 == xhr.readyState && 0 != xhr.status) self.emit('end');
    };
  
    // timeout
    if (timeout && !this._timer) {
      this._timer = setTimeout(function(){
        var err = new Error('timeout of ' + timeout + 'ms exceeded');
        err.timeout = timeout;
        self.callback(err);
        self.abort();
      }, timeout);
    }
  
    // querystring
    if (query) {
      query = request.serializeObject(query);
      this.url += ~this.url.indexOf('?')
        ? '&' + query
        : '?' + query;
    }
  
    // initiate request
    xhr.open(this.method, this.url, true);
  
    // body
    if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data) {
      // serialize stuff
      var serialize = request.serialize[this.header['content-type']];
      if (serialize) data = serialize(data);
    }
  
    // set header fields
    for (var field in this.header) {
      xhr.setRequestHeader(field, this.header[field]);
    }
  
    // send stuff
    xhr.send(data);
    return this;
  };
  
  /**
   * Expose `Request`.
   */
  
  request.Request = Request;
  
  /**
   * Issue a request:
   *
   * Examples:
   *
   *    request('GET', '/users').end(callback)
   *    request('/users').end(callback)
   *    request('/users', callback)
   *
   * @param {String} method
   * @param {String|Function} url or callback
   * @return {Request}
   * @api public
   */
  
  function request(method, url) {
    // callback
    if ('function' == typeof url) {
      return new Request('GET', method).end(url);
    }
  
    // url first
    if (1 == arguments.length) {
      return new Request('GET', method);
    }
  
    return new Request(method, url);
  }
  
  /**
   * GET `url` with optional callback `fn(res)`.
   *
   * @param {String} url
   * @param {Mixed|Function} data or fn
   * @param {Function} fn
   * @return {Request}
   * @api public
   */
  
  request.get = function(url, data, fn){
    var req = request('GET', url);
    if ('function' == typeof data) fn = data, data = null;
    if (data) req.query(data);
    if (fn) req.end(fn);
    return req;
  };
  
  /**
   * GET `url` with optional callback `fn(res)`.
   *
   * @param {String} url
   * @param {Mixed|Function} data or fn
   * @param {Function} fn
   * @return {Request}
   * @api public
   */
  
  request.head = function(url, data, fn){
    var req = request('HEAD', url);
    if ('function' == typeof data) fn = data, data = null;
    if (data) req.send(data);
    if (fn) req.end(fn);
    return req;
  };
  
  /**
   * DELETE `url` with optional callback `fn(res)`.
   *
   * @param {String} url
   * @param {Function} fn
   * @return {Request}
   * @api public
   */
  
  request.del = function(url, fn){
    var req = request('DELETE', url);
    if (fn) req.end(fn);
    return req;
  };
  
  /**
   * PATCH `url` with optional `data` and callback `fn(res)`.
   *
   * @param {String} url
   * @param {Mixed} data
   * @param {Function} fn
   * @return {Request}
   * @api public
   */
  
  request.patch = function(url, data, fn){
    var req = request('PATCH', url);
    if ('function' == typeof data) fn = data, data = null;
    if (data) req.send(data);
    if (fn) req.end(fn);
    return req;
  };
  
  /**
   * POST `url` with optional `data` and callback `fn(res)`.
   *
   * @param {String} url
   * @param {Mixed} data
   * @param {Function} fn
   * @return {Request}
   * @api public
   */
  
  request.post = function(url, data, fn){
    var req = request('POST', url);
    if ('function' == typeof data) fn = data, data = null;
    if (data) req.send(data);
    if (fn) req.end(fn);
    return req;
  };
  
  /**
   * PUT `url` with optional `data` and callback `fn(res)`.
   *
   * @param {String} url
   * @param {Mixed|Function} data or fn
   * @param {Function} fn
   * @return {Request}
   * @api public
   */
  
  request.put = function(url, data, fn){
    var req = request('PUT', url);
    if ('function' == typeof data) fn = data, data = null;
    if (data) req.send(data);
    if (fn) req.end(fn);
    return req;
  };
  
  /**
   * Expose `request`.
   */
  
  module.exports = request;
  