Пример #1
0
  req.on('response', function(res){
    debug('%s %s -> %s', self.method, self.url, res.statusCode);
    var max = self._maxRedirects;
    var mime = utils.type(res.headers['content-type'] || '');
    var len = res.headers['content-length'];
    var type = mime.split('/');
    var subtype = type[1];
    var type = type[0];
    var multipart = 'multipart' == type;
    var redirect = isRedirect(res.statusCode);

    if (self.piped) {
      res.on('end', function(){
        self.emit('end');
      });
      return;
    }

    // redirect
    if (redirect && self._redirects++ != max) {
      return self.redirect(res);
    }

    // zlib support
    if (/^(deflate|gzip)$/.test(res.headers['content-encoding'])) {
      utils.unzip(req, res);
    }

    // don't buffer multipart
    if (multipart) buffer = false;

    // TODO: make all parsers take callbacks
    if (multipart) {
      var form = new formidable.IncomingForm;

      form.parse(res, function(err, fields, files){
        if (err) return self.callback(err);
        var response = new Response(req, res);
        response.body = fields;
        response.files = files;
        response.redirects = self._redirectList;
        self.emit('end');
        self.callback(null, response);
      });
      return;
    }

    // by default only buffer text/*, json
    // and messed up thing from hell
    var text = isText(mime);
    if (null == buffer && text) buffer = true;

    // parser
    var parse = 'text' == type
      ? exports.parse.text
      : exports.parse[mime];

    // buffered response
    if (buffer) parse = parse || exports.parse.text;

    // explicit parser
    if (self._parser) parse = self._parser;

    // parse
    if (parse) {
      parse(res, function(err, obj){
        // TODO: handle error
        res.body = obj;
      });
    }

    // unbuffered
    if (!buffer) {
      debug('unbuffered %s %s', self.method, self.url);
      self.res = res;
      var response = new Response(self.req, self.res);
      response.redirects = self._redirectList;
      self.emit('response', response);
      if (multipart) return // allow multipart to handle end event
      res.on('end', function(){
        debug('end %s %s', self.method, self.url);
        self.emit('end');
      })
      return;
    }

    // end event
    self.res = res;
    res.on('end', function(){
      debug('end %s %s', self.method, self.url);
      // TODO: unless buffering emit earlier to stream
      var response = new Response(self.req, self.res);
      response.redirects = self._redirectList;
      self.emit('response', response);
      self.emit('end');
    });
  });
Пример #2
0
  req.on('response', function(res){
    debug('%s %s -> %s', self.method, self.url, res.statusCode);
    var max = self._maxRedirects;
    var mime = utils.type(res.headers['content-type'] || '') || 'text/plain';
    var len = res.headers['content-length'];
    var type = mime.split('/');
    var subtype = type[1];
    var type = type[0];
    var multipart = 'multipart' == type;
    var redirect = isRedirect(res.statusCode);
    var parser = self._parser;

    self.res = res;

    if ('HEAD' == self.method) {
      var response = new Response(self);
      self.response = response;
      response.redirects = self._redirectList;
      self.emit('response', response);
      self.callback(null, response);
      self.emit('end');
      return;
    }

    if (self.piped) {
      return;
    }

    // redirect
    if (redirect && self._redirects++ != max) {
      return self._redirect(res);
    }

    // zlib support
    if (/^(deflate|gzip)$/.test(res.headers['content-encoding'])) {
      utils.unzip(req, res);
    }

    // don't buffer multipart
    if (multipart) buffer = false;

    // TODO: make all parsers take callbacks
    if (!parser && multipart) {
      var form = new formidable.IncomingForm;

      form.parse(res, function(err, fields, files){
        if (err) return self.callback(err);
        var response = new Response(self);
        self.response = response;
        response.body = fields;
        response.files = files;
        response.redirects = self._redirectList;
        self.emit('end');
        self.callback(null, response);
      });
      return;
    }

    // check for images, one more special treatment
    if (!parser && isImage(mime)) {
      exports.parse.image(res, function(err, obj){
        if (err) return self.callback(err);
        var response = new Response(self);
        self.response = response;
        response.body = obj;
        response.redirects = self._redirectList;
        self.emit('end');
        self.callback(null, response);
      });
      return;
    }

    // by default only buffer text/*, json and messed up thing from hell
    if (null == buffer && isText(mime) || isJSON(mime)) buffer = true;

    // parser
    var parse = 'text' == type
      ? exports.parse.text
      : exports.parse[mime];

    // everyone wants their own white-labeled json
    if (!parse && isJSON(mime)) parse = exports.parse['application/json'];

    // buffered response
    if (buffer) parse = parse || exports.parse.text;

    // explicit parser
    if (parser) parse = parser;

    // parse
    if (parse) {
      try {
        parse(res, function(err, obj){
          if (err && !self._aborted) self.callback(err);
          res.body = obj;
        });
      } catch (err) {
        self.callback(err);
        return;
      }
    }

    // unbuffered
    if (!buffer) {
      debug('unbuffered %s %s', self.method, self.url);
      self.res = res;
      var response = new Response(self);
      self.response = response;
      response.redirects = self._redirectList;
      self.emit('response', response);
      self.callback(null, response);
      if (multipart) return // allow multipart to handle end event
      res.on('end', function(){
        debug('end %s %s', self.method, self.url);
        self.emit('end');
      })
      return;
    }

    // terminating events
    self.res = res;
    res.on('error', function(err){
      self.callback(err, null);
    });
    res.on('end', function(){
      debug('end %s %s', self.method, self.url);
      // TODO: unless buffering emit earlier to stream
      var response = new Response(self);
      self.response = response;
      response.redirects = self._redirectList;
      self.emit('response', response);
      self.callback(null, response);
      self.emit('end');
    });
  });
