'Cannot set headers after they are sent to the client' after second request

Issue

I made a web server that serves as a client-side using socket.io-client and express (because I have to use this form in other project).

It emits the string posted and when receiving ‘boom’ emit from io server it responds by sending the string served.

Posting ‘heat_bomb’ works well for the first time, but when I try second time ‘[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client’ occurs at res.send(data) in socket.on().

Is there a way to refresh whenever post request is generated, so that each request uses independent response?

app.ts

import express from 'express'
import {io} from 'socket.io-client'
import bodyParser from 'body-parser'

const app=express()
const PORT=8080

const socket=io(`http://localhost:2002`, {
    query:{
        hello:"merhaba"
    }
})

app.use(bodyParser.urlencoded({extended:false}))

app.get('/', (req, res)=>{
    res.sendFile(__dirname+`/index.html`)
})
app.post('/heat_bomb', (req, res)=>{
    socket.emit('heat_bomb', req.body.elem)
    socket.on('boom', (data)=>{
        res.send(data)
    })
})

app.listen(PORT, ()=>{
    console.log(`Server Running: ${PORT}`)
})

index.html

$('#heat_button').click(function(){
    console.log('heating bomb')
    $.post('/heat_bomb', {elem: $('#input_number').val()},(data, status)=>{
        console.log(data)
        console.log('heated')
    })
})

Solution

Your /heat_bomb middleware registers a new boom handler for every request on the same globally defined socket. Although your code snippet does not show how the heat_bomb and boom events are connected, I assume that the emit('boom') during the second request re-triggers the heat_bomb handler that was registered during the first request, leading to another res.send for the res from the first request, which is already completed. This leads to the observed error message.

socket.once('boom') alone will not solve this reliably: if one heat_bomb event can overtake another, the data from the first can wrongly be "paired" with the res from the second. The res needs to be a second argument of your events, something like this:

socket.emit('heat_bomb', req.body.elem, res);
socket.once('boom', function(data, res) {
  res.send(data);
});

Answered By – Heiko Theißen

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published