Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why response is closed and not finished?

Tags:

node.js

I have the following code in node.js in a function readFile:

      res.setHeader("content-type", 'application/octet-stream');
      res.setHeader("Content-Disposition", 'attachment; filename="' + 'original' + '"' + "; filename*=UTF-8''" + 'original' + "");
      var readStream;
      var exists = fs.existsSync(fullPath);
           if (exists) {
                callback(true);
                readStream = fs.createReadStream(fullPath);
                readStream.pipe(res);
           } else {
                callback(false);
                return;
           }
              res.on('finish', function(){
                        logger.info('response ending');
                        readStream.close();
               })
              res.on('close', function(){
                        logger.info('response close');
                        readStream.close();
              })
              res.on('error', function(error){
                        logger.info(error);
                        readStream.close();
              })

For some reason, some requests are emitted the close event, while other the finish. As I understand, close is emitted when something get wrong.

The close event can fired between 2 sec and up to 2 min. In rare cases, no close and no finish events are emitted and all, and the request is "stuck", waiting for a response.

What can be the reason that some requests will success, and other not?

EDIT

How can I know why a close event has emitted? Is it a client issue or a bug in my application?

like image 596
Or Smith Avatar asked Jan 15 '15 08:01

Or Smith


3 Answers

if there is a finish then it is all normal, but if there is a close then it could be because of anything. I tried following code following to your event declarations, before the pipe was completed.

1. `res.emit('close');`  And
2. `readStream.close();`

Now the first one here explicitly emits the close event, and the second one closes the readStream which was piped. both of these statements cause to trigger the res.on('close'), But I couldn't really find the reason for close.

I can not be sure if it is a server bug or client bug , but there could be following reasons:

  1. res.emit('close'); explicitly emitted the close event.

  2. something went wrong with source of pipe. (ex. in above case #2 the readStream was closed) in this case it would take a little longer than the rest of the reasons.

  3. Network went down after the response sending was started

  4. client can also cause the close event to trigger , if it requested the data and then afterwards client wasn't present to receive the data.

the reason could be anything, which made the response not to complete.

like image 128
Naeem Shaikh Avatar answered Nov 03 '22 10:11

Naeem Shaikh


i think this comes from the HTTP protocol itself. there is a option for keep-alive. if this is used then the connection can be reused for different requests.

you shut disable it with res.set("Connection", "close"); ant test it again.

like image 1
yuki Avatar answered Nov 03 '22 08:11

yuki


i would prefer ending your response when the close and finish event is called rather than closing the readStream.

  res.setHeader("content-type", 'application/octet-stream');
  res.setHeader("Content-Disposition", 'attachment; filename="' + 'original' + '"' + "; filename*=UTF-8''" + 'original' + "");
  var readStream;
  var exists = fs.existsSync(fullPath);
       if (exists) {
            callback(true);
            readStream = fs.createReadStream(fullPath);
            readStream.pipe(res);
       } else {
            callback(false);
            return;
       }
          res.on('finish', function(){
                    logger.info('response ending');
                    readStream.close(); // This closes the readStream not the response
                    res.end('FINISHED');  // Ends the response with the message FINISHED

           })
          res.on('close', function(){
                    logger.info('response close');
                    readStream.close(); // This closes the readStream not the response
                    res.end('CLOSED'); // Ends the response with the message CLOSED

          })
          res.on('error', function(error){
                    logger.info(error);
                    readStream.close(); // This closes the readStream not the response
                    res.end(error); // Ends the response with ERROR
          })

The response is not closed since you close the readStream which closes the readStream alone and not the response. To finish or end the response use res.end().

Reference: http://nodejs.org/api/http.html#http_event_close_1 http://nodejs.org/api/http.html#http_response_end_data_encoding

Hope this helps.

like image 1
SUNDARRAJAN K Avatar answered Nov 03 '22 09:11

SUNDARRAJAN K