Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express + Request Changing headers mid-stream

I'm using express as my server and request to retrieve content from an up-stream box.

I've got this beautifully simple function to stream data from the up-stream to the client:

function(req, res){
  request("http://example.com").pipe(res);
}

The upstream box is returning a cache header Cache-Control: no-cache that I'd like to modify, so that Nginx (reverse proxy) can cache the response.

Where should I put the res.header('Cache-Control', 60);?

I've tried:

function(req, res){
  var retrieve = request("http://example.com");
  retrieve.on('data', function(chunk){
    if(res.get('Cache-Control') != 60)
      res.header('Cache-Control', 60);
  });
  retrieve.pipe(res);
}

But this throws a Error: Can't set headers after they are sent error.

Is there a listener that fires when the headers are sent, but before writeHeader() is called?

like image 817
alexcline Avatar asked Nov 01 '13 17:11

alexcline


People also ask

Can't set headers after they are sent?

The error "Error: Can't set headers after they are sent." means that you're already in the Body or Finished state, but some function tried to set a header or statusCode. When you see this error, try to look for anything that tries to send a header after some of the body has already been written.

What does res sendFile do?

The res. sendFile() function basically transfers the file at the given path and it sets the Content-Type response HTTP header field based on the filename extension.

What is Express Urlencoded extended true?

The extended option allows to choose between parsing the URL-encoded data with the querystring library (when false ) or the qs library (when true ). The “extended” syntax allows for rich objects and arrays to be encoded into the URL-encoded format, allowing for a JSON-like experience with URL-encoded.

Does Res send end the function?

send doesn't return the function, but does close the connection / end the request.


2 Answers

It seems request has been updated since the accepted answer was submitted, making this process much easier. You can now do the following:

var resource = request('http://example.com');

resource.on('response', function(response) {
    response.headers['Cache-Control'] = 'max-age=60, public';
});

resource.pipe(res);

Much nicer!

like image 169
cbnz Avatar answered Oct 16 '22 10:10

cbnz


Thanks to Peter Lyons, I was able to get this working using this code:

function(req, res){
  request("http://example.com").pipe(res);

  res.oldWriteHead = res.writeHead;
  res.writeHead = function(statusCode, reasonPhrase, headers){
    res.header('Cache-Control', 'max-age=60, public');
    res.oldWriteHead(statusCode, reasonPhrase, headers);
  }
}
like image 27
alexcline Avatar answered Oct 16 '22 08:10

alexcline