Coverage Report

Created: 2026-06-01 06:40

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