Merge pull request #1027 from M3rs/refactor_uri
Refactor(uri): Remove usage of Url parse in Uri #1022
This commit is contained in:
96
src/uri.rs
96
src/uri.rs
@@ -1,7 +1,7 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::fmt::{Display, self};
|
use std::fmt::{Display, self};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use url::{self, Url};
|
use url::Url;
|
||||||
use url::ParseError as UrlError;
|
use url::ParseError as UrlError;
|
||||||
|
|
||||||
use Error;
|
use Error;
|
||||||
@@ -54,43 +54,38 @@ impl Uri {
|
|||||||
} else if bytes == b"/" {
|
} else if bytes == b"/" {
|
||||||
Ok(Uri::default())
|
Ok(Uri::default())
|
||||||
} else if bytes.starts_with(b"/") {
|
} else if bytes.starts_with(b"/") {
|
||||||
let mut temp = "http://example.com".to_owned();
|
|
||||||
temp.push_str(s);
|
|
||||||
let url = try!(Url::parse(&temp));
|
|
||||||
let query_len = url.query().unwrap_or("").len();
|
|
||||||
let fragment_len = url.fragment().unwrap_or("").len();
|
|
||||||
Ok(Uri {
|
Ok(Uri {
|
||||||
source: s.to_owned().into(),
|
source: s.to_owned().into(),
|
||||||
scheme_end: None,
|
scheme_end: None,
|
||||||
authority_end: None,
|
authority_end: None,
|
||||||
query: if query_len > 0 { Some(query_len) } else { None },
|
query: parse_query(s),
|
||||||
fragment: if fragment_len > 0 { Some(fragment_len) } else { None },
|
fragment: parse_fragment(s),
|
||||||
})
|
})
|
||||||
} else if s.contains("://") {
|
} else if s.contains("://") {
|
||||||
let url = try!(Url::parse(s));
|
let scheme = parse_scheme(s);
|
||||||
let query_len = url.query().unwrap_or("").len();
|
let auth = parse_authority(s);
|
||||||
let new_s = url.to_string();
|
if let Some(end) = scheme {
|
||||||
let authority_end = {
|
match &s[..end] {
|
||||||
let v: Vec<&str> = new_s.split("://").collect();
|
"ftp" | "gopher" | "http" | "https" | "ws" | "wss" => {},
|
||||||
v.last().unwrap()
|
"blob" | "file" => return Err(Error::Method),
|
||||||
.split(url.path())
|
_ => return Err(Error::Method),
|
||||||
.next()
|
}
|
||||||
.unwrap_or(&new_s)
|
match auth {
|
||||||
.len() + if v.len() == 2 { v[0].len() + 3 } else { 0 }
|
Some(a) => {
|
||||||
};
|
if (end + 3) == a {
|
||||||
let fragment_len = url.fragment().unwrap_or("").len();
|
return Err(Error::Method);
|
||||||
match url.origin() {
|
}
|
||||||
url::Origin::Opaque(_) => Err(Error::Method),
|
},
|
||||||
url::Origin::Tuple(scheme, _, _) => {
|
None => return Err(Error::Method),
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(Uri {
|
Ok(Uri {
|
||||||
source: new_s.into(),
|
source: s.to_owned().into(),
|
||||||
scheme_end: Some(scheme.len()),
|
scheme_end: scheme,
|
||||||
authority_end: if authority_end > 0 { Some(authority_end) } else { None },
|
authority_end: auth,
|
||||||
query: if query_len > 0 { Some(query_len) } else { None },
|
query: parse_query(s),
|
||||||
fragment: if fragment_len > 0 { Some(fragment_len) } else { None },
|
fragment: parse_fragment(s),
|
||||||
})
|
})
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Ok(Uri {
|
Ok(Uri {
|
||||||
source: s.to_owned().into(),
|
source: s.to_owned().into(),
|
||||||
@@ -110,6 +105,9 @@ impl Uri {
|
|||||||
let end = self.source.len() - if query_len > 0 { query_len + 1 } else { 0 } -
|
let end = self.source.len() - if query_len > 0 { query_len + 1 } else { 0 } -
|
||||||
if fragment_len > 0 { fragment_len + 1 } else { 0 };
|
if fragment_len > 0 { fragment_len + 1 } else { 0 };
|
||||||
if index >= end {
|
if index >= end {
|
||||||
|
if self.scheme().is_some() {
|
||||||
|
return "/" // absolute-form MUST have path
|
||||||
|
}
|
||||||
""
|
""
|
||||||
} else {
|
} else {
|
||||||
&self.source[index..end]
|
&self.source[index..end]
|
||||||
@@ -129,6 +127,7 @@ impl Uri {
|
|||||||
pub fn authority(&self) -> Option<&str> {
|
pub fn authority(&self) -> Option<&str> {
|
||||||
if let Some(end) = self.authority_end {
|
if let Some(end) = self.authority_end {
|
||||||
let index = self.scheme_end.map(|i| i + 3).unwrap_or(0);
|
let index = self.scheme_end.map(|i| i + 3).unwrap_or(0);
|
||||||
|
|
||||||
Some(&self.source[index..end])
|
Some(&self.source[index..end])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@@ -179,6 +178,39 @@ impl Uri {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_scheme(s: &str) -> Option<usize> {
|
||||||
|
s.find(':')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_authority(s: &str) -> Option<usize> {
|
||||||
|
let v: Vec<&str> = s.split("://").collect();
|
||||||
|
match v.last() {
|
||||||
|
Some(auth) => Some(auth.split("/")
|
||||||
|
.next()
|
||||||
|
.unwrap_or(s)
|
||||||
|
.len() + if v.len() == 2 { v[0].len() + 3 } else { 0 }),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_query(s: &str) -> Option<usize> {
|
||||||
|
match s.find('?') {
|
||||||
|
Some(i) => {
|
||||||
|
let frag_pos = s.find('#').unwrap_or(s.len());
|
||||||
|
|
||||||
|
return Some(frag_pos - i - 1);
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_fragment(s: &str) -> Option<usize> {
|
||||||
|
match s.find('#') {
|
||||||
|
Some(i) => Some(s.len() - i - 1),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl FromStr for Uri {
|
impl FromStr for Uri {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
@@ -305,7 +337,7 @@ test_parse! {
|
|||||||
"http://127.0.0.1:80",
|
"http://127.0.0.1:80",
|
||||||
|
|
||||||
scheme = Some("http"),
|
scheme = Some("http"),
|
||||||
authority = Some("127.0.0.1"),
|
authority = Some("127.0.0.1:80"),
|
||||||
path = "/",
|
path = "/",
|
||||||
query = None,
|
query = None,
|
||||||
fragment = None,
|
fragment = None,
|
||||||
@@ -316,7 +348,7 @@ test_parse! {
|
|||||||
"https://127.0.0.1:443",
|
"https://127.0.0.1:443",
|
||||||
|
|
||||||
scheme = Some("https"),
|
scheme = Some("https"),
|
||||||
authority = Some("127.0.0.1"),
|
authority = Some("127.0.0.1:443"),
|
||||||
path = "/",
|
path = "/",
|
||||||
query = None,
|
query = None,
|
||||||
fragment = None,
|
fragment = None,
|
||||||
|
|||||||
Reference in New Issue
Block a user