Note: for support questions, please use one of these channels: stackoverflow or slack
I am trying to make an app with Node.js, Express and Socket.io. I'm using EJS as the view engine. This is the relevant part of my code -
const express = require('express');
const app = express();
//copied from socket.io tutorial
const http = require('http').Server(app);
const io = require('socket.io')(http);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, '../templates'));
...
app.get('/', function (req, res) {
logger.info('index');
return res.render('index');
});
...
const port = process.env.PORT || localConfig.port;
http.listen(port);
Now if I navigate to localhost:3000, I get the error
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader (_http_outgoing.js:496:3)
at ServerResponse.header (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:767:10)
at ServerResponse.contentType (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:595:15)
at ServerResponse.send (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:145:14)
at done (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/response.js:1004:10)
at tryHandleCache (/home/aniket/Documents/HumbleHelper/node_modules/ejs/lib/ejs.js:228:10)
at View.exports.renderFile [as engine] (/home/aniket/Documents/HumbleHelper/node_modules/ejs/lib/ejs.js:437:10)
at View.render (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/view.js:135:8)
at tryRender (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/application.js:640:10)
From the log, I can see that 'index' has been called twice, followed by the error. However, if I remove this line -
const io = require('socket.io')(http);
Navigate the browser to localhost:3000 and it fails. I have tried a res.send()
instead of res.render()
but that fails too.
The index page should be rendered correctly
I'm also using Passport, Helmet, Body-parser and express-session in conjunction with Socket.io
This happens if I share the same port between Socket.io and Express
I tried giving Socket.io another port. And tried to connect to that port. Now it gives this error
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader (_http_outgoing.js:496:3)
at expressInit (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/middleware/init.js:30:42)
at Layer.handle [as handle_request] (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:317:13)
at /home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:335:12)
at next (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:275:10)
at query (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/middleware/query.js:45:5)
at Layer.handle [as handle_request] (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/layer.js:95:5)
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader (_http_outgoing.js:496:3)
at expressInit (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/middleware/init.js:30:42)
at Layer.handle [as handle_request] (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:317:13)
at /home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:335:12)
at next (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:275:10)
at query (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/middleware/query.js:45:5)
at Layer.handle [as handle_request] (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/layer.js:95:5)
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader (_http_outgoing.js:496:3)
at expressInit (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/middleware/init.js:30:42)
at Layer.handle [as handle_request] (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:317:13)
at /home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:335:12)
at next (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/index.js:275:10)
at query (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/middleware/query.js:45:5)
at Layer.handle [as handle_request] (/home/aniket/Documents/HumbleHelper/node_modules/express/lib/router/layer.js:95:5)
_http_outgoing.js:489
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader (_http_outgoing.js:496:3)
at ServerResponse.writeHead (_http_server.js:209:21)
at IncomingMessage.onEnd (/home/aniket/Documents/HumbleHelper/node_modules/engine.io/lib/transports/polling.js:180:9)
at emitNone (events.js:105:13)
at IncomingMessage.emit (events.js:207:7)
at endReadableNT (_stream_readable.js:1059:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)
I have found the issue at
require('appmetrics-dash').attach();
require('appmetrics-prometheus').attach();
Working Fiddle:
https://github.com/BrokenMutant/socket.io-fiddle
run "npm start" and go to localhost:3000 and the console should show the error
Hi @Herald-Of-Solace, I know this is 2 years old but fyi I believe the problem is not with socket.io, but with the appmetrics packages.
appmetrics-dash.attach()
is not designed to be followed by another attach
call (e.g. appmetrics-dash.attach()
or appmetrics-prometheus.attach()
).
In your fiddle you should do:
const express = require('express');
const app = express();
const port = 3000;
app.set('view engine','ejs');
app.set('views',__dirname + '/public');
app.get('/',(req,res) =>
res.render('index'));
app.use('/metrics', require('appmetrics-prometheus').endpoint()); // see https://github.com/CloudNativeJS/appmetrics-prometheus#usage
var server = app.listen(port);
require('appmetrics-dash').monitor({server, app}); // see https://github.com/appsody/stacks/blob/b6333dceb86a2501bfa987a5ad91964cf2cad104/incubator/nodejs-express/image/project/server.js#L13
const io = require('socket.io')(server);
io.on('connect', onConnect);
server.listen(port, () => console.log('server listening on port ' + port));
function onConnect(socket){
console.log('connect ' + socket.id);
socket.on('disconnect', () => console.log('disconnect ' + socket.id));
}
Thanks @rwalle61 for your help! As far as I remember I was following the default Node JS template for IBM Bluemix (It was for a hackathon), and the lines were already there if memory serves!
Anyway, I completed the hackathon by removing those lines. Now I see why this happened! Thanks for your help!
Most helpful comment
This happens if I share the same port between Socket.io and Express