Skip to content

hx-sse:close does not work when there is no data #3920

Description

@aytekinar

I am using/testing HTMX v4.0.0-beta6 right now, and I have the following test file (runnable via uv):

#! /usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.14"
# dependencies = [
#     "sse-starlette~=3.0",
#     "starlette~=1.0",
#     "uvicorn[standard]~=0.51.0",
# ]
# ///
import asyncio
import collections.abc

import sse_starlette
import starlette.applications
import starlette.requests
import starlette.responses
import starlette.routing
import uvicorn

CONTENT = """
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <script src="https://cdn.jsdelivr.net/npm/htmx.org@4.0.0-beta6/dist/htmx.min.js" defer></script>
    <script src="https://cdn.jsdelivr.net/npm/htmx.org@4.0.0-beta6/dist/ext/hx-sse.min.js" defer></script>
    <title>HTMX SSE Playground</title>
  </head>
  <body>
    <output aria-live="polite" hx-sse:connect="/sse" hx-sse:close="done"></output>
  </body>
</html>
"""


async def homepage(_: starlette.requests.Request) -> starlette.responses.HTMLResponse:
    return starlette.responses.HTMLResponse(content=CONTENT)


async def sse_endpoint(
    _: starlette.requests.Request,
) -> sse_starlette.EventSourceResponse:
    async def values() -> collections.abc.AsyncIterable[sse_starlette.ServerSentEvent]:
        for idx in range(10):
            yield sse_starlette.ServerSentEvent(data=f"data {idx}")
            await asyncio.sleep(1)

        # if data=None, `hx-sse:close` does not work
        # yield sse_starlette.ServerSentEvent(event="done")
        yield sse_starlette.ServerSentEvent(event="done", data="")

    return sse_starlette.EventSourceResponse(content=values())


app = starlette.applications.Starlette(
    routes=[
        starlette.routing.Route("/sse", sse_endpoint, methods=["GET"]),
        starlette.routing.Route("/", homepage, methods=["GET"]),
    ]
)

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8080)

Currently, hx-sse:close does not close the long-running hx-sse:connect session when an event done is received with no data. Is this expected behavior? For it to work properly, I need to send an empty string.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions