express.js не передает поток chunked 'text/event-stream' resposne
Я пытаюсь отправить SSE text/event-stream
ответ от конечной точки express.js. Мой обработчик маршрута выглядит так:
function openSSE(req, res) {
res.writeHead(200, {
'Content-Type': 'text/event-stream; charset=UTF-8',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Transfer-Encoding': 'chunked'
});
// support the polyfill
if (req.headers['x-requested-with'] == 'XMLHttpRequest') {
res.xhr = null;
}
res.write(':' + Array(2049).join('\t') + '\n'); //2kb padding for IE
res.write('id: '+ lastID +'\n');
res.write('retry: 2000\n');
res.write('data: cool connection\n\n');
console.log("connection added");
connections.push(res);
}
Позже я тогда позвоню:
function sendSSE(res, message){
res.write(message);
if (res.hasOwnProperty('xhr')) {
clearTimeout(res.xhr);
res.xhr = setTimeout(function () {
res.end();
removeConnection(res);
}, 250);
}
}
Мой браузер делает и держит запрос:
Ни один из ответов не передается в браузер. Ни одно из моих событий не запущено. Если я убью сервер express.js. Ответ внезапно истощается, и каждое событие сразу попадает в браузер.
Если я обновлю свой код, чтобы добавить res.end()
после res.write(message)
line Он корректно очищает поток, но затем возвращается к опросу событий и не передает поток ответа.
Я попытался добавить заполнение к заголовку ответа, какres.write(':' + Array(2049).join('\t') + '\n');
как я видел из другого поста SO, это может привести к тому, что браузер истощит ответ.
Я подозреваю, что это проблема с express.js, потому что я ранее использовал этот код с нативными узлами http
сервер и он работал правильно. Поэтому мне интересно, есть ли какой-нибудь способ обойти экспресс-упаковку объекта ответа.
1 ответ
Это код, который я работаю в своем проекте.
Сторона сервера:
router.get('/listen', function (req, res) {
res.header('transfer-encoding', 'chunked');
res.set('Content-Type', 'text/json');
var callback = function (data) {
console.log('data');
res.write(JSON.stringify(data));
};
//Event listener which calls calback.
dbdriver.listener.on(name, callback);
res.socket.on('end', function () {
//Removes the listener on socket end
dbdriver.listener.removeListener(name, callback);
});
});
Сторона клиента:
xhr = new XMLHttpRequest();
xhr.open("GET", '/listen', true);
xhr.onprogress = function () {
//responseText contains ALL the data received
console.log("PROGRESS:", xhr.responseText)
};
xhr.send();
Я тоже боролся с этим, поэтому после некоторого просмотра и чтения я решил эту проблему, установив дополнительный заголовок для объекта ответа:
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
"Content-Encoding": "none"
});
Короче говоря, когда EventSource
ведет переговоры с сервером, он отправляет Accept-Encoding: gzip, deflate, br
заголовок, который делает express
ответить Content-Encoding: gzip
заголовок. Итак, есть два решения этой проблемы. Первое - добавитьContent-Encoding: none
заголовок ответа, а второй - сжатие ответа (gzip).