ring icon indicating copy to clipboard operation
ring copied to clipboard

Spec support for connection close notification

Open Ramblurr opened this issue 3 months ago • 1 comments

The Ring spec provides no mechanism for applications to be notified when a client connection is closed. This limitation is particularly relevant for long-lived streaming responses (e.g., Server-Sent Events), where the server may wish to release resources as soon as the client disconnects.

Currently the only way for the streaming server to discover the connection has been closed is to attempt a write to the output stream and catch the failure.

Some servers, such as http-kit (via its AsyncChannel) and Aleph (via manifold streams), already offer this functionality.

This issue is to open a discussion on whether and how the Ring spec could define a standard way for applications to observe the connection closure event.

Ramblurr avatar Oct 28 '25 13:10 Ramblurr

This is a reasonable addition and I think can be accomplished via an additional protocol that can be applied to the body. For instance:

(defprotocol CloseableResponseBody
  (on-client-close [body response]))

I briefly considered whether the standard Closeable interface could be used, but interfaces have the disadvantage that they can't be applied to existing classes, while protocols can. In addition, we're not necessarily closing the body, but reacting to a close event from the client.

Another possible option:

(defprotocol DisconnectableResponseBody
  (on-client-disconnect [body response]))

The response is added as an argument in case we need additional information on the response. For the StreamableResponseBody protocol this is used to access charset information. For CloseableResponseBody it could be used to access a session ID if the stream is being used for SSEs and you need to remove it from a set of broadcast receivers.

I don't think we need to pass the closed OutputStream, as an output stream can only be closed, flushed or written to - all of which are redundant once the stream is closed.

weavejester avatar Oct 29 '25 15:10 weavejester