Skip to content

Ioxide engine: server-sent events over HTTP/2 and HTTP/3 never notice that the client left #932

Description

@MDA2AV

Over HTTP/2 and HTTP/3, the ioxide engine can't tell a streamed response that its client has gone, so a server-sent event source keeps producing for a closed tab. Over HTTP/1.1 this already works: Http1WriterStream.FlushAsync throws ConnectionClosedException when ioxide reports a completed flush, and EventConnection.SendAsync turns that IOException into Connected = false.

What ioxide changed

MDA2AV/ioxide#269, which was filed from this engine, is fixed in ioxide 0.16.281 by MDA2AV/ioxide#274. The HTTP/2 and HTTP/3 response writers' FlushAsync now returns ValueTask<FlushResult>. IsCompleted is true once the peer has reset or stopped the stream, or the connection is gone.

Before that, ioxide got this case wrong itself. An HTTP/2 writer parked forever waiting for flow-control credit, and an nghttp3 writer spun its reactor at 100% CPU.

What the engine needs

Http2Driver and Http3Driver write bodies through StreamedResponder.WriteBodyAsync and StreamedSink, which take a Func<ValueTask> and so never see a result. They should take Func<ValueTask<FlushResult>> and throw ConnectionClosedException on a completed flush, the same way Http1WriterStream does.

0.16.281 needs that same signature change to compile, so the code is the one already posted on #929.

Done when

An SSE client that disconnects over HTTP/2, and one over HTTP/3, each sees IEventConnection.Connected turn false and its source stop, as over HTTP/1.1.

Depends on #929 (moving to 0.16.281).

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions