Home > front end >  express JS https.get cause "Cannot set headers after they are sent to the client"
express JS https.get cause "Cannot set headers after they are sent to the client"

Time:03-01

I know there are many threads with this error but I could not find anything close to my use case.

I have ExpressJS app and one of the endpoints loads an image and transforms the image as for my needs.

This is my code:

app.get('/test', (request, response) => {
    require('https').get('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png', (image) => {
        image.on('data', (data) => {
            response.setHeader('Content-Type', 'text/plain');
            response.end('wow')
        });
    });
});

This code responds with wow but then server fails with

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:561:11)
    at IncomingMessage.<anonymous> (/home/boris/_/idealo/caas/magnolia/image-processor/server.js:18:22)
    at IncomingMessage.emit (events.js:400:28)
    at addChunk (internal/streams/readable.js:290:12)
    at readableAddChunk (internal/streams/readable.js:265:9)
    at IncomingMessage.Readable.push (internal/streams/readable.js:204:10)
    at HTTPParser.parserOnBody (_http_common.js:139:24)
    at TLSSocket.socketOnData (_http_client.js:515:22)
    at TLSSocket.emit (events.js:400:28)
    at addChunk (internal/streams/readable.js:290:12) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

How do I fix the error?

CodePudding user response:

This answer extends what if have commented already.
image is the response object for the request you are performing to google. The response itself is a stream. The response object can listen for the data event that will be triggered every time a new bit of data passed through the stream and was received by your server making the request. As the data event will be triggered more than once you are trying to set headers on a response that has already been send.
So what you are looking for is to somehow save each chunk of data that was received then process that data as a whole and finally send your response. It could look somewhat like the following. Here the Buffer.toString method might not be the best way to go as we are dealing with an image but it should give a general idea of how to do it.

app.get('/test', (request, response) => {
    require('https').get('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png', (image) => {
        let data = "";
        image.on('data', (chunk) => {
            data  = chunk.toString();
        });
        // end event will be triggered when every bit of the image was received
        image.on("end", () => {
            // process the image in here
            response.setHeader("Content-Type", "plain/text");
            response.end("wow");
        })
    });
});
  • Related