没有 stream.end() hapi 18 eventsourcing 无法工作

hapi 18 eventsourcing not working without stream.end()

尝试存档:

我尝试使用 HTML5 EventSourcing API https://developer.mozilla.org/de/docs/Web/API/EventSource 将事件推送到我的客户端应用程序 (javascript)。

使用纯节点 http:

的工作示例代码

通过一个简单的示例节点实现,它可以完美地按预期工作。示例代码:https://www.html5rocks.com/en/tutorials/eventsource/basics/

问题:

当我尝试将 EventSourcing(或 SSE)集成到基于 hapi(当前使用最新版本 - 18.1.0)的 API 端点时,它不起作用。

我的路由处理程序代码与我发现的一些代码混合在一起:

const Stream = require('stream');

class ResponseStream extends Stream.PassThrough {
    setCompressor (compressor) {
        this._compressor = compressor;
    }
}

const stream = new ResponseStream();
let data = 0;

setInterval(() => {
    data++;
    stream.write('event: message\n');
    stream.write('data:' + data + '\n\n');
    console.log('write data...', data);
    // stream.end();        
}, 1000);

return h
    .response(stream)
    .type('text/event-stream')
    .header('Connection', 'keep-alive')
    .header('Cache-Control', 'no-cache')

调查结果:

我已经搜索过了,似乎从 hapi 17.x 开始,他们就公开了压缩机 < https://github.com/hapijs/hapi/issues/3658 > 部分功能的冲洗方法。 但是还是不行。

他们发送消息的唯一方法是在发送数据后取消注释 stream.end() 行。问题显然是,如果我关闭流,我将无法发送更多数据:/.

如果我终止服务器(注释 stream.end() 行),数据将在“单次传输”中传输到客户端。我认为即使在刷新流时问题仍然存在于 gzip 缓冲中。

hapi github 中有一些代码示例,但我 none 使用 hapi 17 或 18(所有示例中 hapi =< 16) :/

有人知道如何解决这个问题或有最新 hapi 的有效 EventSource 示例吗?如果有任何帮助或建议,我将不胜感激。

编辑 - 解决方案

下面 post 的解决方案确实有效,但我的 api 端点前面还有一个 nginx 反向代理,看来主要问题不是我的代码,而是 nginx 有还缓冲了事件源消息。 为避免此类问题,请在您的 hapi 中添加:X-Accel-Buffering: no; 并且它可以正常工作

好吧,我刚刚使用 Hapi 18.1.0 进行了测试,并设法创建了一个工作示例。

这是我的处理程序代码:

handler: async (request, h) => {
    class ResponseStream extends Stream.PassThrough {
        setCompressor(compressor) {
            this._compressor = compressor;
        }
    }

    const stream = new ResponseStream();

    let data = 0;

    setInterval(() => {
        data++;
        stream.write('event: message\n');
        stream.write('data:' + data + '\n\n');
        console.log('write data...', data);
        stream._compressor.flush();
    }, 1000);

    return h.response(stream)
        .type('text/event-stream')
}

这是用于测试的客户端代码

var evtSource = new EventSource("http://localhost/");
evtSource.onmessage = function(e) {
    console.log("Data", + e.data);
};

evtSource.onerror = function(e) {
    console.log("EventSource failed.", e);
};

这些是我找到工作示例的方式的资源

https://github.com/hapijs/hapi/blob/70f777bd2fbe6e2462847f05ee10a7206571e280/test/transmit.js#L1816

https://github.com/hapijs/hapi/issues/3599#issuecomment-485190525