Lahiru Chandima
Lahiru Chandima

Reputation: 24068

HTTP connection gets prematurely terminated in nodejs app hosted on Amazon EC2

I have a REST api hosted on Amazon EC2, which is written with Nodejs (Express).

In a particular REST call, a reply of about 5MB is sent to the client. Before the client completely receives the reply, client prints following error message.

Premature end of Content-Length delimited message body

I added a connection listener in nodejs server like below to check what is going on the server.

var app = express();

var server = http.createServer(app);
var port = app.get('port');
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
server.on('connection', function (socket) {
    log.debug('SOCKET OPENED' + JSON.stringify(socket.address()));
    socket.setTimeout(300000);   //5 minute timeout
    socket.on('end', function () {
        log.debug('SOCKET END: other end of the socket sends a FIN packet');
    });

    socket.on('timeout', function () {
        log.warn('SOCKET TIMEOUT');
    });

    socket.on('error', function (error) {
        log.warn('SOCKET ERROR: ' + JSON.stringify(error));
    });

    socket.on('close', function (had_error) {
        log.debug('SOCKET CLOSED. IT WAS ERROR: ' + had_error);
    });
});

I observed that SOCKET TIMEOUT gets logged in backend. In above code, I have increased the socket timeout to 5 minutes, but it doesn't seem to have any effect.

Earlier I had the REST API hosted in Google compute engine, and I didn't have this problem back then.

What could be the problem here?

Edit: Here is the code of REST API call.

I have following code in my app.js

require('./routes/index')(app);

Following is the index.js of routes directory.

var changeCase = require('change-case');
var express = require('express');
var routes = require('require-dir')();

module.exports = function (app) {
    Object.keys(routes).forEach(function (routeName) {
        var router = express.Router();
        require('./' + routeName)(router);
        app.use('/api/' + changeCase.paramCase(routeName), router);
    });
};

As it can be seen, it loops through all the js files in the routes directory and registers the file name as the URL path in app.

Here is the code of this particular route for which I face this problem.

   module.exports = function (router) {   
       router.get("/fetch", function (req, res, next) {
            itemModel.fetch(req.user.clientId, function (error, items) {
                if (error) {
                    res.status(500).json({error: error});
                } else {
                    res.json(items);    //items is a JSON array
                }
            });
        });
    }

Upvotes: 0

Views: 588

Answers (1)

Lahiru Chandima
Lahiru Chandima

Reputation: 24068

Setting timeout for the HTTP server resolved the issue.

var server = http.createServer(app);
var port = app.get('port');
server.listen(port);
server.setTimeout(300000, function (socket) {
});

Upvotes: 1

Related Questions