warp
warp copied to clipboard
websocket `auto_ping` as parallel to sse `keep_alive`
The SSE filter has a keep_alive method that sends periodic messages to clients to persist the connection. However, the WS filter lacks similar functionality, even though it is sometimes needed and is often included (for example, in the startAutoPing method in Cluster WS, one of the more prominent WebSockets libraries in the JavaScript ecosystem).
Would it be possible to add that functionality? If so, I'm happy to help—though I took a look at the code and am not quite sure where to start, so I'd appreciate a bit of guidance.
The underlying implementation (tungstenite) supports Ping/Pong messages, but warp has created their own API which doesn't.
So either:
- the warp API is to be rewritten to have a better coverage of the websocket protocol
- you use hyper to upgrade http connections and switch to tungstenite yourself
- use a websocket library (tungstenite/ws/websocket) directly on another port
Hope it clarifies things
Thanks, that was my understanding as well.
the warp API is to be rewritten to have a better coverage of the websocket protocol
That is exactly what I am proposing. If no one objects, I can work on an initial PR that would lay the groundwork for an extension of the Warp API to allow for ping messages. I think the first step would be to give the Message struct a .ping public method, paralleling the .text and .binary methods it already exposes.
You can have a look at prior thoughts here: #257 and #258
@codesections have you started on this already? I also need either the manual way to send / receive pings and pongs or the auto_ping functionality you describe. If you haven't started working on it, I can also take a stab at implementing it.
have you started on this already?
My apologies for the delay in getting back to you on this. All I have done so far is the (very small) PR in #281, which would allow users to manually send Pings
@codesections have you started on this already? I also need either the manual way to send / receive pings and pongs or the
auto_pingfunctionality you describe. If you haven't started working on it, I can also take a stab at implementing it.
Just remember that tungstenite always responds to pings automatically as long as you keep polling the stream or sending things in the sink. You should never manually answer the pings.
Just remember that tungstenite always responds to pings automatically as long as you keep polling the stream or sending things in the sink. You should never manually answer the pings.
Right, I understand that—but the functionality I'm looking for is not about manually answering pings, it's about sending pings.
There are two general ways a client–server connection can implement a WebSocket connection with keep alive. First, the client can send pings and expect the server to answer them with pongs; Warp already supports this setup.
Second, however, the server can send pings to the client (and receive pongs in reply). Warp currently does not support that setup, and thus doesn't work with clients that expect the server to send the pings. The PR I proposed would allow Warp to work in this second scenario as well.
Thanks for working on this, this would indeed be an useful feature.
@codesections Sorry if this is a bit late, there is an open-standing bug on tungstenite considering handling of pong messages. It probably not affect you if you just send ping messages, it affects sending pong as unidirectional heartbeats. Just thought it best if people are aware of it: https://github.com/snapview/tungstenite-rs/issues/78
As an update: warp now supports creating Message::ping(data), so it is possible to construct this manually.
But I do think it'd be nice if this were just an option, similar to Ws::max_send_queue and the like. A question around implementation: would an idle checker apply only to sends, or include receives as well?
I am not sure what @codesections has in mind, but I would be happy to have a keep-alive setting that drops inactive connections. WebSocket RFC states that ping must be replied by client and server with pong and it can be sent almost at any phase.
For application level keep-alive this would mean that some kind of ping_interval could be set with inactivity_timeout which would close the connection when pongs or other data is not received within some period. Tk-http has an API example available which also includes byte-level setting. This has been working well for me earlier. Tk-http has this enabled by default.
I was able to do above keep-alive setting manually with some additional modifications to Warp and simple use of atomic variables with timers (PR https://github.com/jq-rs/arki-server/pull/5) where pings and pongs are counted and if there is too much of a difference, the connection is closed as inactive.
The commit for needed Warp changes is sent via #429 for 0.1.x
What's the status on this? I realised this was the cause of #798. I just need some way to tell warp to periodically ping clients.
+1 here, any updates, please?
Has there been any progress on this? If not, would there be any objection to me adding a ping_interval and ping_timeout, similar to the python websockets API? I'm not entirely sure where they should be set, either under some struct in this repo or under the tungstenite WebSocketConfig that this repo uses.
Hey @seanmonstar, any update on this? Would you be open to an upstream change that adds ping / pong capabilities for warp websockets? Thanks!