diff --git a/url/src/lib.rs b/url/src/lib.rs index cc263a79..1f13f217 100644 --- a/url/src/lib.rs +++ b/url/src/lib.rs @@ -820,7 +820,7 @@ impl Url { /// assert_eq!(url.origin(), /// Origin::Tuple("ftp".into(), /// Host::Domain("example.com".into()), - /// 21)); + /// None)); /// # Ok(()) /// # } /// # run().unwrap(); @@ -837,7 +837,7 @@ impl Url { /// assert_eq!(url.origin(), /// Origin::Tuple("https".into(), /// Host::Domain("example.com".into()), - /// 443)); + /// None)); /// # Ok(()) /// # } /// # run().unwrap(); diff --git a/url/src/origin.rs b/url/src/origin.rs index a039f452..ad7db780 100644 --- a/url/src/origin.rs +++ b/url/src/origin.rs @@ -7,16 +7,24 @@ // except according to those terms. use crate::host::Host; -use crate::parser::default_port; use crate::Url; use alloc::borrow::ToOwned; use alloc::format; use alloc::string::String; use core::sync::atomic::{AtomicUsize, Ordering}; +/// Get the origin from a URL according to the specification: +/// pub fn url_origin(url: &Url) -> Origin { let scheme = url.scheme(); match scheme { + // > "blob" + // > 1. If url’s blob URL entry is non-null, then return url’s blob URL entry’s + // > environment’s origin. + // > 2. Let pathURL be the result of parsing the result of URL path serializing url. + // > 3. If pathURL is failure, then return a new opaque origin. + // > 4. If pathURL’s scheme is "http", "https", or "file", then return pathURL’s origin. + // > 5. Return a new opaque origin. "blob" => { let result = Url::parse(url.path()); match result { @@ -24,13 +32,20 @@ pub fn url_origin(url: &Url) -> Origin { Err(_) => Origin::new_opaque(), } } + // > "ftp" "http" "https" "ws" "wss": Return the tuple origin (url’s scheme, url’s host, + // > url’s port, null). + // "ftp" | "http" | "https" | "ws" | "wss" => Origin::Tuple( scheme.to_owned(), url.host().unwrap().to_owned(), - url.port_or_known_default().unwrap(), + url.port(), ), + // > "file": Unfortunate as it is, this is left as an exercise to the reader. When in + // > doubt, return a new opaque origin. + // // TODO: Figure out what to do if the scheme is a file "file" => Origin::new_opaque(), + // > Otherwise: Return a new opaque origin. _ => Origin::new_opaque(), } } @@ -58,7 +73,7 @@ pub enum Origin { Opaque(OpaqueOrigin), /// Consists of the URL's scheme, host and port - Tuple(String, Host, u16), + Tuple(String, Host, Option), } impl Origin { @@ -78,12 +93,11 @@ impl Origin { pub fn ascii_serialization(&self) -> String { match *self { Origin::Opaque(_) => "null".to_owned(), - Origin::Tuple(ref scheme, ref host, port) => { - if default_port(scheme) == Some(port) { - format!("{}://{}", scheme, host) - } else { - format!("{}://{}:{}", scheme, host, port) - } + Origin::Tuple(ref scheme, ref host, Some(port)) => { + format!("{}://{}:{}", scheme, host, port) + } + Origin::Tuple(ref scheme, ref host, _) => { + format!("{}://{}", scheme, host) } } } @@ -100,10 +114,9 @@ impl Origin { } _ => host.clone(), }; - if default_port(scheme) == Some(port) { - format!("{}://{}", scheme, host) - } else { - format!("{}://{}:{}", scheme, host, port) + match port { + Some(port) => format!("{}://{}:{}", scheme, host, port), + None => format!("{}://{}", scheme, host), } } } diff --git a/url/tests/unit.rs b/url/tests/unit.rs index b3596610..8e797ac3 100644 --- a/url/tests/unit.rs +++ b/url/tests/unit.rs @@ -667,6 +667,31 @@ fn test_origin_unicode_serialization() { } } +#[test] +fn test_origin_default_port() { + let urls_and_expected_origin_ports = [ + ("http://example.com:80", None), + ("http://example.com", None), + ("https://example.com:443", None), + ("https://example.com", None), + ("ftp://127.0.0.1:21/", None), + ("ftp://127.0.0.1/", None), + ("http://example.com:221", Some(221)), + ("http://example.com:123", Some(123)), + ("https://example.com:442", Some(442)), + ("https://example.com:80", Some(80)), + ("ftp://127.0.0.1:20/", Some(20)), + ("ftp://127.0.0.1:80/", Some(80)), + ]; + + for (url_string, expected_port) in &urls_and_expected_origin_ports { + match Url::parse(url_string).unwrap().origin() { + Origin::Opaque(..) => unreachable!("Should not have found an opaque origin."), + Origin::Tuple(_, _, port) => assert_eq!(port, *expected_port), + } + } +} + #[test] #[cfg(feature = "std")] #[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]