-
-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
trillium-client: Add client WebSocket support #520
Conversation
cd5c702
to
9b91605
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #520 +/- ##
==========================================
+ Coverage 46.06% 48.42% +2.35%
==========================================
Files 179 180 +1
Lines 6984 7030 +46
==========================================
+ Hits 3217 3404 +187
+ Misses 3767 3626 -141 ☔ View full report in Codecov by Sentry. |
73c218a
to
c34eee7
Compare
Thanks, I like this a lot! My only hesitation: I'm unsure if this would be better as a I don't have a strong sense of which of the three options is best, but I think this and the proposed features in #449 should have consistent structure The options:
Relevant question: Would the interface be advantaged at all by being intrinsic to trillium_client::Conn? Footnotes
|
@jbr I did initially try the experiment of making this a Here's what I ran into when doing that:
If you don't mind some API bumps, I think the ideal interface looks like this:
|
c34eee7
to
8609833
Compare
@jbr I've rewritten this to live in |
@jbr I've also tested this in my project that's using |
Expressing intent: I intend to merge this. If I have minor interface iterations, would you prefer I merge and make them as subsequent PR or suggest them here? If the latter: The hunch is that the multiple calls here present unnecessary opportunities to write code that doesn't work as intended: let websocket = client
.get(url)
.with_websocket_upgrade_headers()
.await?
.into_websocket()?; In this case, the last three lines will almost always be called in sequence, and if any of them is omitted, it won't work as intended. A simpler interface might be: let websocket = client.get(url).upgrade_websocket().await?; where upgrade_websocket applies the appropriate headers with a try_insert, calls self.exec(), and then into_websocket. It might be that this should be a later improvement after there's a client::Error type that can contain the websocket error or trillium_http::Error. This might even be built in terms of the existing interface, but I'm not sure What do you think? |
@jbr wrote:
❤️ Thank you!
Up to you, but I do like being involved in the ones that affect interface design, since they might surface potential assumptions about the ways I'm expecting to use the interface.
I agree with you, and I seriously considered using this approach. In particular, I thought about having The original reason I hadn't done this was because I need the error to be recoverable, retrieving the |
@jbr Done. I removed the public function for setting the upgrade headers, because I couldn't think of a use case for needing to run code between a |
The CI failure seems unrelated. Submitted a PR that should fix it: #522 |
Add a `websocket` feature gating support for client-side WebSocket support. When set, provide methods on `trillium_client::Conn` that allow upgrading to a `WebSocketConn`. Usage: ```rust let mut ws = client .get(url) .with_websocket_upgrade_headers() .await? .into_websocket() .await?; ws.send_string(format!("Hello from a WebSocket client!")).await?; ``` Having this support natively in trillium allows reusing a connection from the connection pool when establishing a WebSocket connection (though of course the connection cannot go *back* to the pool). It also allows using any headers and base already set on the client. And finally, it allows clients to avoid some of async-tungstenite's dependencies, such as async-tls and rustls, in favor of trillium-client's dependencies.
This makes it consistent with the `trillium-websockets` crate.
Rework the error type to also handle HTTP errors, while still allowing recovery of the `Conn`. Add a test case for recovering the `Conn` from an error and using that to read an error message from the body.
e918aa7
to
c510c79
Compare
Rebased atop #522 so that CI passes now. |
@jbr Would it be possible to get a release with this change, please? |
Add a
websocket
feature gating support for client-side WebSocketsupport. When set, provide methods on
trillium_client::Conn
that allowupgrading to a
WebSocketConn
.Usage:
Having this support natively in trillium allows reusing a connection
from the connection pool when establishing a WebSocket connection
(though of course the connection cannot go back to the pool). It also
allows using any headers and base already set on the client. And
finally, it allows clients to avoid some of async-tungstenite's
dependencies, such as async-tls and rustls, in favor of
trillium-client's dependencies.