1 use std::fmt::{self, Display};
2 use std::borrow::Cow;
3 
4 use crate::ext::IntoOwned;
5 use crate::parse::{Indexed, IndexedStr};
6 use crate::uri::{as_utf8_unchecked, Error};
7 
8 /// A URI with an authority only: `user:pass@host:8000`.
9 ///
10 /// # Structure
11 ///
12 /// The following diagram illustrates the syntactic structure of an authority
13 /// URI:
14 ///
15 /// ```text
16 /// username:password@some.host:8088
17 /// |---------------| |-------| |--|
18 ///     user info        host   port
19 /// ```
20 ///
21 /// Only the host part of the URI is required.
22 #[derive(Debug, Clone)]
23 pub struct Authority<'a> {
24     source: Option<Cow<'a, str>>,
25     user_info: Option<IndexedStr<'a>>,
26     host: Host<IndexedStr<'a>>,
27     port: Option<u16>,
28 }
29 
30 #[derive(Debug, Clone)]
31 pub(crate) enum Host<T> {
32     Bracketed(T),
33     Raw(T)
34 }
35 
36 impl<T: IntoOwned> IntoOwned for Host<T> {
37     type Owned = Host<T::Owned>;
38 
into_owned(self) -> Self::Owned39     fn into_owned(self) -> Self::Owned {
40         self.map_inner(IntoOwned::into_owned)
41     }
42 }
43 
44 impl IntoOwned for Authority<'_> {
45     type Owned = Authority<'static>;
46 
into_owned(self) -> Authority<'static>47     fn into_owned(self) -> Authority<'static> {
48         Authority {
49             source: self.source.into_owned(),
50             user_info: self.user_info.into_owned(),
51             host: self.host.into_owned(),
52             port: self.port
53         }
54     }
55 }
56 
57 impl<'a> Authority<'a> {
raw( source: Cow<'a, [u8]>, user_info: Option<Indexed<'a, [u8]>>, host: Host<Indexed<'a, [u8]>>, port: Option<u16> ) -> Authority<'a>58     pub(crate) unsafe fn raw(
59         source: Cow<'a, [u8]>,
60         user_info: Option<Indexed<'a, [u8]>>,
61         host: Host<Indexed<'a, [u8]>>,
62         port: Option<u16>
63     ) -> Authority<'a> {
64         Authority {
65             source: Some(as_utf8_unchecked(source)),
66             user_info: user_info.map(|u| u.coerce()),
67             host: host.map_inner(|inner| inner.coerce()),
68             port: port
69         }
70     }
71 
72     #[cfg(test)]
new( user_info: Option<&'a str>, host: Host<&'a str>, port: Option<u16> ) -> Authority<'a>73     pub(crate) fn new(
74         user_info: Option<&'a str>,
75         host: Host<&'a str>,
76         port: Option<u16>
77     ) -> Authority<'a> {
78         Authority {
79             source: None,
80             user_info: user_info.map(|u| u.into()),
81             host: host.map_inner(|inner| inner.into()),
82             port: port
83         }
84     }
85 
86     /// Parses the string `string` into an `Authority`. Parsing will never
87     /// allocate. Returns an `Error` if `string` is not a valid authority URI.
88     ///
89     /// # Example
90     ///
91     /// ```rust
92     /// # extern crate rocket;
93     /// use rocket::http::uri::Authority;
94     ///
95     /// // Parse a valid authority URI.
96     /// let uri = Authority::parse("user:pass@host").expect("valid URI");
97     /// assert_eq!(uri.user_info(), Some("user:pass"));
98     /// assert_eq!(uri.host(), "host");
99     /// assert_eq!(uri.port(), None);
100     ///
101     /// // Invalid authority URIs fail to parse.
102     /// Authority::parse("http://google.com").expect_err("invalid authority");
103     /// ```
parse(string: &'a str) -> Result<Authority<'a>, Error<'a>>104     pub fn parse(string: &'a str) -> Result<Authority<'a>, Error<'a>> {
105         crate::parse::uri::authority_from_str(string)
106     }
107 
108     /// Returns the user info part of the authority URI, if there is one.
109     ///
110     /// # Example
111     ///
112     /// ```rust
113     /// # extern crate rocket;
114     /// use rocket::http::uri::Authority;
115     ///
116     /// let uri = Authority::parse("username:password@host").unwrap();
117     /// assert_eq!(uri.user_info(), Some("username:password"));
118     /// ```
user_info(&self) -> Option<&str>119     pub fn user_info(&self) -> Option<&str> {
120         self.user_info.as_ref().map(|u| u.from_cow_source(&self.source))
121     }
122 
123     /// Returns the host part of the authority URI.
124     ///
125     ///
126     /// If the host was provided in brackets (such as for IPv6 addresses), the
127     /// brackets will not be part of the returned string.
128     ///
129     /// # Example
130     ///
131     /// ```rust
132     /// # extern crate rocket;
133     /// use rocket::http::uri::Authority;
134     ///
135     /// let uri = Authority::parse("domain.com:123").unwrap();
136     /// assert_eq!(uri.host(), "domain.com");
137     ///
138     /// let uri = Authority::parse("username:password@host:123").unwrap();
139     /// assert_eq!(uri.host(), "host");
140     ///
141     /// let uri = Authority::parse("username:password@[1::2]:123").unwrap();
142     /// assert_eq!(uri.host(), "1::2");
143     /// ```
144     #[inline(always)]
host(&self) -> &str145     pub fn host(&self) -> &str {
146         self.host.inner().from_cow_source(&self.source)
147     }
148 
149     /// Returns the port part of the authority URI, if there is one.
150     ///
151     /// # Example
152     ///
153     /// ```rust
154     /// # extern crate rocket;
155     /// use rocket::http::uri::Authority;
156     ///
157     /// // With a port.
158     /// let uri = Authority::parse("username:password@host:123").unwrap();
159     /// assert_eq!(uri.port(), Some(123));
160     ///
161     /// let uri = Authority::parse("domain.com:8181").unwrap();
162     /// assert_eq!(uri.port(), Some(8181));
163     ///
164     /// // Without a port.
165     /// let uri = Authority::parse("username:password@host").unwrap();
166     /// assert_eq!(uri.port(), None);
167     /// ```
168     #[inline(always)]
port(&self) -> Option<u16>169     pub fn port(&self) -> Option<u16> {
170         self.port
171     }
172 }
173 
174 impl<'b> PartialEq<Authority<'b>> for Authority<'_> {
eq(&self, other: &Authority<'b>) -> bool175     fn eq(&self, other: &Authority<'b>) -> bool {
176         self.user_info() == other.user_info()
177             && self.host() == other.host()
178             && self.host.is_bracketed() == other.host.is_bracketed()
179             && self.port() == other.port()
180     }
181 }
182 
183 impl Display for Authority<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result184     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185         if let Some(user_info) = self.user_info() {
186             write!(f, "{}@", user_info)?;
187         }
188 
189         match self.host {
190             Host::Bracketed(_) => write!(f, "[{}]", self.host())?,
191             Host::Raw(_) => write!(f, "{}", self.host())?
192         }
193 
194         if let Some(port) = self.port {
195             write!(f, ":{}", port)?;
196         }
197 
198         Ok(())
199     }
200 }
201 
202 impl<T> Host<T> {
203     #[inline]
inner(&self) -> &T204     fn inner(&self) -> &T {
205         match *self {
206             Host::Bracketed(ref inner) | Host::Raw(ref inner) => inner
207         }
208     }
209 
210     #[inline]
is_bracketed(&self) -> bool211     fn is_bracketed(&self) -> bool {
212         match *self {
213             Host::Bracketed(_) => true,
214             _ => false
215         }
216     }
217 
218     #[inline]
map_inner<F, U>(self, f: F) -> Host<U> where F: FnOnce(T) -> U219     fn map_inner<F, U>(self, f: F) -> Host<U>
220         where F: FnOnce(T) -> U
221     {
222         match self {
223             Host::Bracketed(inner) => Host::Bracketed(f(inner)),
224             Host::Raw(inner) => Host::Raw(f(inner))
225         }
226     }
227 }
228