Package: httpx-sse
httpx-sseConsumeServer-Sent Event (SSE)messages withHTTPX.Table of contentsInstallationQuickstartHow-ToAPI ReferenceInstallationNOTE: This is beta software. Please be sure to pin your dependencies.pipinstallhttpx-sse=="0.4.*"Quickstarthttpx-sseprovides theconnect_sseandaconnect_ssehelpers for connecting to an SSE endpoint. The resultingEventSourceobject exposes the.iter_sse()and.aiter_sse()methods to iterate over the server-sent events.Example usage:importhttpxfromhttpx_sseimportconnect_ssewithhttpx.Client()asclient:withconnect_sse(client,"GET","http://localhost:8000/sse")asevent_source:forsseinevent_source.iter_sse():print(sse.event,sse.data,sse.id,sse.retry)You can try this against this example Starlette server (credit):# Requirements: pip install uvicorn starlette sse-starletteimportasyncioimportuvicornfromstarlette.applicationsimportStarlettefromstarlette.routingimportRoutefromsse_starlette.sseimportEventSourceResponseasyncdefnumbers(minimum,maximum):foriinrange(minimum,maximum+1):awaitasyncio.sleep(0.9)yield{"data":i}asyncdefsse(request):generator=numbers(1,5)returnEventSourceResponse(generator)routes=[Route("/sse",endpoint=sse)]app=Starlette(routes=routes)if__name__=="__main__":uvicorn.run(app)How-ToCalling into Python web appsYou cancall into Python web appswith HTTPX andhttpx-sseto test SSE endpoints directly.Here's an example of calling into a Starlette ASGI app...importasyncioimporthttpxfromhttpx_sseimportaconnect_ssefromsse_starlette.sseimportEventSourceResponsefromstarlette.applicationsimportStarlettefromstarlette.routingimportRouteasyncdefauth_events(request):asyncdefevents():yield{"event":"login","data":'{"user_id": "4135"}',}returnEventSourceResponse(events())app=Starlette(routes=[Route("/sse/auth/",endpoint=auth_events)])asyncdefmain():asyncwithhttpx.AsyncClient(app=app)asclient:asyncwithaconnect_sse(client,"GET","http://localhost:8000/sse/auth/")asevent_source:events=[sseasyncforsseinevent_source.aiter_sse()](sse,)=eventsassertsse.event=="login"assertsse.json()=={"user_id":"4135"}asyncio.run(main())Handling reconnections(Advanced)SSETransportandAsyncSSETransportdon't have reconnection built-in. This is because how to perform retries is generally dependent on your use case. As a result, if the connection breaks while attempting to read from the server, you will get anhttpx.ReadErrorfromiter_sse()(oraiter_sse()).However,httpx-ssedoes allow implementing reconnection by using theLast-Event-IDand reconnection time (in milliseconds), exposed assse.idandsse.retryrespectively.Here's how you might achieve this usingstamina...importtimefromtypingimportIteratorimporthttpxfromhttpx_sseimportconnect_sse,ServerSentEventfromstaminaimportretrydefiter_sse_retrying(client,method,url):last_event_id=""reconnection_delay=0.0# `stamina` will apply jitter and exponential backoff on top of# the `retry` reconnection delay sent by the server.@retry(on=httpx.ReadError)def_iter_sse():nonlocallast_event_id,reconnection_delaytime.sleep(reconnection_delay)headers={"Accept":"text/event-stream"}iflast_event_id:headers["Last-Event-ID"]=last_event_idwithconnect_sse(client,method,url,headers=headers)asevent_source:forsseinevent_source.iter_sse():last_event_id=sse.idifsse.retryisnotNone:reconnection_delay=sse.retry/1000yieldssereturn_iter_sse()Usage:withhttpx.Client()asclient:forsseiniter_sse_retrying(client,"GET","http://localhost:8000/sse"):print(sse.event,sse.data)API Referenceconnect_ssedefconnect_sse(client:httpx.Client,method:str,url:Union[str,httpx.URL],**kwargs,)->ContextManager[EventSource]Connect to an SSE endpoint and return anEventSourcecontext manager.This setsCache-Control: no-storeon the request, as per the SSE spec, as well asAccept: text/event-stream.If the responseContent-Typeis nottext/event-stream, this will raise anSSEError.aconnect_sseasyncdefaconnect_sse(client:httpx.AsyncClient,method:str,url:Union[str,httpx.URL],**kwargs,)->AsyncContextManager[EventSource]An async equivalent toconnect_sse.EventSourcedef__init__(response:httpx.Response)Helper for working with an SSE response.responseThe underlyinghttpx.Response.iter_ssedefiter_sse()->Iterator[ServerSentEvent]Decode the response content and yield correspondingServerSentEvent.Example usage:forsseinevent_source.iter_sse():...aiter_sseasyncdefiter_sse()->AsyncIterator[ServerSentEvent]An async equivalent toiter_sse.ServerSentEventRepresents a server-sent event.event: str- Defaults to"message".data: str- Defaults to"".id: str- Defaults to"".retry: str | None- Defaults toNone.Methods:json() -> Any- Returnssse.datadecoded as JSON.SSEErrorAn error that occurred while making a request to an SSE endpoint.Parents:httpx.TransportErrorLicenseMITChangelogAll notable changes to this project will be documented in this file.The format is based onKeep a Changelog.0.4.0 - 2023-12-22RemovedDropped Python 3.7 support, as it has reached EOL. (Pull #21)AddedAdd official support for Python 3.12. (Pull #21)FixedAllowContent-Typethat contain but are not strictlytext/event-stream. (Pull #22 by @dbuades)Improve error message whenContent-Typeis missing. (Pull #20 by @jamesbraza)0.3.1 - 2023-06-01AddedAdd__repr__()forServerSentEventmodel, which may help with debugging and other tasks. (Pull #16)0.3.0 - 2023-04-27ChangedRaising anSSEErrorif the response content type is nottext/event-streamis now performed as part ofiter_sse()/aiter_sse(), instead ofconnect_sse()/aconnect_sse(). This allows inspecting the response before iterating on server-sent events, such as checking for error responses. (Pull #12)0.2.0 - 2023-03-27Changedconnect_sse()andaconnect_sse()now require amethodargument:connect_sse(client, "GET", "https://example.org"). This provides support for SSE requests with HTTP verbs other thanGET. (Pull #7)0.1.0 - 2023-02-05Initial releaseAddedAddconnect_sse,aconnect_sse(),ServerSentEventandSSEError.