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

feat: add {http1,http2}_only for auto conn #111

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

dswij
Copy link
Member

@dswij dswij commented Mar 17, 2024

Closes hyperium/hyper#3511

This PR adds an option to choose http1 or http2 only for auto connections.

@dswij dswij force-pushed the issue-3511 branch 2 times, most recently from 4669753 to b29fc46 Compare March 17, 2024 12:56
@dswij dswij marked this pull request as ready for review March 18, 2024 16:08
@dswij dswij requested a review from seanmonstar March 18, 2024 18:53
@seanmonstar
Copy link
Member

@sfackler would this solve your use case?

///
/// Does not do anything if used with [`serve_connection_with_upgrades`]
#[cfg(feature = "http2")]
pub fn http2_only(mut self) -> Self {
Copy link

Choose a reason for hiding this comment

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

What about adding a param controlling if enable http2_only or not? So that we can just write such codes(example codes from Line 1068-1075):

                    auto::Builder::new(TokioExecutor::new())
                        .http1_only(h1_only)
                        .http2_only(h2_only)
                        .serve_connection(stream, service_fn(hello))
                        .await;

instead of

                    let mut builder = auto::Builder::new(TokioExecutor::new());
                    if h1_only {
                        builder = builder.http1_only();
                    } else if h2_only {
                        builder = builder.http2_only();
                    }

                    builder.serve_connection(stream, service_fn(hello)).await;

As far as I'm concerned, the latter snippet lacks elegance.

Copy link
Member Author

Choose a reason for hiding this comment

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

You're right in terms of ergonomics, but the first example somewhat suggests that we expect the user to turn the knob for both of them.

With the second example, while not elegant, does suggest that you set only either at any given time.

Copy link

@cxw620 cxw620 Apr 3, 2024

Choose a reason for hiding this comment

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

You're right in terms of ergonomics, but the first example somewhat suggests that we expect the user to turn the knob for both of them.

With the second example, while not elegant, does suggest that you set only either at any given time.

I must admit that I agree with you about avoiding the user's mistake of setting http1_only or http2_only multiple times. After all, there are always users who don't read the documentation carefully, or mistakenly do so, whick may bring with some unintended troubles.

However, considering that hyper-util is a relatively low-level library, should we provide more flexibility to users and let themselves be responsible for not setting http1_only or http2_only multiple times? BTW, in my opinion, manual runtime panic in release mode doesn't seem quite appropriate, since it's actually not an unrecoverable error, consider using debug_assert?

Copy link

@mcmah309 mcmah309 May 8, 2024

Choose a reason for hiding this comment

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

As @tisonkun pointed out, seems like a pretty straight forward case for exposing the enum. Why introduce the possibility of an error or require conditional logic.

async fn start_server(version: Option<Version>) -> SocketAddr {
    ...
    let mut builder = auto::Builder::new(TokioExecutor::new());
    builder = match version {
        Some(version) => builder.http_version(version),
        None => builder
    };
    builder.serve_connection(stream, service_fn(hello)).await;

I don't think http_version should accept an Option though, since None is already the default. But if you do allow, then

async fn start_server(version: Option<Version>) -> SocketAddr {
    ...
     auto::Builder::new(TokioExecutor::new())
            .http_version(version)
            .serve_connection(stream, service_fn(hello))
            .await;

Copy link

@tisonkun tisonkun left a comment

Choose a reason for hiding this comment

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

Share my opinion on the style issue. In general, I'm OK with either way and let's try to move forward.

///
/// Does not do anything if used with [`serve_connection_with_upgrades`]
#[cfg(feature = "http2")]
pub fn http2_only(mut self) -> Self {
Copy link

@tisonkun tisonkun May 5, 2024

Choose a reason for hiding this comment

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

I'd instead suggest:

    pub fn http_version(mut self, v: Option<Version>) -> Self

... and expose Version struct. Otherwise, it's panicable when you call with http1_only = true and http2_only = true, or self.http1_only().http2_only(). It's hard to tell if a passed builder is already configured. version setter override the configured value, at least better than assert! not set.

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