-
Notifications
You must be signed in to change notification settings - Fork 226
Extract hyper-independent part of rust-websocket into a separate crate. #222
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
Conversation
# Conflicts: # Cargo.toml # websocket-codec/src/codec/ws.rs
Because of it is non-last version of hyper, making it auto-deprecated. For example, Debian package suites are supposed to contain only one package per crate. If Hyper 0.10 continues to live, it should be published with some new separate name. |
I will help if you need to. |
What exactly do you want to achieve? What is your plan? |
} | ||
} | ||
|
||
pub(crate) fn towse<E>(e: E) -> WebSocketError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry but the name sux. How about using .map_err(WebSocketOtherError::from)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about how should I do error handing after splitting the crate in general. This function is basically to avoid typing .map_err(WebSocketOtherError::from)
and making lines really longer (or introducing additional lines).
Making websocket-lowlevel
's error type primary error type also for high-level websocket
is dubious, but I'm not sure how to do better: there are traits that are re-exported from websocket-lowlevel
by websocket
and those rely on lowlevel's error type.
websocket-lowlevel/src/codec/ws.rs
Outdated
use bytes::BytesMut; | ||
use tokio_codec::Decoder; | ||
use tokio_codec::Encoder; | ||
use self::bytes::BufMut; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why self::
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably some edition 2015 shenanigans.
websocket-lowlevel/src/header.rs
Outdated
pub fn new() -> WebSocketKey { | ||
let key: [u8; 16] = unsafe { | ||
// Much faster than calling random() several times | ||
mem::transmute(rand::random::<(u64, u64)>()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was only transferred from the parent crate, not invented by me.
Maybe at the time the code was written, rand
had fewer functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you expect "drive by" refactorings to be in scope for splitting pull request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I can do that in another PR, and you can rebase on master to get these changes
websocket-lowlevel/src/header.rs
Outdated
let mut array = [0u8; 20]; | ||
let mut iter = vec.into_iter(); | ||
for i in &mut array { | ||
*i = iter.next().unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
match base64::decode(accept) {
Ok(vec) => {
use std::convert::TryInto;
vec[..].try_into()
.map(WebSocketAccept)
.map_err(|_e| WebSocketError::ProtocolError(
"Sec-WebSocket-Accept must be 20 bytes",
))
}
Err(_) => Err(WebSocketError::ProtocolError(
"Invalid Sec-WebSocket-Accept ",
)),
}
The plan is mostly this:
I'm not sure about this although. |
websocket-lowlevel/src/header.rs
Outdated
/// Return the Base64 encoding of this WebSocketAccept | ||
pub fn serialize(&self) -> String { | ||
let WebSocketAccept(accept) = *self; | ||
base64::encode(&accept) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub fn serialize(&self) -> String {
base64::encode(&self.0)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code was only transferred from the parent crate, not invented by me.
websocket-lowlevel/src/codec/ws.rs
Outdated
@@ -365,6 +368,8 @@ mod tests { | |||
|
|||
#[test] | |||
fn message_codec_client_send_receive() { | |||
extern crate tokio; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import this crate only in lib.rs
with cfg test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't #[test]
imply #[cfg(test)]
?
What's wrong with non-root crate import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
/// Represents a Sec-WebSocket-Accept header | ||
#[derive(PartialEq, Clone, Copy)] | ||
pub struct WebSocketAccept([u8; 20]); | ||
pub struct WebSocketAccept(WebSocketAcceptLL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? pub use websocket_lowlevel::header::WebSocketAccept
would be enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does not implement hyper_0.10's Header
and HeaderFormat
traits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see
So looks like you want to move all core parts and create some kind of https://github.com/snapview/tungstenite-rs/tree/master/src ? |
Can it do async? How does it compare to |
I don't know, but I have just discovered it in https://github.com/seanmonstar/warp/blob/master/src/filters/ws.rs when googled how to set up hyper with websockets. |
Conflicts: src/header/accept.rs src/header/key.rs
Is this change still being considered? I'd like to update websockets to the new futures api, but doing that would conflict with this change heavily. |
Yes, I'm going to base You can look at But expect the pull request to hang around for rather long time. Maybe it would make sense to release it to crates.io with other name (like |
Is there any way I can help with getting it merged? |
Review it and state opinions:
|
I'm curious, why not just have the crate use a newer version of hyper? After reading the comments here, it seems like the motivation for the split is remaining on hyper 0.10, but no one says why. |
Hyper 0.12 is drastically different from 0.10. Also it does not support non-async at all. It may be easier to rewrite |
Note, reqwest implements both sync and async apis on top of hyper's async api's. That seems reasonable? |
You have to have an executor (futures/tokio/romio) to block on a async future. And this library is executor-free. |
hyper depends on tokio, tokio has an executor, so a sync version of websockets can be implemented on top of hyper by blocking on the tokio executor? |
@vi Are you sure? |
So, do you have any opinions? Shall |
I have said it before on tungstenite and tide, but I think what would make sense for the rust websocket ecosystem is to have a separate websocket_handshake crate that everyone can agree on. It would deal with http handshake and websocket crates could take it from when the handshake is finished. It could rely just on http crate, take in something that implements std::Read + std::Write and return that once the handshake is complete. It would deal with protocols, extensions, http2 etc. All web frameworks could depend on it for the handshake before switching to a websocket phase 2 crate, or implementing their own phase 2 API (like warp) All websocket crates could depend on it for standalone websocket server. This would reduce all of the duplicated work, as well as decrease risk of bugs and security vulnerabilities and improve interoperability. |
@hyyking , Do you have an opinion about this pull request? Shall I release it already (as |
Rust wise LGTM, I don't like the name But like said above we could split the crate even more it would make feature developping much easier (rn it's hard to differentiate what needs what). Maybe have a codec workspace for async and a true base crate with handshake/frame like said above. |
@hyyking Which names do you suggest for:
|
I believe the project should be split in 3 parts (I'm ok with helping btw)
|
Shall special effort be dedicated to prevent / minimize API breakage during the split? |
That's up to you, if we achieve the changes above it's a major release-worthy so breaking changes may occur. Current API is fine imho but maybe things will be uncovered during the split. If these changes go through we should be able to handle errors in a clearer way but that should be another release I think. |
Conflicts: src/client/builder.rs src/result.rs
rust-websocket still depends on legacy
hyper 0.10
.This may be the first step to migrate it to something else.