0

I try to read stream request line by line and use split module for it. But I got an error when I try set header connection:close when data is big!

Example code:

const http = require('http');
const split = require('split');

server.on('request', (req, res) => {
let size = 0;

req
    .pipe(split())
    .on('data', chunk => {
        size += chunk.length;
        if (size > 1024) {
            res.statusCode = 413;
            res.setHeader('Connection', 'close');
            res.end('File is too big!');
        }
    })
    .on('end', () => {
        res.end('OK');        
    });
}

Error: Can't set headers after they are sent.

How I can stop browser streaming without set a header and how correctly read line-by-line request stream in this case?

Avrel Dusop
  • 135
  • 3
  • 11
  • Can't set headers after they are sent is an error that occurs when you try to change the header of a request after the request has been sent. Are you firing multiple commands on the same request? If so, you either need to alter your code to fire only one command per request and close the connection on a separate request, or determine how to accomplish the same thing without changing your headers. I generally do something like make a POST to [baseUrl]/end to end a browser stream. – Link0352 Aug 18 '17 at 13:25

1 Answers1

1

The issue is that once the size exceeds 1024, and you send back a response, the data events will continue to be emitted, so the next line after the size exceeds 1024 will send back a new 413 response, which causes the error (because you can only send one response).

An option would be to use something like size-limit-stream to limit the size of the stream, and trigger an error when it does.

Something like this:

const limitStream = require('size-limit-stream')

...


server.on('request', (req, res) => {
  let limiter = limitStream(1024).on('error', e => {
    res.statusCode = 413;
    res.setHeader('Connection', 'close');
    res.end('File is too big!');
  });

  req .pipe(split())
      .pipe(limiter)
      .on('data', chunk => {
        // this will emit until the limit has been reached,
        // or all lines have been read.
      })
      .on('end', () => {
        // this will emit when all lines have _succesfully_ been read
        // (so the amount of data fell within the limit)
        res.end('OK');
      });
});
robertklep
  • 198,204
  • 35
  • 394
  • 381