Skip to content
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

Add SecWebsocketExtensions #88

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

kazk
Copy link

@kazk kazk commented Sep 13, 2021

I'm working on seanmonstar/warp#770 and noticed this is missing.

Copy link
Member

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

Does this type by itself provide any use? I imagine you need to do more with it than simply materialize an opaque value from the map.

@kazk

This comment has been minimized.

@kazk kazk force-pushed the sec-websocket-extensions branch 3 times, most recently from b60896b to ff67b0b Compare September 17, 2021 06:37
@kazk kazk marked this pull request as draft September 17, 2021 06:51
@kazk kazk force-pushed the sec-websocket-extensions branch 5 times, most recently from c6ee5f0 to 16e387a Compare September 17, 2021 07:55
@kazk kazk marked this pull request as ready for review September 17, 2021 07:59
Copy link
Member

@seanmonstar seanmonstar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, this is a lot of work, thanks for putting so much thought into this!

/// [RFC6455_11.3.2]: https://tools.ietf.org/html/rfc6455#section-11.3.2
/// [RFC7692_7]: https://tools.ietf.org/html/rfc7692#section-7
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct SecWebsocketExtensions(pub Vec<WebsocketExtension>);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should keep the fields private, so we can change the internal implementation whenever desired.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I explained the reason behind this in #88 (comment)


/// A WebSocket extension containing the name and parameters.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WebsocketExtension {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just a thought, let me know what you think. What if this type simply held a reference, instead of individual owned value strings and a vector of params? The name and params methods could return "lazy" values, as a few of the other headers in this crate already do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually had struct SecWebsocketExtensions(HeaderValueString); with lazy iter() originally. But I wanted decode to fail on values with invalid syntax, so typed_try_get can be used to detect them. This requires parsing the values, so I thought it was better to store the result.

The main reason this can be useful is, when negotiating extensions, values with invalid syntax must be rejected:

If a value is received by either the client or the server during negotiation that does not conform to the ABNF below, the recipient of such malformed data MUST immediately Fail the WebSocket Connection.

https://datatracker.ietf.org/doc/html/rfc6455#section-9.1

If we validate the syntax in decode, crates using headers can focus on the parameters for each extension, and warp can reject the invalid headers, etc..


Also, having WebsocketExtension independent is useful because the server needs to filter them, and respond with potentially mutated versions (e.g., parameter ("client_max_window_bits", Some("10")) may be changed to have value Some("9") in the response). WebsocketExtension can provide setters/builder that makes sure that the value won't result in invalid syntax.

This is why I made the field and the struct public, but I can try to come up with something else if this is an issue.


/// An iterator over the `WebsocketExtension`s in `SecWebsocketExtensions` header(s).
pub fn iter(&self) -> impl Iterator<Item = &WebsocketExtension> {
self.0.iter()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar question here, what if instead of owning a Vec, the return iterator were lazy, and did the parsing as requested on each call to next, like other headers?

@kazk kazk force-pushed the sec-websocket-extensions branch 2 times, most recently from 50ae3d2 to f6fb712 Compare September 17, 2021 23:10
@kazk kazk marked this pull request as draft March 14, 2022 06:07
@ilammy
Copy link

ilammy commented Oct 17, 2022

I'd like to take over pushing permessage-deflate through the WebSockets stack.

Which review points have to be addressed in order to get this PR merged?

@kazk
Copy link
Author

kazk commented Oct 17, 2022

@ilammy I was waiting on a response from @seanmonstar for #88 (comment).

Once this is merged, I already have a branch using it, which is a rebased version of my original tungstenite-rs PR.

@gallowsmaker
Copy link

@kazk @seanmonstar I'm humble ask to return to review this PR as dependent functionality in tungstenite-rs extremely important for my team, but in same time we have strict policy don't use libraries from branches, so we have to wait for finalized published version.

@kazk
Copy link
Author

kazk commented Jan 6, 2023

@gallowsmaker I can't do anything for this PR, but I'll open a new PR for tungstenite-rs so we can start reviewing the new version while we wait for this. It will also clarify what needs to be done. Looks like I need to rebase again and there are some conflicts, but I should be able to open it soon.

I've been using the original version in production without any issues, but I'd love to get these merged and move on.

@nicknotfun
Copy link

@seanmonstar just checking if you're still able to review this?

@nakedible-p
Copy link

It would be super nice to get this merged - any hope for this to progress?

@zy010101

This comment was marked as spam.

@ilammy
Copy link

ilammy commented Nov 13, 2023

@seanmonstar @kazk bump. What's the blocker here? What help do you need?

@xxaier

This comment was marked as spam.

@AdrianEddy

This comment was marked as spam.

xxaier added a commit to xxaier/headers that referenced this pull request Nov 22, 2023
I need use SecWebsocketExtensions 
 hyperium#88 , but it not merge, pub util so I can copy the file to my project without merge it into headers , the file need util is public
@xxaier xxaier mentioned this pull request Nov 22, 2023
@kaszperro
Copy link

This PR is highly needed feature. It is blocker for us for using permessage-deflate. What can I do, to speedup merging of this?

@ddimaria
Copy link

ddimaria commented Feb 1, 2024

@seanmonstar are there any plans for this to be merged, or do you require any changes to be made? Getting this merged unblocks a PR in tungstenite that provides permessage-deflate support for websockets.

@AdrianEddy
Copy link

@seanmonstar What would it take to get this merged? I'm willing to sponsor this work

@seanmonstar
Copy link
Member

I know there's a lot of interest here. I've describe this a few times in chat, but never here. So, let me try:

  • This crate tries to expose built-in header types which expose as little internal details as possible. The reason for that is to try to limit mistakes that occurred when this was hyper::header in older versions, and changes to the exposed internals would mean breaking changes.
  • It's not clear whether SecWebsocketExtensions should be optimized for parsing, or for mutating.
    • That changes whether it should internally hold onto a flattened string, and parse on the fly of fn iter() -> impl Iterator, or if it should store everything parsed at construction in a list.
    • Unfortunately, that internal decision seems like it will leak, since the iterator would either provide WebsocketExtension<'a>s referring to the flat string, or &WebsocketExtension if an owned item inside a list.
    • Most asking for this feature are more interested in it just working (understandably), than the maintenance details afterwards.
  • This doesn't need to block people. This is the most important thing that is missed. Since the crate is based on a trait Header, any other code is able to declare its own typed header and impl Header for MySecWebSocketExtensions.
    • That code can start in tungstenite, or wherever else that's wanting this, and the design and performance of the type can be tested and tweaked there.
    • Once those questions are answered and tested, we can merge something here for longer term maintenance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.