Просмотр исходного кода

fix typo. skip data tests for idna if feature not enabled. opt out unicode_serialziation for Origin if idna not enabled

lishuo 4 лет назад
Родитель
Сommit
a4af4a70eb
5 измененных файлов с 48 добавлено и 9 удалено
  1. 19 4
      url/src/host.rs
  2. 1 1
      url/src/lib.rs
  3. 1 4
      url/src/origin.rs
  4. 25 0
      url/tests/data.rs
  5. 2 0
      url/tests/unit.rs

+ 19 - 4
url/src/host.rs

@@ -83,10 +83,7 @@ impl Host<String> {
         }
         }
         let domain = percent_decode(input.as_bytes()).decode_utf8_lossy();
         let domain = percent_decode(input.as_bytes()).decode_utf8_lossy();
 
 
-        #[cfg(feature = "idna")]
-        let domain = idna::domain_to_ascii(&domain)?;
-        #[cfg(not(feature = "idna"))]
-        let domain = domain.to_string();
+        let domain = Self::domain_to_ascii(&domain)?;
 
 
         if domain.is_empty() {
         if domain.is_empty() {
             return Err(ParseError::EmptyHost);
             return Err(ParseError::EmptyHost);
@@ -161,6 +158,24 @@ impl Host<String> {
             ))
             ))
         }
         }
     }
     }
+
+    /// convert domain with idna
+    #[cfg(feature = "idna")]
+    fn domain_to_ascii(domain: &str) -> Result<String, ParseError> {
+        idna::domain_to_ascii(&domain).map_err(Into::into)
+    }
+
+    /// checks domain is ascii
+    #[cfg(not(feature = "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.starts_with("xn--") {
+            Ok(domain)
+        } else {
+            Err(ParseError::InvalidDomainCharacter)
+        }
+    }
 }
 }
 
 
 impl<S: AsRef<str>> fmt::Display for Host<S> {
 impl<S: AsRef<str>> fmt::Display for Host<S> {

+ 1 - 1
url/src/lib.rs

@@ -124,7 +124,7 @@ url = { version = "2", features = ["serde"] }
 You can opt out [idna](https://en.wikipedia.org/wiki/Internationalized_domain_name) support
 You can opt out [idna](https://en.wikipedia.org/wiki/Internationalized_domain_name) support
 to reduce final binary size.
 to reduce final binary size.
 
 
-```tomo
+```toml
 url = { version = "2", default-features = false }
 url = { version = "2", default-features = false }
 ```
 ```
 
 

+ 1 - 4
url/src/origin.rs

@@ -86,17 +86,14 @@ impl Origin {
     }
     }
 
 
     /// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
     /// <https://html.spec.whatwg.org/multipage/#unicode-serialisation-of-an-origin>
+    #[cfg(feature = "idna")]
     pub fn unicode_serialization(&self) -> String {
     pub fn unicode_serialization(&self) -> String {
         match *self {
         match *self {
             Origin::Opaque(_) => "null".to_owned(),
             Origin::Opaque(_) => "null".to_owned(),
             Origin::Tuple(ref scheme, ref host, port) => {
             Origin::Tuple(ref scheme, ref host, port) => {
                 let host = match *host {
                 let host = match *host {
                     Host::Domain(ref domain) => {
                     Host::Domain(ref domain) => {
-                        #[cfg(feature = "idna")]
                         let (domain, _errors) = idna::domain_to_unicode(domain);
                         let (domain, _errors) = idna::domain_to_unicode(domain);
-                        #[cfg(not(feature = "idna"))]
-                        let domain = domain.clone();
-
                         Host::Domain(domain)
                         Host::Domain(domain)
                     }
                     }
                     _ => host.clone(),
                     _ => host.clone(),

+ 25 - 0
url/tests/data.rs

@@ -16,6 +16,20 @@ use url::{quirks, Url};
 
 
 #[test]
 #[test]
 fn urltestdata() {
 fn urltestdata() {
+    #[cfg(not(feature = "idna"))]
+    let idna_skip_inputs = [
+        "http://www.foo。bar.com",
+        "http://Go.com",
+        "http://你好你好",
+        "https://faß.ExAmPlE/",
+        "http://0Xc0.0250.01",
+        "ftp://%e2%98%83",
+        "https://%e2%98%83",
+        "file://a\u{ad}b/p",
+        "file://a%C2%ADb/p",
+        "http://GOO\u{200b}\u{2060}\u{feff}goo.com",
+    ];
+
     // Copied form https://github.com/w3c/web-platform-tests/blob/master/url/
     // Copied form https://github.com/w3c/web-platform-tests/blob/master/url/
     let mut json = Value::from_str(include_str!("urltestdata.json"))
     let mut json = Value::from_str(include_str!("urltestdata.json"))
         .expect("JSON parse error in urltestdata.json");
         .expect("JSON parse error in urltestdata.json");
@@ -30,6 +44,11 @@ fn urltestdata() {
         let input = entry.take_string("input");
         let input = entry.take_string("input");
         let failure = entry.take_key("failure").is_some();
         let failure = entry.take_key("failure").is_some();
 
 
+        #[cfg(not(feature = "idna"))]
+        if idna_skip_inputs.contains(&input.as_str()) {
+            continue;
+        }
+
         let base = match Url::parse(&base) {
         let base = match Url::parse(&base) {
             Ok(base) => base,
             Ok(base) => base,
             Err(_) if failure => continue,
             Err(_) if failure => continue,
@@ -106,6 +125,12 @@ fn setters_tests() {
         let mut tests = json.take_key(attr).unwrap();
         let mut tests = json.take_key(attr).unwrap();
         for mut test in tests.as_array_mut().unwrap().drain(..) {
         for mut test in tests.as_array_mut().unwrap().drain(..) {
             let comment = test.take_key("comment").map(|s| s.string());
             let comment = test.take_key("comment").map(|s| s.string());
+            #[cfg(not(feature = "idna"))]
+            if let Some(comment) = comment.as_ref() {
+                if comment.starts_with("IDNA Nontransitional_Processing") {
+                    continue;
+                }
+            }
             let href = test.take_string("href");
             let href = test.take_string("href");
             let new_value = test.take_string("new_value");
             let new_value = test.take_string("new_value");
             let name = format!("{:?}.{} = {:?}", href, attr, new_value);
             let name = format!("{:?}.{} = {:?}", href, attr, new_value);

+ 2 - 0
url/tests/unit.rs

@@ -296,6 +296,7 @@ fn host_serialization() {
     );
     );
 }
 }
 
 
+#[cfg(feature = "idna")]
 #[test]
 #[test]
 fn test_idna() {
 fn test_idna() {
     assert!("http://goșu.ro".parse::<Url>().is_ok());
     assert!("http://goșu.ro".parse::<Url>().is_ok());
@@ -531,6 +532,7 @@ fn test_origin_opaque() {
     assert!(!&Url::parse("blob:malformed//").unwrap().origin().is_tuple())
     assert!(!&Url::parse("blob:malformed//").unwrap().origin().is_tuple())
 }
 }
 
 
+#[cfg(feature = "idna")]
 #[test]
 #[test]
 fn test_origin_unicode_serialization() {
 fn test_origin_unicode_serialization() {
     let data = [
     let data = [