1 //! URI component of request and response lines
2 //!
3 //! This module primarily contains the `Uri` type which is a component of all
4 //! HTTP requests and also reexports this type at the root of the crate. A URI
5 //! is not always a "full URL" in the sense of something you'd type into a web
6 //! browser, but HTTP requests may only have paths on servers but may have full
7 //! schemes and hostnames on clients.
8 //!
9 //! # Examples
10 //!
11 //! ```
12 //! use http::Uri;
13 //!
14 //! let uri = "/foo/bar?baz".parse::<Uri>().unwrap();
15 //! assert_eq!(uri.path(), "/foo/bar");
16 //! assert_eq!(uri.query(), Some("baz"));
17 //! assert_eq!(uri.host(), None);
18 //!
19 //! let uri = "https://www.rust-lang.org/install.html".parse::<Uri>().unwrap();
20 //! assert_eq!(uri.scheme_str(), Some("https"));
21 //! assert_eq!(uri.host(), Some("www.rust-lang.org"));
22 //! assert_eq!(uri.path(), "/install.html");
23 //! ```
24
25 use crate::byte_str::ByteStr;
26 use std::convert::TryFrom;
27
28 use bytes::Bytes;
29
30 use std::error::Error;
31 use std::hash::{Hash, Hasher};
32 use std::str::{self, FromStr};
33 use std::{fmt, u16, u8};
34
35 use self::scheme::Scheme2;
36
37 pub use self::authority::Authority;
38 pub use self::builder::Builder;
39 pub use self::path::PathAndQuery;
40 pub use self::port::Port;
41 pub use self::scheme::Scheme;
42
43 mod authority;
44 mod builder;
45 mod path;
46 mod port;
47 mod scheme;
48 #[cfg(test)]
49 mod tests;
50
51 /// The URI component of a request.
52 ///
53 /// For HTTP 1, this is included as part of the request line. From Section 5.3,
54 /// Request Target:
55 ///
56 /// > Once an inbound connection is obtained, the client sends an HTTP
57 /// > request message (Section 3) with a request-target derived from the
58 /// > target URI. There are four distinct formats for the request-target,
59 /// > depending on both the method being requested and whether the request
60 /// > is to a proxy.
61 /// >
62 /// > ```notrust
63 /// > request-target = origin-form
64 /// > / absolute-form
65 /// > / authority-form
66 /// > / asterisk-form
67 /// > ```
68 ///
69 /// The URI is structured as follows:
70 ///
71 /// ```notrust
72 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
73 /// |-| |-------------------------------||--------| |-------------------| |-----|
74 /// | | | | |
75 /// scheme authority path query fragment
76 /// ```
77 ///
78 /// For HTTP 2.0, the URI is encoded using pseudoheaders.
79 ///
80 /// # Examples
81 ///
82 /// ```
83 /// use http::Uri;
84 ///
85 /// let uri = "/foo/bar?baz".parse::<Uri>().unwrap();
86 /// assert_eq!(uri.path(), "/foo/bar");
87 /// assert_eq!(uri.query(), Some("baz"));
88 /// assert_eq!(uri.host(), None);
89 ///
90 /// let uri = "https://www.rust-lang.org/install.html".parse::<Uri>().unwrap();
91 /// assert_eq!(uri.scheme_str(), Some("https"));
92 /// assert_eq!(uri.host(), Some("www.rust-lang.org"));
93 /// assert_eq!(uri.path(), "/install.html");
94 /// ```
95 #[derive(Clone)]
96 pub struct Uri {
97 scheme: Scheme,
98 authority: Authority,
99 path_and_query: PathAndQuery,
100 }
101
102 /// The various parts of a URI.
103 ///
104 /// This struct is used to provide to and retrieve from a URI.
105 #[derive(Debug, Default)]
106 pub struct Parts {
107 /// The scheme component of a URI
108 pub scheme: Option<Scheme>,
109
110 /// The authority component of a URI
111 pub authority: Option<Authority>,
112
113 /// The origin-form component of a URI
114 pub path_and_query: Option<PathAndQuery>,
115
116 /// Allow extending in the future
117 _priv: (),
118 }
119
120 /// An error resulting from a failed attempt to construct a URI.
121 #[derive(Debug)]
122 pub struct InvalidUri(ErrorKind);
123
124 /// An error resulting from a failed attempt to construct a URI.
125 #[derive(Debug)]
126 pub struct InvalidUriParts(InvalidUri);
127
128 #[derive(Debug, Eq, PartialEq)]
129 enum ErrorKind {
130 InvalidUriChar,
131 InvalidScheme,
132 InvalidAuthority,
133 InvalidPort,
134 InvalidFormat,
135 SchemeMissing,
136 AuthorityMissing,
137 PathAndQueryMissing,
138 TooLong,
139 Empty,
140 SchemeTooLong,
141 }
142
143 // u16::MAX is reserved for None
144 const MAX_LEN: usize = (u16::MAX - 1) as usize;
145
146 // URI_CHARS is a table of valid characters in a URI. An entry in the table is
147 // 0 for invalid characters. For valid characters the entry is itself (i.e.
148 // the entry for 33 is b'!' because b'!' == 33u8). An important characteristic
149 // of this table is that all entries above 127 are invalid. This makes all of the
150 // valid entries a valid single-byte UTF-8 code point. This means that a slice
151 // of such valid entries is valid UTF-8.
152 const URI_CHARS: [u8; 256] = [
153 // 0 1 2 3 4 5 6 7 8 9
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // x
155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x
157 0, 0, 0, b'!', 0, b'#', b'$', 0, b'&', b'\'', // 3x
158 b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', b'0', b'1', // 4x
159 b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b':', b';', // 5x
160 0, b'=', 0, b'?', b'@', b'A', b'B', b'C', b'D', b'E', // 6x
161 b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', // 7x
162 b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', // 8x
163 b'Z', b'[', 0, b']', 0, b'_', 0, b'a', b'b', b'c', // 9x
164 b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', // 10x
165 b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', // 11x
166 b'x', b'y', b'z', 0, 0, 0, b'~', 0, 0, 0, // 12x
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13x
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14x
169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15x
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16x
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 17x
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 18x
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 19x
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20x
175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21x
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 22x
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 23x
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 24x
179 0, 0, 0, 0, 0, 0 // 25x
180 ];
181
182 impl Uri {
183 /// Creates a new builder-style object to manufacture a `Uri`.
184 ///
185 /// This method returns an instance of `Builder` which can be usd to
186 /// create a `Uri`.
187 ///
188 /// # Examples
189 ///
190 /// ```
191 /// use http::Uri;
192 ///
193 /// let uri = Uri::builder()
194 /// .scheme("https")
195 /// .authority("hyper.rs")
196 /// .path_and_query("/")
197 /// .build()
198 /// .unwrap();
199 /// ```
builder() -> Builder200 pub fn builder() -> Builder {
201 Builder::new()
202 }
203
204 /// Attempt to convert a `Uri` from `Parts`
from_parts(src: Parts) -> Result<Uri, InvalidUriParts>205 pub fn from_parts(src: Parts) -> Result<Uri, InvalidUriParts> {
206 if src.scheme.is_some() {
207 if src.authority.is_none() {
208 return Err(ErrorKind::AuthorityMissing.into());
209 }
210
211 if src.path_and_query.is_none() {
212 return Err(ErrorKind::PathAndQueryMissing.into());
213 }
214 } else {
215 if src.authority.is_some() && src.path_and_query.is_some() {
216 return Err(ErrorKind::SchemeMissing.into());
217 }
218 }
219
220 let scheme = match src.scheme {
221 Some(scheme) => scheme,
222 None => Scheme {
223 inner: Scheme2::None,
224 },
225 };
226
227 let authority = match src.authority {
228 Some(authority) => authority,
229 None => Authority::empty(),
230 };
231
232 let path_and_query = match src.path_and_query {
233 Some(path_and_query) => path_and_query,
234 None => PathAndQuery::empty(),
235 };
236
237 Ok(Uri {
238 scheme: scheme,
239 authority: authority,
240 path_and_query: path_and_query,
241 })
242 }
243
244 /// Attempt to convert a `Bytes` buffer to a `Uri`.
245 ///
246 /// This will try to prevent a copy if the type passed is the type used
247 /// internally, and will copy the data if it is not.
from_maybe_shared<T>(src: T) -> Result<Self, InvalidUri> where T: AsRef<[u8]> + 'static,248 pub fn from_maybe_shared<T>(src: T) -> Result<Self, InvalidUri>
249 where
250 T: AsRef<[u8]> + 'static,
251 {
252 if_downcast_into!(T, Bytes, src, {
253 return Uri::from_shared(src);
254 });
255
256 Uri::try_from(src.as_ref())
257 }
258
259 // Not public while `bytes` is unstable.
from_shared(s: Bytes) -> Result<Uri, InvalidUri>260 fn from_shared(s: Bytes) -> Result<Uri, InvalidUri> {
261 use self::ErrorKind::*;
262
263 if s.len() > MAX_LEN {
264 return Err(TooLong.into());
265 }
266
267 match s.len() {
268 0 => {
269 return Err(Empty.into());
270 }
271 1 => match s[0] {
272 b'/' => {
273 return Ok(Uri {
274 scheme: Scheme::empty(),
275 authority: Authority::empty(),
276 path_and_query: PathAndQuery::slash(),
277 });
278 }
279 b'*' => {
280 return Ok(Uri {
281 scheme: Scheme::empty(),
282 authority: Authority::empty(),
283 path_and_query: PathAndQuery::star(),
284 });
285 }
286 _ => {
287 let authority = Authority::from_shared(s)?;
288
289 return Ok(Uri {
290 scheme: Scheme::empty(),
291 authority: authority,
292 path_and_query: PathAndQuery::empty(),
293 });
294 }
295 },
296 _ => {}
297 }
298
299 if s[0] == b'/' {
300 return Ok(Uri {
301 scheme: Scheme::empty(),
302 authority: Authority::empty(),
303 path_and_query: PathAndQuery::from_shared(s)?,
304 });
305 }
306
307 parse_full(s)
308 }
309
310 /// Convert a `Uri` from a static string.
311 ///
312 /// This function will not perform any copying, however the string is
313 /// checked to ensure that it is valid.
314 ///
315 /// # Panics
316 ///
317 /// This function panics if the argument is an invalid URI.
318 ///
319 /// # Examples
320 ///
321 /// ```
322 /// # use http::uri::Uri;
323 /// let uri = Uri::from_static("http://example.com/foo");
324 ///
325 /// assert_eq!(uri.host().unwrap(), "example.com");
326 /// assert_eq!(uri.path(), "/foo");
327 /// ```
from_static(src: &'static str) -> Self328 pub fn from_static(src: &'static str) -> Self {
329 let s = Bytes::from_static(src.as_bytes());
330 match Uri::from_shared(s) {
331 Ok(uri) => uri,
332 Err(e) => panic!("static str is not valid URI: {}", e),
333 }
334 }
335
336 /// Convert a `Uri` into `Parts`.
337 ///
338 /// # Note
339 ///
340 /// This is just an inherent method providing the same functionality as
341 /// `let parts: Parts = uri.into()`
342 ///
343 /// # Examples
344 ///
345 /// ```
346 /// # use http::uri::*;
347 /// let uri: Uri = "/foo".parse().unwrap();
348 ///
349 /// let parts = uri.into_parts();
350 ///
351 /// assert_eq!(parts.path_and_query.unwrap(), "/foo");
352 ///
353 /// assert!(parts.scheme.is_none());
354 /// assert!(parts.authority.is_none());
355 /// ```
356 #[inline]
into_parts(self) -> Parts357 pub fn into_parts(self) -> Parts {
358 self.into()
359 }
360
361 /// Returns the path & query components of the Uri
362 #[inline]
path_and_query(&self) -> Option<&PathAndQuery>363 pub fn path_and_query(&self) -> Option<&PathAndQuery> {
364 if !self.scheme.inner.is_none() || self.authority.data.is_empty() {
365 Some(&self.path_and_query)
366 } else {
367 None
368 }
369 }
370
371 /// Get the path of this `Uri`.
372 ///
373 /// Both relative and absolute URIs contain a path component, though it
374 /// might be the empty string. The path component is **case sensitive**.
375 ///
376 /// ```notrust
377 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
378 /// |--------|
379 /// |
380 /// path
381 /// ```
382 ///
383 /// If the URI is `*` then the path component is equal to `*`.
384 ///
385 /// # Examples
386 ///
387 /// A relative URI
388 ///
389 /// ```
390 /// # use http::Uri;
391 ///
392 /// let uri: Uri = "/hello/world".parse().unwrap();
393 ///
394 /// assert_eq!(uri.path(), "/hello/world");
395 /// ```
396 ///
397 /// An absolute URI
398 ///
399 /// ```
400 /// # use http::Uri;
401 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
402 ///
403 /// assert_eq!(uri.path(), "/hello/world");
404 /// ```
405 #[inline]
path(&self) -> &str406 pub fn path(&self) -> &str {
407 if self.has_path() {
408 self.path_and_query.path()
409 } else {
410 ""
411 }
412 }
413
414 /// Get the scheme of this `Uri`.
415 ///
416 /// The URI scheme refers to a specification for assigning identifiers
417 /// within that scheme. Only absolute URIs contain a scheme component, but
418 /// not all absolute URIs will contain a scheme component. Although scheme
419 /// names are case-insensitive, the canonical form is lowercase.
420 ///
421 /// ```notrust
422 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
423 /// |-|
424 /// |
425 /// scheme
426 /// ```
427 ///
428 /// # Examples
429 ///
430 /// Absolute URI
431 ///
432 /// ```
433 /// use http::uri::{Scheme, Uri};
434 ///
435 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
436 ///
437 /// assert_eq!(uri.scheme(), Some(&Scheme::HTTP));
438 /// ```
439 ///
440 ///
441 /// Relative URI
442 ///
443 /// ```
444 /// # use http::Uri;
445 /// let uri: Uri = "/hello/world".parse().unwrap();
446 ///
447 /// assert!(uri.scheme().is_none());
448 /// ```
449 #[inline]
scheme(&self) -> Option<&Scheme>450 pub fn scheme(&self) -> Option<&Scheme> {
451 if self.scheme.inner.is_none() {
452 None
453 } else {
454 Some(&self.scheme)
455 }
456 }
457
458 /// Get the scheme of this `Uri` as a `&str`.
459 ///
460 /// # Example
461 ///
462 /// ```
463 /// # use http::Uri;
464 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
465 ///
466 /// assert_eq!(uri.scheme_str(), Some("http"));
467 /// ```
468 #[inline]
scheme_str(&self) -> Option<&str>469 pub fn scheme_str(&self) -> Option<&str> {
470 if self.scheme.inner.is_none() {
471 None
472 } else {
473 Some(self.scheme.as_str())
474 }
475 }
476
477 /// Get the authority of this `Uri`.
478 ///
479 /// The authority is a hierarchical element for naming authority such that
480 /// the remainder of the URI is delegated to that authority. For HTTP, the
481 /// authority consists of the host and port. The host portion of the
482 /// authority is **case-insensitive**.
483 ///
484 /// The authority also includes a `username:password` component, however
485 /// the use of this is deprecated and should be avoided.
486 ///
487 /// ```notrust
488 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
489 /// |-------------------------------|
490 /// |
491 /// authority
492 /// ```
493 ///
494 /// This function will be renamed to `authority` in the next semver release.
495 ///
496 /// # Examples
497 ///
498 /// Absolute URI
499 ///
500 /// ```
501 /// # use http::Uri;
502 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
503 ///
504 /// assert_eq!(uri.authority().map(|a| a.as_str()), Some("example.org:80"));
505 /// ```
506 ///
507 ///
508 /// Relative URI
509 ///
510 /// ```
511 /// # use http::Uri;
512 /// let uri: Uri = "/hello/world".parse().unwrap();
513 ///
514 /// assert!(uri.authority().is_none());
515 /// ```
516 #[inline]
authority(&self) -> Option<&Authority>517 pub fn authority(&self) -> Option<&Authority> {
518 if self.authority.data.is_empty() {
519 None
520 } else {
521 Some(&self.authority)
522 }
523 }
524
525 /// Get the host of this `Uri`.
526 ///
527 /// The host subcomponent of authority is identified by an IP literal
528 /// encapsulated within square brackets, an IPv4 address in dotted- decimal
529 /// form, or a registered name. The host subcomponent is **case-insensitive**.
530 ///
531 /// ```notrust
532 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
533 /// |---------|
534 /// |
535 /// host
536 /// ```
537 ///
538 /// # Examples
539 ///
540 /// Absolute URI
541 ///
542 /// ```
543 /// # use http::Uri;
544 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
545 ///
546 /// assert_eq!(uri.host(), Some("example.org"));
547 /// ```
548 ///
549 ///
550 /// Relative URI
551 ///
552 /// ```
553 /// # use http::Uri;
554 /// let uri: Uri = "/hello/world".parse().unwrap();
555 ///
556 /// assert!(uri.host().is_none());
557 /// ```
558 #[inline]
host(&self) -> Option<&str>559 pub fn host(&self) -> Option<&str> {
560 self.authority().map(|a| a.host())
561 }
562
563 /// Get the port part of this `Uri`.
564 ///
565 /// The port subcomponent of authority is designated by an optional port
566 /// number following the host and delimited from it by a single colon (":")
567 /// character. It can be turned into a decimal port number with the `as_u16`
568 /// method or as a `str` with the `as_str` method.
569 ///
570 /// ```notrust
571 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
572 /// |-|
573 /// |
574 /// port
575 /// ```
576 ///
577 /// # Examples
578 ///
579 /// Absolute URI with port
580 ///
581 /// ```
582 /// # use http::Uri;
583 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
584 ///
585 /// let port = uri.port().unwrap();
586 /// assert_eq!(port.as_u16(), 80);
587 /// ```
588 ///
589 /// Absolute URI without port
590 ///
591 /// ```
592 /// # use http::Uri;
593 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
594 ///
595 /// assert!(uri.port().is_none());
596 /// ```
597 ///
598 /// Relative URI
599 ///
600 /// ```
601 /// # use http::Uri;
602 /// let uri: Uri = "/hello/world".parse().unwrap();
603 ///
604 /// assert!(uri.port().is_none());
605 /// ```
port(&self) -> Option<Port<&str>>606 pub fn port(&self) -> Option<Port<&str>> {
607 self.authority().and_then(|a| a.port())
608 }
609
610 /// Get the port of this `Uri` as a `u16`.
611 ///
612 ///
613 /// # Example
614 ///
615 /// ```
616 /// # use http::{Uri, uri::Port};
617 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
618 ///
619 /// assert_eq!(uri.port_u16(), Some(80));
620 /// ```
port_u16(&self) -> Option<u16>621 pub fn port_u16(&self) -> Option<u16> {
622 self.port().and_then(|p| Some(p.as_u16()))
623 }
624
625 /// Get the query string of this `Uri`, starting after the `?`.
626 ///
627 /// The query component contains non-hierarchical data that, along with data
628 /// in the path component, serves to identify a resource within the scope of
629 /// the URI's scheme and naming authority (if any). The query component is
630 /// indicated by the first question mark ("?") character and terminated by a
631 /// number sign ("#") character or by the end of the URI.
632 ///
633 /// ```notrust
634 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
635 /// |-------------------|
636 /// |
637 /// query
638 /// ```
639 ///
640 /// # Examples
641 ///
642 /// Absolute URI
643 ///
644 /// ```
645 /// # use http::Uri;
646 /// let uri: Uri = "http://example.org/hello/world?key=value".parse().unwrap();
647 ///
648 /// assert_eq!(uri.query(), Some("key=value"));
649 /// ```
650 ///
651 /// Relative URI with a query string component
652 ///
653 /// ```
654 /// # use http::Uri;
655 /// let uri: Uri = "/hello/world?key=value&foo=bar".parse().unwrap();
656 ///
657 /// assert_eq!(uri.query(), Some("key=value&foo=bar"));
658 /// ```
659 ///
660 /// Relative URI without a query string component
661 ///
662 /// ```
663 /// # use http::Uri;
664 /// let uri: Uri = "/hello/world".parse().unwrap();
665 ///
666 /// assert!(uri.query().is_none());
667 /// ```
668 #[inline]
query(&self) -> Option<&str>669 pub fn query(&self) -> Option<&str> {
670 self.path_and_query.query()
671 }
672
has_path(&self) -> bool673 fn has_path(&self) -> bool {
674 !self.path_and_query.data.is_empty() || !self.scheme.inner.is_none()
675 }
676 }
677
678 impl<'a> TryFrom<&'a [u8]> for Uri {
679 type Error = InvalidUri;
680
681 #[inline]
try_from(t: &'a [u8]) -> Result<Self, Self::Error>682 fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
683 Uri::from_shared(Bytes::copy_from_slice(t))
684 }
685 }
686
687 impl<'a> TryFrom<&'a str> for Uri {
688 type Error = InvalidUri;
689
690 #[inline]
try_from(t: &'a str) -> Result<Self, Self::Error>691 fn try_from(t: &'a str) -> Result<Self, Self::Error> {
692 t.parse()
693 }
694 }
695
696 impl<'a> TryFrom<&'a String> for Uri {
697 type Error = InvalidUri;
698
699 #[inline]
try_from(t: &'a String) -> Result<Self, Self::Error>700 fn try_from(t: &'a String) -> Result<Self, Self::Error> {
701 t.parse()
702 }
703 }
704
705 impl TryFrom<String> for Uri {
706 type Error = InvalidUri;
707
708 #[inline]
try_from(t: String) -> Result<Self, Self::Error>709 fn try_from(t: String) -> Result<Self, Self::Error> {
710 Uri::from_shared(Bytes::from(t))
711 }
712 }
713
714 impl<'a> TryFrom<Vec<u8>> for Uri {
715 type Error = InvalidUri;
716
717 #[inline]
try_from(vec: Vec<u8>) -> Result<Self, Self::Error>718 fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
719 Uri::from_shared(Bytes::from(vec))
720 }
721 }
722
723 impl TryFrom<Parts> for Uri {
724 type Error = InvalidUriParts;
725
726 #[inline]
try_from(src: Parts) -> Result<Self, Self::Error>727 fn try_from(src: Parts) -> Result<Self, Self::Error> {
728 Uri::from_parts(src)
729 }
730 }
731
732 impl<'a> TryFrom<&'a Uri> for Uri {
733 type Error = crate::Error;
734
735 #[inline]
try_from(src: &'a Uri) -> Result<Self, Self::Error>736 fn try_from(src: &'a Uri) -> Result<Self, Self::Error> {
737 Ok(src.clone())
738 }
739 }
740
741 /// Convert a `Uri` from parts
742 ///
743 /// # Examples
744 ///
745 /// Relative URI
746 ///
747 /// ```
748 /// # use http::uri::*;
749 /// let mut parts = Parts::default();
750 /// parts.path_and_query = Some("/foo".parse().unwrap());
751 ///
752 /// let uri = Uri::from_parts(parts).unwrap();
753 ///
754 /// assert_eq!(uri.path(), "/foo");
755 ///
756 /// assert!(uri.scheme().is_none());
757 /// assert!(uri.authority().is_none());
758 /// ```
759 ///
760 /// Absolute URI
761 ///
762 /// ```
763 /// # use http::uri::*;
764 /// let mut parts = Parts::default();
765 /// parts.scheme = Some("http".parse().unwrap());
766 /// parts.authority = Some("foo.com".parse().unwrap());
767 /// parts.path_and_query = Some("/foo".parse().unwrap());
768 ///
769 /// let uri = Uri::from_parts(parts).unwrap();
770 ///
771 /// assert_eq!(uri.scheme().unwrap().as_str(), "http");
772 /// assert_eq!(uri.authority().unwrap(), "foo.com");
773 /// assert_eq!(uri.path(), "/foo");
774 /// ```
775 impl From<Uri> for Parts {
from(src: Uri) -> Self776 fn from(src: Uri) -> Self {
777 let path_and_query = if src.has_path() {
778 Some(src.path_and_query)
779 } else {
780 None
781 };
782
783 let scheme = match src.scheme.inner {
784 Scheme2::None => None,
785 _ => Some(src.scheme),
786 };
787
788 let authority = if src.authority.data.is_empty() {
789 None
790 } else {
791 Some(src.authority)
792 };
793
794 Parts {
795 scheme: scheme,
796 authority: authority,
797 path_and_query: path_and_query,
798 _priv: (),
799 }
800 }
801 }
802
parse_full(mut s: Bytes) -> Result<Uri, InvalidUri>803 fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
804 // Parse the scheme
805 let scheme = match Scheme2::parse(&s[..])? {
806 Scheme2::None => Scheme2::None,
807 Scheme2::Standard(p) => {
808 // TODO: use truncate
809 let _ = s.split_to(p.len() + 3);
810 Scheme2::Standard(p)
811 }
812 Scheme2::Other(n) => {
813 // Grab the protocol
814 let mut scheme = s.split_to(n + 3);
815
816 // Strip ://, TODO: truncate
817 let _ = scheme.split_off(n);
818
819 // Allocate the ByteStr
820 let val = unsafe { ByteStr::from_utf8_unchecked(scheme) };
821
822 Scheme2::Other(Box::new(val))
823 }
824 };
825
826 // Find the end of the authority. The scheme will already have been
827 // extracted.
828 let authority_end = Authority::parse(&s[..])?;
829
830 if scheme.is_none() {
831 if authority_end != s.len() {
832 return Err(ErrorKind::InvalidFormat.into());
833 }
834
835 let authority = Authority {
836 data: unsafe { ByteStr::from_utf8_unchecked(s) },
837 };
838
839 return Ok(Uri {
840 scheme: scheme.into(),
841 authority: authority,
842 path_and_query: PathAndQuery::empty(),
843 });
844 }
845
846 // Authority is required when absolute
847 if authority_end == 0 {
848 return Err(ErrorKind::InvalidFormat.into());
849 }
850
851 let authority = s.split_to(authority_end);
852 let authority = Authority {
853 data: unsafe { ByteStr::from_utf8_unchecked(authority) },
854 };
855
856 Ok(Uri {
857 scheme: scheme.into(),
858 authority: authority,
859 path_and_query: PathAndQuery::from_shared(s)?,
860 })
861 }
862
863 impl FromStr for Uri {
864 type Err = InvalidUri;
865
866 #[inline]
from_str(s: &str) -> Result<Uri, InvalidUri>867 fn from_str(s: &str) -> Result<Uri, InvalidUri> {
868 Uri::try_from(s.as_bytes())
869 }
870 }
871
872 impl PartialEq for Uri {
eq(&self, other: &Uri) -> bool873 fn eq(&self, other: &Uri) -> bool {
874 if self.scheme() != other.scheme() {
875 return false;
876 }
877
878 if self.authority() != other.authority() {
879 return false;
880 }
881
882 if self.path() != other.path() {
883 return false;
884 }
885
886 if self.query() != other.query() {
887 return false;
888 }
889
890 true
891 }
892 }
893
894 impl PartialEq<str> for Uri {
eq(&self, other: &str) -> bool895 fn eq(&self, other: &str) -> bool {
896 let mut other = other.as_bytes();
897 let mut absolute = false;
898
899 if let Some(scheme) = self.scheme() {
900 let scheme = scheme.as_str().as_bytes();
901 absolute = true;
902
903 if other.len() < scheme.len() + 3 {
904 return false;
905 }
906
907 if !scheme.eq_ignore_ascii_case(&other[..scheme.len()]) {
908 return false;
909 }
910
911 other = &other[scheme.len()..];
912
913 if &other[..3] != b"://" {
914 return false;
915 }
916
917 other = &other[3..];
918 }
919
920 if let Some(auth) = self.authority() {
921 let len = auth.data.len();
922 absolute = true;
923
924 if other.len() < len {
925 return false;
926 }
927
928 if !auth.data.as_bytes().eq_ignore_ascii_case(&other[..len]) {
929 return false;
930 }
931
932 other = &other[len..];
933 }
934
935 let path = self.path();
936
937 if other.len() < path.len() || path.as_bytes() != &other[..path.len()] {
938 if absolute && path == "/" {
939 // PathAndQuery can be ommitted, fall through
940 } else {
941 return false;
942 }
943 } else {
944 other = &other[path.len()..];
945 }
946
947 if let Some(query) = self.query() {
948 if other.len() == 0 {
949 return query.len() == 0;
950 }
951
952 if other[0] != b'?' {
953 return false;
954 }
955
956 other = &other[1..];
957
958 if other.len() < query.len() {
959 return false;
960 }
961
962 if query.as_bytes() != &other[..query.len()] {
963 return false;
964 }
965
966 other = &other[query.len()..];
967 }
968
969 other.is_empty() || other[0] == b'#'
970 }
971 }
972
973 impl PartialEq<Uri> for str {
eq(&self, uri: &Uri) -> bool974 fn eq(&self, uri: &Uri) -> bool {
975 uri == self
976 }
977 }
978
979 impl<'a> PartialEq<&'a str> for Uri {
eq(&self, other: &&'a str) -> bool980 fn eq(&self, other: &&'a str) -> bool {
981 self == *other
982 }
983 }
984
985 impl<'a> PartialEq<Uri> for &'a str {
eq(&self, uri: &Uri) -> bool986 fn eq(&self, uri: &Uri) -> bool {
987 uri == *self
988 }
989 }
990
991 impl Eq for Uri {}
992
993 /// Returns a `Uri` representing `/`
994 impl Default for Uri {
995 #[inline]
default() -> Uri996 fn default() -> Uri {
997 Uri {
998 scheme: Scheme::empty(),
999 authority: Authority::empty(),
1000 path_and_query: PathAndQuery::slash(),
1001 }
1002 }
1003 }
1004
1005 impl fmt::Display for Uri {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1006 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1007 if let Some(scheme) = self.scheme() {
1008 write!(f, "{}://", scheme)?;
1009 }
1010
1011 if let Some(authority) = self.authority() {
1012 write!(f, "{}", authority)?;
1013 }
1014
1015 write!(f, "{}", self.path())?;
1016
1017 if let Some(query) = self.query() {
1018 write!(f, "?{}", query)?;
1019 }
1020
1021 Ok(())
1022 }
1023 }
1024
1025 impl fmt::Debug for Uri {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1026 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1027 fmt::Display::fmt(self, f)
1028 }
1029 }
1030
1031 impl From<ErrorKind> for InvalidUri {
from(src: ErrorKind) -> InvalidUri1032 fn from(src: ErrorKind) -> InvalidUri {
1033 InvalidUri(src)
1034 }
1035 }
1036
1037 impl From<ErrorKind> for InvalidUriParts {
from(src: ErrorKind) -> InvalidUriParts1038 fn from(src: ErrorKind) -> InvalidUriParts {
1039 InvalidUriParts(src.into())
1040 }
1041 }
1042
1043 impl InvalidUri {
s(&self) -> &str1044 fn s(&self) -> &str {
1045 match self.0 {
1046 ErrorKind::InvalidUriChar => "invalid uri character",
1047 ErrorKind::InvalidScheme => "invalid scheme",
1048 ErrorKind::InvalidAuthority => "invalid authority",
1049 ErrorKind::InvalidPort => "invalid port",
1050 ErrorKind::InvalidFormat => "invalid format",
1051 ErrorKind::SchemeMissing => "scheme missing",
1052 ErrorKind::AuthorityMissing => "authority missing",
1053 ErrorKind::PathAndQueryMissing => "path missing",
1054 ErrorKind::TooLong => "uri too long",
1055 ErrorKind::Empty => "empty string",
1056 ErrorKind::SchemeTooLong => "scheme too long",
1057 }
1058 }
1059 }
1060
1061 impl fmt::Display for InvalidUri {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1062 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1063 self.s().fmt(f)
1064 }
1065 }
1066
1067 impl Error for InvalidUri {}
1068
1069 impl fmt::Display for InvalidUriParts {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1070 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1071 self.0.fmt(f)
1072 }
1073 }
1074
1075 impl Error for InvalidUriParts {}
1076
1077 impl Hash for Uri {
hash<H>(&self, state: &mut H) where H: Hasher,1078 fn hash<H>(&self, state: &mut H)
1079 where
1080 H: Hasher,
1081 {
1082 if !self.scheme.inner.is_none() {
1083 self.scheme.hash(state);
1084 state.write_u8(0xff);
1085 }
1086
1087 if let Some(auth) = self.authority() {
1088 auth.hash(state);
1089 }
1090
1091 Hash::hash_slice(self.path().as_bytes(), state);
1092
1093 if let Some(query) = self.query() {
1094 b'?'.hash(state);
1095 Hash::hash_slice(query.as_bytes(), state);
1096 }
1097 }
1098 }
1099