Request emitter doesn't emit 'end' in Express

I have situation where the request emitter does emit 'data' event but not the 'end' event. I am not sure how to troubleshoot. How would you?

var Review = require('../lib/review')
    , qs = require('querystring');

exports.processReview = function(req, res){
        var body = '';
        req.setEncoding('utf8');
        req.on('data', function(chunk){body += chunk});
        req.on('end', function(){
            console.log('got here: ' + body);
            var obj = qs.parse(body);
            var review = new Review({
                title: obj.param('title'),
                content: obj.param('content'),
                submittedBy: obj.param('submittedBy'),
                recommendedFor: obj.param('recommendedFor')
            });
            console.log('New Review: ' + JSON.stringify(review));
            res.end('Ok\n');
        });
        res.end('Ok\n');
        console.log('_________end______' + body);
    };

    exports.displayForm = function(req, res){
        var html = '<html><head><title>some head</title></head><body><h1>Review Form</h1>'
            + '<form method="post" action="/process/review" >'
            + '<p>Title: <input type="text" name="title" /></p>'
            + '<p>Content: <input type="text" name="content" /></p>'
            + '<p>Nickname: <input type="text" name="submittedBy" /></p>'
            + '<p>Recommended for: <input type="text" name="recommendedFor" /></p>'
            + '<p><input type="submit" value="Submit Review" /></p>'
            + '</form></body></html>';
        res.setHeader('Content-Type', 'text/html');
        res.setHeader('Content-Length', Buffer.byteLength(html));
        res.end(html);
    };

How would you go and troubleshoot this? and what is the problem? Thank You

If you are using express, and bodyParser or any similar middleware, then end will have already been emitted before it reaches your handler.

But like I said in the comment, if you're using express, you're also making things way too hard on yourself. You shouldn't need to worry about end in this situation. Let the middleware take care of parsing the body.

And by using res.send, you can let express take care of other common tasks as well. send is basically a wrapper around node's end. To name a few things, it:

  • accepts HTTP status, body, or both as arguments
  • converts objects to json responses
  • sets the content-length and other headers
  • calculates and sets etag
  • sends 304 for requests that hit a fresh cache
  • sends head responses for bodiless sends

Your handlers could be written something like:

var Review = require('../lib/review');

exports.processReview = function(req, res){
  // the bodyParser (if it is in fact already a middleware) will have parsed
  // the request body already into `req.body`
  var review = new Review({
    title: req.body.title,
    content: req.body.content,
    submittedBy: req.body.submittedBy,
    recommendedFor: req.body.recommendedFor
  });
  console.log('New Review: ' + JSON.stringify(review));
  // here you'd probably save your view before sending.
  res.send(200);
};

exports.displayForm = function(req, res){
  // here you could keep your html in a template (e.g. /views/form.html), then:
  // res.render("form");

  // but even without doing that, express handles setting the content-type
  // and body length, like so:
  var html = '<html><head><title>some head</title></head><body><h1>Review Form</h1>'
    + '<form method="post" action="/process/review" >'
    + '<p>Title: <input type="text" name="title" /></p>'
    + '<p>Content: <input type="text" name="content" /></p>'
    + '<p>Nickname: <input type="text" name="submittedBy" /></p>'
    + '<p>Recommended for: <input type="text" name="recommendedFor" /></p>'
    + '<p><input type="submit" value="Submit Review" /></p>'
    + '</form></body></html>';
  res.send(html);
};

In your processReview function, you are ending the response for every request.

    res.end('Ok\n'); // end response
    console.log('_________end______' + body);

The request is finished processing on res.end and no more events are listened/processed anymore. Since you execute res.end unconditionally it does not reach the event handler of end for the request.