Parcourir la source

Use opaque host parser for non-special schemes

Valentin Gosu il y a 9 ans
Parent
commit
803b8bd99e
3 fichiers modifiés avec 19 ajouts et 4 suppressions
  1. 12 1
      src/host.rs
  2. 4 0
      src/parser.rs
  3. 3 3
      tests/urltestdata.json

+ 12 - 1
src/host.rs

@@ -13,7 +13,7 @@ use std::io;
 use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
 use std::vec;
 use parser::{ParseResult, ParseError};
-use percent_encoding::percent_decode;
+use percent_encoding::{percent_decode, utf8_percent_encode, SIMPLE_ENCODE_SET};
 use idna;
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -158,6 +158,17 @@ impl Host<String> {
             Ok(Host::Domain(domain.into()))
         }
     }
+
+    // <https://url.spec.whatwg.org/#concept-opaque-host-parser>
+    pub fn parse_opaque(input: &str) -> Result<Self, ParseError> {
+        if input.find(|c| matches!(c,
+            '\0' | '\t' | '\n' | '\r' | ' ' | '#' | '/' | ':' | '?' | '@' | '[' | '\\' | ']'
+        )).is_some() {
+            return Err(ParseError::InvalidDomainCharacter)
+        }
+        let s = utf8_percent_encode(input, SIMPLE_ENCODE_SET).to_string();
+        Ok(Host::Domain(s))
+    }
 }
 
 impl<S: AsRef<str>> fmt::Display for Host<S> {

+ 4 - 0
src/parser.rs

@@ -783,6 +783,10 @@ impl<'a> Parser<'a> {
         if scheme_type.is_special() && host_str.is_empty() {
             return Err(ParseError::EmptyHost)
         }
+        if !scheme_type.is_special() {
+            let host = Host::parse_opaque(host_str)?;
+            return Ok((host, input));
+        }
         let host = Host::parse(host_str)?;
         Ok((host, input))
     }

+ 3 - 3
tests/urltestdata.json

@@ -4180,13 +4180,13 @@
   {
     "input": "sc://ñ.test/",
     "base": "about:blank",
-    "href": "sc://xn--ida.test/",
+    "href": "sc://%C3%B1.test/",
     "origin": "null",
     "protocol": "sc:",
     "username": "",
     "password": "",
-    "host": "xn--ida.test",
-    "hostname": "xn--ida.test",
+    "host": "%C3%B1.test",
+    "hostname": "%C3%B1.test",
     "port": "",
     "pathname": "/",
     "search": "",