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 feature "disable_idna" #836

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions url/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ serde = {version = "1.0", optional = true, features = ["derive"]}

[features]
default = []
# Produce smaller binaries by omitting Unicode domain support
disable_idna = []
# UNSTABLE FEATURES (requires Rust nightly)
# Enable to use the #[debugger_visualizer] attribute.
debugger_visualizer = []
Expand Down
13 changes: 13 additions & 0 deletions url/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,22 @@ impl Host<String> {
}

/// convert domain with idna
#[cfg(not(feature = "disable_idna"))]
fn domain_to_ascii(domain: &str) -> Result<String, ParseError> {
idna::domain_to_ascii(domain).map_err(Into::into)
}

/// checks domain is ascii
#[cfg(feature = "disable_idna")]
fn domain_to_ascii(domain: &str) -> Result<String, ParseError> {
// without idna feature, we can't verify that xn-- domains correctness
let domain = domain.to_lowercase();
if domain.is_ascii() && domain.split('.').all(|s| !s.starts_with("xn--")) {
Ok(domain)
} else {
Err(ParseError::InvalidDomainCharacter)
}
}
}

impl<S: AsRef<str>> fmt::Display for Host<S> {
Expand Down
3 changes: 3 additions & 0 deletions url/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -899,8 +899,11 @@ impl Url {
/// assert_eq!(url.authority(), "user:[email protected]");
/// let url = Url::parse("irc://àlex.рф.example.com:6667/foo")?;
/// assert_eq!(url.authority(), "%C3%A0lex.%D1%80%D1%84.example.com:6667");
/// # #[cfg(not(feature = "disable_idna"))]
/// # {
/// let url = Url::parse("http://àlex.рф.example.com:80/foo")?;
/// assert_eq!(url.authority(), "xn--lex-8ka.xn--p1ai.example.com");
/// # }
/// # Ok(())
/// # }
/// # run().unwrap();
Expand Down
1 change: 1 addition & 0 deletions url/src/origin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ impl Origin {
}

/// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
#[cfg(not(feature = "disable_idna"))]
pub fn unicode_serialization(&self) -> String {
match *self {
Origin::Opaque(_) => "null".to_owned(),
Expand Down
1 change: 1 addition & 0 deletions url/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ simple_enum_error! {
Overflow => "URLs more than 4 GB are not supported",
}

#[cfg(not(feature = "disable_idna"))]
impl From<::idna::Errors> for ParseError {
fn from(_: ::idna::Errors) -> ParseError {
ParseError::IdnaError
Expand Down
1 change: 1 addition & 0 deletions url/src/quirks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub fn internal_components(url: &Url) -> InternalComponents {
}

/// https://url.spec.whatwg.org/#dom-url-domaintoascii
#[cfg(not(feature = "disable_idna"))]
pub fn domain_to_ascii(domain: &str) -> String {
match Host::parse(domain) {
Ok(Host::Domain(domain)) => domain,
Expand Down
12 changes: 11 additions & 1 deletion url/tests/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,17 @@ fn urltestdata() {
.expect("missing base key")
.maybe_string();
let input = entry.take_string("input");
let failure = entry.take_key("failure").is_some();
let failure = {
#[cfg(not(feature = "disable_idna"))]
{
entry.take_key("failure").is_some()
}

#[cfg(feature = "disable_idna")]
{
entry.take_key("is_idna").is_some() || entry.take_key("failure").is_some()
}
};

let res = if let Some(base) = maybe_base {
let base = match Url::parse(&base) {
Expand Down
24 changes: 17 additions & 7 deletions url/tests/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ fn host_serialization() {
}

#[test]
#[cfg(not(feature = "disable_idna"))]
fn test_idna() {
assert!("http://goșu.ro".parse::<Url>().is_ok());
assert_eq!(
Expand Down Expand Up @@ -586,6 +587,7 @@ fn test_origin_opaque() {
}

#[test]
#[cfg(not(feature = "disable_idna"))]
fn test_origin_unicode_serialization() {
let data = [
("http://😅.com", "http://😅.com"),
Expand Down Expand Up @@ -758,6 +760,7 @@ fn test_set_href() {
}

#[test]
#[cfg(not(feature = "disable_idna"))]
fn test_domain_encoding_quirks() {
use url::quirks::{domain_to_ascii, domain_to_unicode};

Expand Down Expand Up @@ -811,8 +814,11 @@ fn test_windows_unc_path() {
let url = Url::from_file_path(Path::new(r"\\host\share\path\file.txt")).unwrap();
assert_eq!(url.as_str(), "file://host/share/path/file.txt");

let url = Url::from_file_path(Path::new(r"\\höst\share\path\file.txt")).unwrap();
assert_eq!(url.as_str(), "file://xn--hst-sna/share/path/file.txt");
#[cfg(not(feature = "disable_idna"))]
{
let url = Url::from_file_path(Path::new(r"\\höst\share\path\file.txt")).unwrap();
assert_eq!(url.as_str(), "file://xn--hst-sna/share/path/file.txt");
}

let url = Url::from_file_path(Path::new(r"\\192.168.0.1\share\path\file.txt")).unwrap();
assert_eq!(url.host(), Some(Host::Ipv4(Ipv4Addr::new(192, 168, 0, 1))));
Expand Down Expand Up @@ -1256,9 +1262,13 @@ fn test_authority() {
url.authority(),
"%C3%A0lex:%C3%A0lex@%C3%A0lex.%D1%80%D1%84.example.com:6667"
);
let url = Url::parse("https://àlex:àlex@àlex.рф.example.com:443/foo").unwrap();
assert_eq!(
url.authority(),
"%C3%A0lex:%C3%[email protected]"
);

#[cfg(not(feature = "disable_idna"))]
{
let url = Url::parse("https://àlex:àlex@àlex.рф.example.com:443/foo").unwrap();
assert_eq!(
url.authority(),
"%C3%A0lex:%C3%[email protected]"
);
}
}
33 changes: 22 additions & 11 deletions url/tests/urltestdata.json
Original file line number Diff line number Diff line change
Expand Up @@ -3617,7 +3617,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
"Leading and trailing C0 control or space",
{
Expand Down Expand Up @@ -3649,7 +3650,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
"Invalid unicode characters should fail... U+FDD0 is disallowed; %ef%b7%90 is U+FDD0",
{
Expand Down Expand Up @@ -3735,7 +3737,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
"URL spec forbids the following. https://www.w3.org/Bugs/Public/show_bug.cgi?id=24257",
{
Expand Down Expand Up @@ -3773,7 +3776,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
{
"input": "https://faß.ExAmPlE/",
Expand All @@ -3788,7 +3792,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
{
"input": "sc://faß.ExAmPlE/",
Expand Down Expand Up @@ -3889,7 +3894,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
"Domains with empty labels",
{
Expand Down Expand Up @@ -5325,7 +5331,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
{
"input": "https://%e2%98%83",
Expand All @@ -5340,7 +5347,8 @@
"port": "",
"pathname": "/",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
"# tests from jsdom/whatwg-url designed for code coverage",
{
Expand Down Expand Up @@ -8172,7 +8180,8 @@
"port": "",
"pathname": "/p",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
{
"input": "file://a%C2%ADb/p",
Expand All @@ -8186,7 +8195,8 @@
"port": "",
"pathname": "/p",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
"IDNA hostnames which get mapped to 'localhost'",
{
Expand All @@ -8201,7 +8211,8 @@
"port": "",
"pathname": "/usr/bin",
"search": "",
"hash": ""
"hash": "",
"is_idna": true
},
"Empty host after the domain to ASCII",
{
Expand Down