litestar-org / litestar

Production-ready, Light, Flexible and Extensible ASGI API framework | Effortlessly Build Performant APIs
https://litestar.dev/
MIT License
5.59k stars 380 forks source link

Bug: SSE not showing up in browser if not explicitly ending AsyncGenerator content with newline #2678

Closed macabrus closed 10 months ago

macabrus commented 1 year ago

Description

I am using Litestar on the backend, HTMX + Jinja2 for templating. I have following code:


@get(path="/progress", sync_to_thread=False)
def handle_updates() -> ServerSentEvent:
    """This route pushes finish/progress events to the client."""

    async def result_notifier() -> AsyncGenerator[str, None]:
        # keep state per client, re-render template fragment
        ctx = {
            "progress": None,
            "tasks": (tasks := TASKS),
        }
        for i in itertools.count(1):
            html = f'<h1>{i}</h1>\n'   # this \n missing was the problem!!!
            yield html
            await asyncio.sleep(1)

    return ServerSentEvent(result_notifier())

and following event receiver in HTMX:

<div id="queue-status" hx-ext="sse" sse-connect="/progress" >
    <div sse-swap="message"></div>
</div>

also tried curling:

curl http://localhost:8000/progress
data: <h1>1</h1>
data: <h1>2</h1>
...

curl http://localhost:8000/progress
data: <h1>1</h1>

data: <h1>2</h1>

data: <h1>3</h1>

data: <h1>4</h1>
...

My issue is that i didn't explicitly end events with '\n' so browser was forever buffering them and not showing in event stream console (neither Safari nor Chrome). As I've learned, SSE should explicitly end in '\n\n' to prevent buffering behavior! Is this expected behaviour? It wasn't obvious for me at all and I suggest this to be in the docs.

URL to code causing the issue

No response

MCVE

No response

Steps to reproduce

No response

Screenshots

No response

Logs

server logs do not contain errors, client side behavior is odd.

Litestar Version

latest

Platform


[!NOTE]
While we are open for sponsoring on GitHub Sponsors and OpenCollective, we also utilize Polar.sh to engage in pledge-based sponsorship.

Check out all issues funded or available for funding on our Polar.sh Litestar dashboard

  • If you would like to see an issue prioritized, make a pledge towards it!
  • We receive the pledge once the issue is completed & verified
  • This, along with engagement in the community, helps us know which features are a priority to our users.

Fund with Polar

JacobCoffee commented 1 year ago

I think we could document this better in https://docs.litestar.dev/latest/usage/responses.html#server-sent-event-responses and also include a link to the living standard for it (https://html.spec.whatwg.org/multipage/server-sent-events.html)

provinzkraut commented 1 year ago

I think we should consider this a bug. It's very unintuitive and can be easily fixed by appending the newline if it's not already there :shrug:

provinzkraut commented 1 year ago

Now that I think about this, it might be better if simply were to add a parameter that could configure this. Something like disable_client_buffering?

provinzkraut commented 10 months ago

@euri10 Iiuc your PR #2888 would fix this one as well, right?

euri10 commented 10 months ago

@euri10 Iiuc your PR #2888 would fix this one as well, right?

yes i think so :)