使用node.js http2模块发送的服务器事件-我应如何将其与stream / pushStream一起使用?

时间:2018-08-29 22:03:54

标签: node.js stream server-sent-events http2

我正在尝试实现一个服务器,该服务器每500毫秒发送大量数据(对象,而不是文件)。 阅读后,通过http2发送的服务器发送的事件似乎是最快的选择(由于http2是二进制协议,而SSE减少了流量开销)

在http / 1.1上与SSE玩了一点之后 我一直试图在http2上做同样的事情。我尝试使用streampushStream这样做,但没有成功。但是,使用与我在http / 1.1中使用的相同方式似乎可以工作。

我的问题是-为什么使用流的服务器1(见下文)无法正常工作,而服务器2却可以正常工作?工作节点流时我会丢失某些东西吗?

我正在使用节点v10.9.0和chrome 68.0.3440.106

我已经阅读了以下问题和帖子,但仍然无法解决此问题:

服务器1-具有流的http2(不起作用-客户端没有事件。chrome将请求描述为未完成的请求):

const fs = require('fs');
const http2 = require('http2');

const HTTPSoptions = {
    key: fs.readFileSync('./cert/selfsigned.key'),
    cert: fs.readFileSync('./cert/selfsigned.crt'),
};
const template = `
<!DOCTYPE html> 
<html>
<body>
    <script type="text/javascript">
        const  source = new EventSource('/sse/');
        source.onmessage = function(e) { 
            document.body.innerHTML += e.data + '<br>';
        };
    </script>
</body>
</html>
`;


const server = http2.createSecureServer(HTTPSoptions);

server.on('stream', (stream, headers, flags) => {
    if (stream.url === 'sse/') {
        console.log(stream.respond);
        stream.respond({
            ':status': 200,
            'content-type': 'text/event-stream'
        });
        setInterval(() => stream ? res.write(`data: ${Math.random()}\n\n`) : '', 200);
    }
});

server.on('request', (req, res) => {
    if(req.url === '/') {
        res.end(template);
    }
});



server.listen(3001);

服务器2-具有流的http2(工作正常):

const fs = require('fs');
const http2 = require('http2');

const HTTPSoptions = {
    key: fs.readFileSync('./cert/selfsigned.key'),
    cert: fs.readFileSync('./cert/selfsigned.crt'),
};
const template = `
<!DOCTYPE html> 
<html>
<body>
    <script type="text/javascript">
        const  source = new EventSource('/sse/');
        source.onmessage = function(e) { 
            document.body.innerHTML += e.data + '<br>';
        };
    </script>
</body>
</html>
`;


const server = http2.createSecureServer(HTTPSoptions);

server.on('request', (req, res) => {
    req.socket.setKeepAlive(true);

    if(req.url === '/sse/') {

        res.writeHead(200, {
            'Content-Type': 'text/event-stream', // <- Important headers
            'Cache-Control': 'no-cache'
        });
        res.write('\n');

        setInterval(() => res.write(`data: ${Math.random()}\n\n`), 200);
    } else {
        res.end(template);
    }
});

server.listen(3001);

1 个答案:

答案 0 :(得分:0)

要获取http2流的请求路径,您必须查看:path标头(docs):

if (headers[':path'] === '/sse/') {

您还尝试使用res.write,而res应该是stream

这是基于您的“服务器1”实现的工作处理程序功能:

server.on('stream', (stream, headers, flags) => {
    if (headers[':path'] === '/sse/') {
        stream.respond({
            ':status': 200,
            'content-type': 'text/event-stream'
        });
        setInterval(() => stream.write(`data: ${Math.random()}\n\n`), 200);
    }
});