I have an expressJS server and I would like to call a WebSocket (I use the ws package) inside it.
Here is what I do on the server side:
import express from 'express';
import { WebSocketServer } from 'ws';
const app = express();
const server = app.listen(3000);
const wss = new WebSocketServer({ server });
// Set the wss to be able to retrieve it in the route
app.set('wss', wss);
app.get('/download', (req, res) => {
// Retrieve the WebSocket server
const wss = req.app.get('wss');
wss.on('connection', async (ws) => {
ws.send('hello world');
// Do some async stuff here to gather data and send some messages
const fileContents = Buffer.from(myData);
const readStream = new stream.PassThrough();
readStream.end(fileContents);
res.set('Content-disposition', `attachment; filename=test.csv`);
res.set('Content-Type', 'text/csv');
readStream.pipe(res);
ws.close()
})
})
In my client:
axios.get('http://'+ window.location.host +'/download', {
responseType: 'blob',
}).then(response=>{
// create file link in browser's memory
const href = URL.createObjectURL(response.data);
// create "a" HTML element with href to file & click
const link = document.createElement('a');
link.href = href;
link.setAttribute('download', `file.csv`);
//or any other extension
document.body.appendChild(link);
link.click();
// clean up "a" element & remove ObjectURL
document.body.removeChild(link);
URL.revokeObjectURL(href);
})
const ws = new WebSocket('ws://' + window.location.host);
ws.addEventListener('message', function(m) {
// Do some stuff with messages
})
This works properly the first time /download
is called (the messages are sent and the file gets downloaded). But the second time (when I refresh the page of the client) the messages are sent but the download fails. I get the following error in the server and the server crashes:
node:internal/errors:478
ErrorCaptureStackTrace(err);
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Express seems to consider the second request part of the first. Why is express not interpreting the second call as an independent call like it does for any endpoint call? What should I do to avoid this error?