Пример #3
0
  req.once('response', res => {
    debug('%s %s -> %s', this.method, this.url, res.statusCode);

    if (this._responseTimeoutTimer) {
      clearTimeout(this._responseTimeoutTimer);
    }

    if (this.piped) {
      return;
    }

    const max = this._maxRedirects;
    const mime = utils.type(res.headers['content-type'] || '') || 'text/plain';
    const type = mime.split('/')[0];
    const multipart = 'multipart' == type;
    const redirect = isRedirect(res.statusCode);
    const responseType = this._responseType;

    this.res = res;

    // redirect
    if (redirect && this._redirects++ != max) {
      return this._redirect(res);
    }

    if ('HEAD' == this.method) {
      this.emit('end');
      this.callback(null, this._emitResponse());
      return;
    }

    // zlib support
    if (this._shouldUnzip(res)) {
      unzip(req, res);
    }

    let buffer = this._buffer;
    if (buffer === undefined && mime in exports.buffer){
      buffer = !!exports.buffer[mime];
    }

    let parser = this._parser;
    if (undefined === buffer) {
      if (parser) {
        console.warn("A custom superagent parser has been set, but buffering strategy for the parser hasn't been configured. Call `req.buffer(true or false)` or set `superagent.buffer[mime] = true or false`");
        buffer = true;
      }
    }

    if (!parser) {
      if (responseType) {
        parser = exports.parse.image; // It's actually a generic Buffer
        buffer = true;
      } else if (multipart) {
        const form = new formidable.IncomingForm();
        parser = form.parse.bind(form);
        buffer = true;
      } else if (isImageOrVideo(mime)) {
        parser = exports.parse.image;
        buffer = true; // For backwards-compatibility buffering default is ad-hoc MIME-dependent
      } else if (exports.parse[mime]) {
        parser = exports.parse[mime];
      } else if ('text' == type) {
        parser = exports.parse.text;
        buffer = (buffer !== false);

        // everyone wants their own white-labeled json
      } else if (isJSON(mime)) {
        parser = exports.parse['application/json'];
        buffer = (buffer !== false);
      } else if (buffer) {
        parser = exports.parse.text;
      } else if (undefined === buffer) {
        parser = exports.parse.image; // It's actually a generic Buffer
        buffer = true;
      }
    }

    // by default only buffer text/*, json and messed up thing from hell
    if ((undefined === buffer && isText(mime)) || isJSON(mime)) {
      buffer = true;
    }

    this._resBuffered = buffer;
    let parserHandlesEnd = false;
    if (buffer) {
      // Protectiona against zip bombs and other nuisance
      let responseBytesLeft = this._maxResponseSize || 200000000;
      res.on('data', buf => {
        responseBytesLeft -= buf.byteLength || buf.length;
        if (responseBytesLeft < 0) {
          // This will propagate through error event
          const err = Error("Maximum response size reached");
          err.code = "ETOOLARGE";
          // Parsers aren't required to observe error event,
          // so would incorrectly report success
          parserHandlesEnd = false;
          // Will emit error event
          res.destroy(err);
        }
      });
    }

    if (parser) {
      try {
        // Unbuffered parsers are supposed to emit response early,
        // which is weird BTW, because response.body won't be there.
        parserHandlesEnd = buffer;

        parser(res, (err, obj, files) => {
          if (this.timedout) {
            // Timeout has already handled all callbacks
            return;
          }

          // Intentional (non-timeout) abort is supposed to preserve partial response,
          // even if it doesn't parse.
          if (err && !this._aborted) {
            return this.callback(err);
          }

          if (parserHandlesEnd) {
            this.emit('end');
            this.callback(null, this._emitResponse(obj, files));
          }
        });
      } catch (err) {
        this.callback(err);
        return;
      }
    }

    this.res = res;

    // unbuffered
    if (!buffer) {
      debug('unbuffered %s %s', this.method, this.url);
      this.callback(null, this._emitResponse());
      if (multipart) return; // allow multipart to handle end event
      res.once('end', () => {
        debug('end %s %s', this.method, this.url);
        this.emit('end');
      });
      return;
    }

    // terminating events
    res.once('error', err => {
      parserHandlesEnd = false;
      this.callback(err, null);
    });
    if (!parserHandlesEnd)
      res.once('end', () => {
        debug('end %s %s', this.method, this.url);
        // TODO: unless buffering emit earlier to stream
        this.emit('end');
        this.callback(null, this._emitResponse());
      });
  });
