toverux/expresse

Determining the hub to use based on the request

allquixotic opened this issue · 2 comments

Hi,

I want to use sseHub() with a different hub instance depending on the data in the request. Basically there are distinct sessions based on a token provided by the client, and each session should have its own hub. Since sseHub accepts ISseHubMiddlewareOptions that means I have to hard-code the hub, right? Is there any way to make it dynamic?

Basically, for each call of the API with the sseHub middleware, I need to first examine the request body to determine which hub to use for that client going forward.

I feel like I am going to end up subclassing Hub but I'm not sure of the direction, yet.

I have only compile tested this, but this seems to be the right approach (note, the code is application-specific):

/**
 * 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);
}

Hi,

Your solution is fine.

That's an interesting feature request you have here though, so I might implement it someday!