httpx icon indicating copy to clipboard operation
httpx copied to clipboard

Server Sent Events

Open tomchristie opened this issue 3 years ago • 15 comments

It'd be really neat to offer built-in support for server sent events, which are a way for servers to stream events to an HTTP client.

(Similar to WebSockets, but uni-directional)

with httpx.stream("GET", "https://www.example.org/sse") as response:
    for sse in response.iter_sse():
        print(sse.data, sse.event, sse.id, sse.retry)

We'd probably also want to include an sse.json() helper method.

Useful resources...

  • https://www.html5rocks.com/en/tutorials/eventsource/basics/
  • https://sysid.github.io/sse/
  • https://pgjones.gitlab.io/quart/tutorials/broadcast_tutorial.html

Not sure if this has come up before or not, but it'd be a really neat feature for us to offer, for relatively little effort.

tomchristie avatar Sep 10 '20 21:09 tomchristie

I really like this. SSE are a under-used feature of the web in my opinion - I could absolutely see myself hooking up a really simple message bus between two machines using SSE served by Starlette and received by HTTPX.

simonw avatar Oct 10 '20 04:10 simonw

FWIW, I had played with SSE myself in Bocadillo at the time, so just linking to the user docs and the server-side encoding implementation in case they could be useful here, as some extra reference material.

florimondmanca avatar Oct 10 '20 07:10 florimondmanca

+1 on this feature. Using FastAPI with sse-starlette + async integration tests with HTTPX testclient. Having a hard time testing my SSE endpoints due to lack of async testclients for SSE

havardthom avatar Apr 23 '21 07:04 havardthom

+1 This is the recommended option with FastAPI and sse-starlette. Would be really nice to have this feature

t94j0 avatar May 18 '21 21:05 t94j0

A couple more references:

  • https://github.com/aio-libs/aiohttp-sse
  • https://github.com/ebraminio/aiosseclient
  • https://github.com/sysid/sse-starlette

dusty-phillips avatar Aug 26 '21 13:08 dusty-phillips

Is this issue open? I would like to contribute if this is open. Thanks.

harshitsinghai77 avatar Oct 09 '21 18:10 harshitsinghai77

@harshitsinghai77 Sure, looks like this is open and contributions and drafts are welcome. :)

florimondmanca avatar Oct 10 '21 20:10 florimondmanca

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Feb 20 '22 15:02 stale[bot]

Still valid thx, @stale bot.

tomchristie avatar Feb 21 '22 13:02 tomchristie

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Mar 25 '22 07:03 stale[bot]

Guessing this is still valid..

johtso avatar Mar 25 '22 18:03 johtso

We should probably bump up the durations on this stale bot. (Wasn't expecting that it'd repeatedly attempt closes after the first attempt) 😐

tomchristie avatar Mar 25 '22 19:03 tomchristie

Surprised that this issue has been open for over a year. I just recently added functionality to rpc.py and wrote a code for parsing SSE. If anyone is interested in this, I'll be making a PR to httpx this week. https://github.com/abersheeran/rpc.py/blob/master/rpcpy/client.py#L211-L243

abersheeran avatar Mar 28 '22 15:03 abersheeran

Ok. Probably a good plan would be to sketch out the API you'd propose, before submitting a pull request.

tomchristie avatar Mar 29 '22 09:03 tomchristie

We should also strongly consider if we really want to have this as functionality in the core package or not. Feasible that we should drop this ticket, but allow for a third party implementation.

For example, this'd make for a perfectly reasonable API, without us having to add additional functionality to httpx itself...

import httpx
from httpx_sse import iter_sse

with httpx.stream("GET", "https://www.example.org/sse") as response:
    for sse in iter_sse(response):
        print(sse.data, sse.event, sse.id, sse.retry)

tomchristie avatar Mar 29 '22 10:03 tomchristie

I worked on an httpx-sse package that I justed pushed here: https://github.com/florimondmanca/httpx-sse

The API is a bit different from what @tomchristie suggested. This is because the spec requires us to prepare or check some things on the request or the response.

I've thought about making connect_sse()/ aconnect_sse() handle reconnections, but that would be a lot more work and may not necessarily fit all use cases, as implementation needs may vary. So I've let that to a "how-to" guide in the project README.

import httpx
from httpx_sse import connect_sse

with httpx.Client() as client:
    with connect_sse(client, "http://localhost:8000/sse") as event_source:
        for sse in event_source.iter_sse():
            print(sse.event, sse.data, sse.id, sse.retry)

This has not been released to PyPI yet. I'd be happy for folks to try that out first. :-)

Edit: released, https://pypi.org/project/httpx-sse/0.1.0

florimondmanca avatar Nov 06 '22 12:11 florimondmanca

very interested in this

MrSalman333 avatar Jan 07 '23 10:01 MrSalman333