Пример #4
0
  req.once('response', function(res){
    debug('%s %s -> %s', self.method, self.url, res.statusCode);

    if (self._responseTimeoutTimer) {
      clearTimeout(self._responseTimeoutTimer);
    }

    if (self.piped) {
      return;
    }

    var max = self._maxRedirects;
    var mime = utils.type(res.headers['content-type'] || '') || 'text/plain';
    var type = mime.split('/')[0];
    var multipart = 'multipart' == type;
    var redirect = isRedirect(res.statusCode);
    var parser = self._parser;
    var responseType = self._responseType;

    self.res = res;

    // redirect
    if (redirect && self._redirects++ != max) {
      return self._redirect(res);
    }

    if ('HEAD' == self.method) {
      self.emit('end');
      self.callback(null, self._emitResponse());
      return;
    }

    // zlib support
    if (self._shouldUnzip(res)) {
      unzip(req, res);
    }

    if (!parser) {
      if (responseType) {
        parser = exports.parse.image; // It's actually a generic Buffer
        buffer = true;
      } else if (multipart) {
        var form = new formidable.IncomingForm();
        parser = form.parse.bind(form);
        buffer = true;
      } else if (isImageOrVideo(mime)) {
        parser = exports.parse.image;
        buffer = true; // For backwards-compatibility buffering default is ad-hoc MIME-dependent
      } else if (exports.parse[mime]) {
        parser = exports.parse[mime];
      } else if ('text' == type) {
        parser = exports.parse.text;
        buffer = (buffer !== false);

        // everyone wants their own white-labeled json
      } else if (isJSON(mime)) {
        parser = exports.parse['application/json'];
        buffer = (buffer !== false);
      } else if (buffer) {
        parser = exports.parse.text;
      }
    }

    // by default only buffer text/*, json and messed up thing from hell
    if (undefined === buffer && isText(mime) || isJSON(mime)) {
      buffer = true;
    }

    var parserHandlesEnd = false;
    if (parser) {
      try {
        // Unbuffered parsers are supposed to emit response early,
        // which is weird BTW, because response.body won't be there.
        parserHandlesEnd = buffer;

        parser(res, function(err, obj, files) {
          if (self.timedout) {
            // Timeout has already handled all callbacks
            return;
          }

          // Intentional (non-timeout) abort is supposed to preserve partial response,
          // even if it doesn't parse.
          if (err && !self._aborted) {
            return self.callback(err);
          }

          if (parserHandlesEnd) {
            self.emit('end');
            self.callback(null, self._emitResponse(obj, files));
          }
        });
      } catch (err) {
        self.callback(err);
        return;
      }
    }

    self.res = res;

    // unbuffered
    if (!buffer) {
      debug('unbuffered %s %s', self.method, self.url);
      self.callback(null, self._emitResponse());
      if (multipart) return // allow multipart to handle end event
      res.once('end', function(){
        debug('end %s %s', self.method, self.url);
        self.emit('end');
      })
      return;
    }

    // terminating events
    res.once('error', function(err){
      self.callback(err, null);
    });
    if (!parserHandlesEnd) res.once('end', function(){
      debug('end %s %s', self.method, self.url);
      // TODO: unless buffering emit earlier to stream
      self.emit('end');
      self.callback(null, self._emitResponse());
    });
  });
