Skip to content

Method on Authority to get the host without [] for IPv6 addresses #830

Open

Description

@gaynor-anthropic

Right now Authority::host returns the hostname, dotted-ipv4-address, or []-surrounded-ipv6 address. However, for many use cases you don't want the [] for IPv6, they're part of the URI encoding, not the IP itself. Today's use case is transforming an HTTP Uri into a rustls-pki-type's ServerName, which doesn't accept the [] version.

Activity

  1. gaynor-anthropic commented on Apr 24, 2026

    @gaynor-anthropic
    Author

    Happy to send a PR for this if there's interest (and a decent name 😬)

  2. seanmonstar commented on Apr 24, 2026

    @seanmonstar
    Member

    Yea, fair point. I've needed this before, and it currently lives split across 2 functions (what was I thinking?): https://github.com/hyperium/hyper-util/blob/e1c5a6c89bfaed11fb34bd483fe9ba616f403791/src/client/legacy/connect/http.rs#L536-L540 and https://github.com/hyperium/hyper-util/blob/e1c5a6c89bfaed11fb34bd483fe9ba616f403791/src/client/legacy/connect/dns.rs#L190-L204

    It'd almost be too beautiful if there was just TryFrom<Authority> for SocketAddr, but dealing with the port is sometimes wanted, sometimes not...

  3. gaynor-anthropic commented on Apr 24, 2026

    @gaynor-anthropic
    Author

    That TryFrom would only handle IP hosts, right? I'm assuming it wouldn't do DNS resolution for hostnames.

    Any suggestion for an appropriate method name on authority() for this?

  4. seanmonstar commented on Apr 27, 2026

    @seanmonstar
    Member

    Yea it shouldn't do a DNS resolution. As for name or where it should live, could you consider the options, determine a recommendation, and why any alternatives are less favorable?

  5. gaynor-anthropic commented on Apr 27, 2026

    @gaynor-anthropic
    Author

    Sure. Three possible choices:

    • bare_host() - It's the host() minus any adornment! This is probably the best purely because I don't like any of the other options, and it's fairly clear.
    • hostname() - this name is what Go and Python use for the same concept, but it's not obvious from first principles why hostname() and host() are different.
    • server_name() - this is what TLS connection would call this value (as seen in SNI), that said, it's got the same problem as hostname() in that it's not clear from first principles how it differs from host(). And also SNI in TLS doesn't actually allow IPs, so it imports the concept in a confusing way.
  6. seanmonstar commented on Apr 27, 2026

    @seanmonstar
    Member

    I agree, what do these methods return that is different than host()? Oh, just that it would strip the brackets? That feels too tiny to provide, in my opinion...

  7. gaynor-anthropic commented on Apr 27, 2026

    @gaynor-anthropic
    Author

    Stripping the brackets is it :-)

    The motivation is less that it's a lot of code (it's not! host.strip_prefix('[').and_then(|h| h.strip_suffix(']')).unwrap_or(host);), and more that it surfaces the concept in a way people are more likely to realize which one they need.

    The failure mode here is really "someone uses host and then silently discovers their code is wrong on IPv6".

    If that's too small to justify a new method, happy to wontfix.

  8. robjtede commented on Apr 27, 2026

    @robjtede

    I agree that this is enough of a footgun since IPv6 is far enough outside the minds of "normal" application devs; I've run into this myself at work. If not a bare_host(), then I'd advise expanded documentation that shows upfront that the uri-host component can contain bracketed IPv6/IPvFuture addresses with a strip_{prefix,suffix}() snippet to copy-paste if what you're after is something like a host or x-forwarded-host header.

  9. seanmonstar commented on Apr 27, 2026

    @seanmonstar
    Member

    To add another reference, here it is mentioned in RFC 9110 - IP-ID.

    I link that either to inform a new method or a documentation update, whatever ends up being decided.

  10. FrankTaylorLieder commented on Jul 13, 2026

    @FrankTaylorLieder

    Hi, I have just stumbled across this whilst trying to fix accessing an IPv6 service through a SOCKs proxy. I believe authority::host() should not include the square brackets in its response.

    Because the resulting host contains square brackets, the SOCKs library does not see it as an address and sends the SOCKs request over as a domain name (Address Type 0x03) which then fails name resolution.

    Are there any valid use cases for the host() method to include the brackets given that they are part of the URL encoding for IPv6 addresses, not the host itself?

    My locally applied fix is trival:

    diff --git a/src/uri/authority.rs b/src/uri/authority.rs
    index c5479cb..b99412c 100644
    --- a/src/uri/authority.rs
    +++ b/src/uri/authority.rs
    @@ -437,7 +437,7 @@ fn host(auth: &str) -> &str {
                 .find(']')
                 .expect("parsing should validate brackets");
             // ..= ranges aren't available in 1.20, our minimum Rust version...
    -        &host_port[0..i + 1]
    +        &host_port[1..i]
         } else {
             host_port
                 .split(':')
    
  11. seanmonstar commented on Jul 13, 2026

    @seanmonstar
    Member

    That could make sense, I agree. But, it could break anyone relying on the current behavior that expects the host to come back in IP-ID format. For example, to use the as a host in a different Uri.

  12. FrankTaylorLieder commented on Jul 13, 2026

    @FrankTaylorLieder

    On reflection, given the purpose of this library is to decompose URLs, it does make sense to return addresses wrapped in square brackets. The caller can deal with removing them if they want a bare IP address. The doc changes suggested above would be good to drive this point home.

    Thanks!

  13. gaynor-anthropic commented on Jul 13, 2026

    @gaynor-anthropic
    Author

    I think if we were writing a brand new http library, doing no-brackets would probably be correct. (Or return an enum that forces you to engage with the differences or something).

    But I think changing the API in the existing http library (even across a semver break) is just very fragile for consumers. Therefore I think the choices are: 1) New API (maybe some day deprecate host()? IDK), 2) change host() really fundamentally (i.e., new return type).

    Curious if this view is resonant for folks.

  14. FrankTaylorLieder commented on Jul 14, 2026

    @FrankTaylorLieder

    Maybe option 1 is best... new API which returns an enum of the different host type options and deprecating the current host() API.

    My only concern is if this is scope creep for the library. Ultimately it's goal is to provide methods to construct and parse URIs... not necessarily interpret them. When additional IP versions are added (if ever!), this library would need updating. Today it would not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions