Search code examples
node.jsherokusails.jssails-skipper

Sails Body Parser Configuration


I have an application hosted on Heroku that sends a huge amount of JSON. I originally was getting a bodyParser - request entity too large error (HTTP 400). Googling around, I came across a few stackoverflow/github issue links

(Sails.js bodyParser - request entity too large on version 0.10.5) (https://github.com/balderdashy/skipper/issues/144)

in which I tried updating my http.js. Now my body parser looks like this:

bodyParser: {
  fn: require('skipper'),
  options:{
    limit: '10mb'
  }
}

This resolved the 400 error, but now I am getting a Heroku H13 error:

2016-08-11T14:02:08.861774+00:00 heroku[router]: at=error code=H13 desc="Connection closed without response"

At this point, I am kind of stumped. I've looked at Heroku's documentation about an H13 error

(https://devcenter.heroku.com/articles/error-codes#h13-connection-closed-without-response),

but I am not sure if

  1. I need to configure more with Heroku (how I would even go about that) or
  2. Do more with Sails bodyParser configuration or
  3. A combination of the two

I am currently using version 0.11.2 of Sails.

[Update]

Researching more lead me to these links:

https://github.com/balderdashy/sails/issues/2653

https://github.com/balderdashy/skipper/issues/22

I noticed an individual had their bodyParser config outside the middleware block. I tried moving mine outside as well, and it seems to fix the 400 and 503 H13 Heroku issue I was receiving (and I slowly tip toed away from the issue). My new question is, why does the below work, especially since the bodyParser comment block is inside the middleware block?

module.exports.http = {
   /****************************************************************************
   *                                                                           *
   * Express middleware to use for every Sails request. To add custom          *
   * middleware to the mix, add a function to the middleware config object and *
   * add its key to the "order" array. The $custom key is reserved for         *
   * backwards-compatibility with Sails v0.9.x apps that use the               *
   * `customMiddleware` config option.                                         *
   *                                                                           *
   ****************************************************************************/

  middleware: {
    passportInit: require('passport').initialize(),
    passportSession: require('passport').session(),
    /***************************************************************************
     *                                                                          *
     * The order in which middleware should be run for HTTP request. (the Sails *
     * router is invoked by the "router" middleware below.)                     *
     *                                                                          *
     ***************************************************************************/

    order: [
      'startRequestTimer',
      'cookieParser',
      'session',
      'passportInit',
      'passportSession',
      'myRequestLogger',
      'bodyParser',
      'handleBodyParserError',
      'compress',
      'methodOverride',
      'poweredBy',
      '$custom',
      'router',
      'www',
      'favicon',
      '404',
      '500'
    ],
    /****************************************************************************
     *                                                                           *
     * Example custom middleware; logs each request to the console.              *
     *                                                                           *
     ****************************************************************************/

    // myRequestLogger: function (req, res, next) {
    //     console.log("Requested :: ", req.method, req.url);
    //     return next();
    // }


    /***************************************************************************
     *                                                                          *
     * The body parser that will handle incoming multipart HTTP requests. By    *
     * default as of v0.10, Sails uses                                          *
     * [skipper](http://github.com/balderdashy/skipper). See                    *
     * http://www.senchalabs.org/connect/multipart.html for other options.      *
     *                                                                          *
     ***************************************************************************/

    // bodyParser: require('skipper')

  },
  /***************************************************************************
   *                                                                          *
   * The number of seconds to cache flat files on disk being served by        *
   * Express static middleware (by default, these files are in `.tmp/public`) *
   *                                                                          *
   * The HTTP static cache is only active in a 'production' environment,      *
   * since that's the only time Express will cache flat-files.                *
   *                                                                          *
   ***************************************************************************/

  // cache: 31557600000

  bodyParser: function () {
    var opts = {limit:'10mb'};
    var fn;

    // Default to built-in bodyParser:
    fn = require('skipper');
    return fn(opts);

  }
};

Solution

  • You can put your middlewares inside and outside the middleware object. As the doc say, you put outside the middlewares that doesn't follow 'app.use(middleware)' convention.

    Since your bodyparser middleware return require('skipper')({limit:'10mb'}) and not require('skipper') which is very different, it doesn't follow the 'app.use(middleware)' convention and should be placed outside, at root of http module, as you did.