Skip to content

Commit

Permalink
web/url: Don't reinvent custom IP types
Browse files Browse the repository at this point in the history
The standard library IP types are sufficient and should
be used for consistency, despite the fact that the URL
spec inexplicably redefines IP addresses in a way that
is incompatible with the IP address spec
(https://datatracker.ietf.org/doc/html/rfc6943#section-3.1.1)

Instead, we only define custom parsing functions now, the public
interface only contains the standard library types
  • Loading branch information
simonwuelker committed Sep 24, 2023
1 parent 19641a8 commit 0ae24ee
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 199 deletions.
3 changes: 1 addition & 2 deletions web/http/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ impl Request {
Host::Domain(host) | Host::OpaqueHost(host) => dns::Domain::new(host.as_str())
.lookup()
.map_err(HTTPError::DNS)?,
Host::IPv4(_ip) => todo!(),
Host::IPv6(_ip) => todo!(),
Host::Ip(_ip) => todo!(),
Host::EmptyHost => todo!(),
};

Expand Down
24 changes: 12 additions & 12 deletions web/url/src/host.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::str::FromStr;
use std::net;

use sl_std::{ascii, punycode};

use crate::{
ip::{ipv4_parse, ipv6_parse},
percent_encode::{is_c0_control, percent_encode},
util, IPParseError, Ipv4Address, Ipv6Address, ValidationError, ValidationErrorHandler,
util, IPParseError, ValidationError, ValidationErrorHandler,
};

/// <https://url.spec.whatwg.org/#forbidden-host-code-point>
Expand Down Expand Up @@ -45,8 +46,7 @@ fn is_forbidden_domain_code_point(c: ascii::Char) -> bool {
#[derive(PartialEq, Clone, Debug)]
pub enum Host {
Domain(ascii::String),
IPv4(Ipv4Address),
IPv6(Ipv6Address),
Ip(net::IpAddr),
OpaqueHost(ascii::String),
EmptyHost,
}
Expand All @@ -63,13 +63,13 @@ impl ToString for Host {
// <https://url.spec.whatwg.org/#host-serializing>
fn to_string(&self) -> String {
match self {
Self::IPv4(ipv4) => {
Self::Ip(net::IpAddr::V4(ipv4)) => {
// 1. If host is an IPv4 address, return the result of running the IPv4 serializer on host.
ipv4.to_string()
},
Self::IPv6(ipv6) => {
Self::Ip(net::IpAddr::V6(ipv6)) => {
// 2. Otherwise, if host is an IPv6 address, return U+005B ([), followed by the result of running the IPv6 serializer on host, followed by U+005D (]).
format!("[{}]", ipv6.to_string())
format!("[{ipv6}]")
},
Self::Domain(host) | Self::OpaqueHost(host) => {
// 3. Otherwise, host is a domain, opaque host, or empty host, return host.
Expand Down Expand Up @@ -105,8 +105,9 @@ where

// Return the result of IPv6 parsing input with its leading U+005B ([) and trailing U+005D (]) removed.
let ipv6_text = &input[1..input.len() - 1];
let parsed_ip = Host::IPv6(Ipv6Address::from_str(ipv6_text).map_err(HostParseError::IP)?);
return Ok(parsed_ip);
let ipv6 = ipv6_parse(ipv6_text).map_err(HostParseError::IP)?;
let host = Host::Ip(net::IpAddr::V6(ipv6));
return Ok(host);
}

// If isNotSpecial is true
Expand Down Expand Up @@ -150,9 +151,8 @@ where
.is_some_and(|&c| ascii::Char::Digit0 <= c && c <= ascii::Char::Digit9)
{
// then return the result of IPv4 parsing asciiDomain.
return Ok(Host::IPv4(
Ipv4Address::from_str(input).map_err(HostParseError::IP)?,
));
let ipv4 = ipv4_parse(input).map_err(HostParseError::IP)?;
return Ok(Host::Ip(net::IpAddr::V4(ipv4)));
}

// Return asciiDomain.
Expand Down
Loading

0 comments on commit 0ae24ee

Please sign in to comment.