Express SSE-广播给会话用户

问题描述 投票:0回答:1

我正在使用Typescript在Express.js中编写REST API。该API基于随机生成的“会议室令牌”,该字符串是指会话数据的特定实例的字符串。会议室令牌可以在多个客户端之间共享-通常是让一个用户创建一个新会议室,然后他们复制粘贴URL以与包括该会议室令牌的朋友/同事共享。

在此API中,我需要支持服务器发送事件(SSE)。看来,具有Typescript类型的Express的唯一SSE中间件是ExpreSSE

因此,我想做的是实施“广播的” SSE(我用术语“广播”来表示;我知道在网络层实际上是一对一的),每个事件仅针对那些具有订阅了特定的房间令牌。

为了说明这一点,请想象下面的对话:

  • 客户端A用数据有效载荷/api/subscribeToChangeNotification呼叫{token: '12345'}
  • 客户端B用数据有效载荷/api/subscribeToChangeNotification呼叫{token: '6789'}
  • 客户端C使用数据有效载荷/api/subscribeToChangeNotification调用{token: '12345'}
  • [服务器端发生事件,启动了SSE代码流。此事件与令牌12345有关,因此SSE消息被发送[[only到客户端A和C。
  • 令牌6789发生另一个SSE,并且消息
  • 发送到客户端B。
为ExpreSSE处理广播的两种记录方法是使用所谓的Hub对象,其中:

    方法1涉及使用Hub中间件为
  • 每个客户端
创建一个新的sse。这不是我想要的,因为那样的话,“广播”将只发给一个单独的客户端,而不是每个客户端订阅给定令牌。方法2涉及设置全局Hub并将其传递到sseHub中间件。
  • 我需要一个“方法#3”,当客户端调用subscribeToChangeNotification时,该方法可让我根据请求的有效负载指定要使用的集线器。我该怎么办?
  • typescript express server-sent-events
    1个回答
    0
    投票
    这是我最终完成此操作的方式。 middleware函数的第一行调用我特定于应用程序的会话全局数据(Map),该数据为每个不同的房间令牌创建并保留对新Hub的引用。 middleware函数的其余部分只是从ExpreSSE的源代码的sseHub()复制粘贴而来。然后,我将SSE API中的dynamicSseHub()用作中间件。

    /** * SSE middleware that configures an Express response for an SSE session, installs `sse.*` functions on the Response * object, as well as the `sse.broadcast.*` variants. * * @param options An ISseMiddlewareOptions to configure the middleware's behaviour. */ function dynamicSseHub(options: Partial<ISseMiddlewareOptions> = {}): Handler { function middleware(req: Request, res: ISseResponse, next: NextFunction): void { let hub : IHub = sessions.get(req.body.toString()).hub; //=> Register the SSE functions of that client on the hub hub.register(res.sse); //=> Unregister the user from the hub when its connection gets closed (close=client, finish=server) res.once('close', () => hub.unregister(res.sse)); res.once('finish', () => hub.unregister(res.sse)); //=> Make hub's functions available on the response (res as ISseHubResponse).sse.broadcast = { data: hub.data.bind(hub), event: hub.event.bind(hub), comment: hub.comment.bind(hub), }; //=> Done next(); } return compose(sse(options), middleware); }

    © www.soinside.com 2019 - 2024. All rights reserved.