express-http-proxy icon indicating copy to clipboard operation
express-http-proxy copied to clipboard

Feature Request: Server Sent Events

Open DanielMSchmidt opened this issue 7 years ago • 3 comments

Hi there,

I would like to use this library in a mock server I am writing & first of all I would like to thank you for all the effort you put into this. I need to be able to proxy server sent events (also referred to as EventSource by the browser) and I would be willing to do a PR for this. I would like to discuss if there is a way how this project already supports these kind of events that I have overlooked. The "Streaming" section in the readme hinted me in a direction that it should already be supported, so I am a bit unsure here.

Current behavior

If I have this code for an express server to proxy against

app.use((req, res, next) => {
    res.writeHead(200, {
        "Content-Type": "text/event-stream",
        "Cache-Control": "no-cache",
        Connection: "keep-alive"
    });

    res.sseSendUntyped = data => {
        res.write("data: " + JSON.stringify(data) + "\n\n");
    };

    res.sseSendTyped = (type, data) => {
        res.write("event: " + type + "\n");
        res.write("data: " + JSON.stringify(data) + "\n\n");
    };

    next();
});

app.use((req, res) => {
    console.log("Send1", Date.now());
    res.sseSendUntyped({ count: 1 });
    setTimeout(() => {
        console.log("Send2", Date.now());
        res.sseSendUntyped({ count: 2 });
        res.end();
    }, 800);
});

And this code as a client

const source = new EventSource(`http://localhost:${port}`, options);
let callCount = 0;
source.onmessage: evt => {
    console.log(evt);
    callCount++;
    console.log("Recv" + callCount, Date.now());
}

I get these timings:

Send1 1524140030398
Send2 1524140031231
Recv1 1524140031244
Recv2 1524140031251

I would expect timings like this:

Send1 1524140030398
Recv1 1524140030418
Send2 1524140031231
Recv2 1524140031251

For me this looks like the express-http-proxy is waiting for the request to finish until it sends out data, which is in contrast to what I need for server sent events.

Could you guide me in a good direction? I am more then willing to extend this proxy if needed, but I could also do a seperate project if you say it is out of scope.

Resources about Server Sent Events

Here are some resources I found useful when learning about them the first time:

  • https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
  • https://www.html5rocks.com/en/tutorials/eventsource/basics/
  • https://streamdata.io/blog/server-sent-events/

DanielMSchmidt avatar Apr 19 '18 12:04 DanielMSchmidt

@DanielMSchmidt Thanks for such a well-written feature request. I'd be happy to take a look next week, or to accept/review a PR.

monkpow avatar Apr 20 '18 16:04 monkpow

Can you also post the code for your proxy request (probably something like

otherApp.use(path, proxy(host, config));

)?
Thanks!

monkpow avatar Apr 20 '18 16:04 monkpow

It was essentially that, I added no proxy configuration, so basically

otherApp.use(proxy(host))

DanielMSchmidt avatar Apr 20 '18 16:04 DanielMSchmidt