Пример #5
0
 req.on('response', function(res) {
   debug('%s %s -> %s', self.method, self.url, res.statusCode);
   var max = self._maxRedirects;
   var mime = utils.type(res.headers['content-type'] || '') || 'text/plain';
   var len = res.headers['content-length'];
   var type = mime.split('/');
   var subtype = type[1];
   var type = type[0];
   var multipart = 'multipart' == type;
   var redirect = isRedirect(res.statusCode);
   var parser = self._parser;
   self.res = res;
   if ('HEAD' == self.method) {
     var response = new Response(self);
     self.response = response;
     response.redirects = self._redirectList;
     self.emit('response', response);
     self.callback(null, response);
     self.emit('end');
     return;
   }
   if (self.piped) {
     return;
   }
   if (redirect && self._redirects++ != max) {
     return self.redirect(res);
   }
   if (/^(deflate|gzip)$/.test(res.headers['content-encoding'])) {
     utils.unzip(req, res);
   }
   if (multipart)
     buffer = false;
   if (!parser && multipart) {
     var form = new formidable.IncomingForm;
     form.parse(res, function(err, fields, files) {
       if (err)
         return self.callback(err);
       var response = new Response(self);
       self.response = response;
       response.body = fields;
       response.files = files;
       response.redirects = self._redirectList;
       self.emit('end');
       self.callback(null, response);
     });
     return;
   }
   if (!parser && isImage(mime)) {
     exports.parse.image(res, function(err, obj) {
       if (err)
         return self.callback(err);
       var response = new Response(self);
       self.response = response;
       response.body = obj;
       response.redirects = self._redirectList;
       self.emit('end');
       self.callback(null, response);
     });
     return;
   }
   if (null == buffer && isText(mime) || isJSON(mime))
     buffer = true;
   var parse = 'text' == type ? exports.parse.text : exports.parse[mime];
   if (!parse && isJSON(mime))
     parse = exports.parse['application/json'];
   if (buffer)
     parse = parse || exports.parse.text;
   if (parser)
     parse = parser;
   if (parse) {
     try {
       parse(res, function(err, obj) {
         if (err && !self._aborted)
           self.callback(err);
         res.body = obj;
       });
     } catch (err) {
       self.callback(err);
       return;
     }
   }
   if (!buffer) {
     debug('unbuffered %s %s', self.method, self.url);
     self.res = res;
     var response = new Response(self);
     self.response = response;
     response.redirects = self._redirectList;
     self.emit('response', response);
     self.callback(null, response);
     if (multipart)
       return;
     res.on('end', function() {
       debug('end %s %s', self.method, self.url);
       self.emit('end');
     });
     return;
   }
   self.res = res;
   res.on('error', function(err) {
     self.callback(err, null);
   });
   res.on('end', function() {
     debug('end %s %s', self.method, self.url);
     var response = new Response(self);
     self.response = response;
     response.redirects = self._redirectList;
     self.emit('response', response);
     self.callback(null, response);
     self.emit('end');
   });
 });