• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 //! HTTP [`URI`].
15 //!
16 //! URI references are used to target requests, indicate redirects, and define
17 //! relationships.
18 //!
19 //! [`URI`]: https://httpwg.org/specs/rfc9110.html#uri.references
20 
21 use core::convert::{Infallible, TryFrom, TryInto};
22 
23 use crate::error::{ErrorKind, HttpError};
24 
25 // Maximum uri length.
26 const MAX_URI_LEN: usize = (u16::MAX - 1) as usize;
27 
28 /// HTTP [`URI`] implementation.
29 ///
30 /// The complete structure of the uri is as follows:
31 ///
32 /// ```text
33 /// | scheme://authority path ?query |
34 /// ```
35 ///
36 /// `URI` currently only supports `HTTP` and `HTTPS` schemes.
37 ///
38 /// According to [RFC9110, Section 4.2], the userinfo parameter before authority
39 /// is forbidden. Fragment information in query is not stored in uri.
40 ///
41 /// So, the `URI` shown below is illegal:
42 ///
43 /// ```text
44 /// http://username:password@example.com:80/
45 /// ```
46 ///
47 /// [`URI`]: https://httpwg.org/specs/rfc9110.html#uri.references
48 /// [RFC9110, Section 4.2]: https://httpwg.org/specs/rfc9110.html#uri.schemes
49 ///
50 /// # Examples
51 ///
52 /// ```
53 /// use ylong_http::request::uri::Uri;
54 ///
55 /// let uri = Uri::builder()
56 ///     .scheme("http")
57 ///     .authority("example.com:80")
58 ///     .path("/foo")
59 ///     .query("a=1")
60 ///     .build()
61 ///     .unwrap();
62 ///
63 /// assert_eq!(uri.scheme().unwrap().as_str(), "http");
64 /// assert_eq!(uri.host().unwrap().as_str(), "example.com");
65 /// assert_eq!(uri.port().unwrap().as_str(), "80");
66 /// assert_eq!(uri.path().unwrap().as_str(), "/foo");
67 /// assert_eq!(uri.query().unwrap().as_str(), "a=1");
68 /// assert_eq!(uri.to_string(), "http://example.com:80/foo?a=1");
69 ///
70 /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
71 /// assert_eq!(uri.to_string(), "http://example.com:80/foo?a=1");
72 /// ```
73 #[derive(Clone, Debug, Default)]
74 pub struct Uri {
75     /// The scheme can be `None` when the relative uri is used.
76     scheme: Option<Scheme>,
77 
78     /// The authority can be `None` when the relative uri is used.
79     authority: Option<Authority>,
80 
81     /// The path can be `None` when the path is "/".
82     path: Option<Path>,
83 
84     /// The query can be `None` when the query is not set.
85     query: Option<Query>,
86 }
87 
88 impl Uri {
89     /// Creates a HTTP-compliant default `Uri` with `Path` set to '/'.
http() -> Uri90     pub(crate) fn http() -> Uri {
91         Uri {
92             scheme: None,
93             authority: None,
94             path: Path::from_bytes(b"/").ok(),
95             query: None,
96         }
97     }
98 
99     /// Creates a new default [`UriBuilder`].
100     ///
101     /// [`UriBuilder`]: UriBuilder
102     ///
103     /// # Examples
104     ///
105     /// ```
106     /// use ylong_http::request::uri::Uri;
107     ///
108     /// let builder = Uri::builder();
109     /// ```
builder() -> UriBuilder110     pub fn builder() -> UriBuilder {
111         UriBuilder::new()
112     }
113 
114     /// Gets a immutable reference to `Scheme`.
115     ///
116     /// Returns `None` if there is no `Scheme`.
117     ///
118     /// # Examples
119     ///
120     /// ```
121     /// use ylong_http::request::uri::Uri;
122     ///
123     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
124     /// assert_eq!(uri.scheme().unwrap().as_str(), "http");
125     /// ```
scheme(&self) -> Option<&Scheme>126     pub fn scheme(&self) -> Option<&Scheme> {
127         self.scheme.as_ref()
128     }
129 
130     /// Gets a immutable reference to `Authority`.
131     ///
132     /// Returns `None` if there is no `Authority`.
133     ///
134     /// # Examples
135     ///
136     /// ```
137     /// use ylong_http::request::uri::Uri;
138     ///
139     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
140     /// let authority = uri.authority().unwrap();
141     /// assert_eq!(authority.host().as_str(), "example.com");
142     /// assert_eq!(authority.port().unwrap().as_str(), "80");
143     /// ```
authority(&self) -> Option<&Authority>144     pub fn authority(&self) -> Option<&Authority> {
145         self.authority.as_ref()
146     }
147 
148     /// Gets a immutable reference to `Host`.
149     ///
150     /// Returns `None` if there is no `Host`.
151     ///
152     /// # Examples
153     ///
154     /// ```
155     /// use ylong_http::request::uri::Uri;
156     ///
157     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
158     /// assert_eq!(uri.host().unwrap().as_str(), "example.com");
159     /// ```
host(&self) -> Option<&Host>160     pub fn host(&self) -> Option<&Host> {
161         self.authority.as_ref().map(|auth| auth.host())
162     }
163 
164     /// Gets a immutable reference to `Port`.
165     ///
166     /// Returns `None` if there is no `Port`.
167     ///
168     /// # Examples
169     ///
170     /// ```
171     /// use ylong_http::request::uri::Uri;
172     ///
173     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
174     /// assert_eq!(uri.port().unwrap().as_str(), "80");
175     /// ```
port(&self) -> Option<&Port>176     pub fn port(&self) -> Option<&Port> {
177         self.authority.as_ref().and_then(|auth| auth.port())
178     }
179 
180     /// Gets a immutable reference to `Path`.
181     ///
182     /// Returns `None` if there is no `Path`.
183     ///
184     /// # Examples
185     ///
186     /// ```
187     /// use ylong_http::request::uri::Uri;
188     ///
189     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
190     /// assert_eq!(uri.path().unwrap().as_str(), "/foo");
191     /// ```
path(&self) -> Option<&Path>192     pub fn path(&self) -> Option<&Path> {
193         self.path.as_ref()
194     }
195 
196     /// Gets a immutable reference to `Query`.
197     ///
198     /// Returns `None` if there is no `Query`.
199     ///
200     /// # Examples
201     ///
202     /// ```
203     /// use ylong_http::request::uri::Uri;
204     ///
205     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
206     /// assert_eq!(uri.query().unwrap().as_str(), "a=1");
207     /// ```
query(&self) -> Option<&Query>208     pub fn query(&self) -> Option<&Query> {
209         self.query.as_ref()
210     }
211 
212     /// Converts a bytes slice into a `Uri`.
213     ///
214     /// # Examples
215     ///
216     /// ```
217     /// use ylong_http::request::uri::Uri;
218     ///
219     /// let uri = Uri::from_bytes(b"/foo?a=1").unwrap();
220     /// ```
from_bytes(bytes: &[u8]) -> Result<Self, HttpError>221     pub fn from_bytes(bytes: &[u8]) -> Result<Self, HttpError> {
222         if bytes.len() > MAX_URI_LEN {
223             return Err(InvalidUri::UriTooLong.into());
224         }
225         if bytes.is_empty() {
226             return Err(InvalidUri::InvalidFormat.into());
227         }
228         let (scheme, rest) = scheme_token(bytes)?;
229         let (authority, rest) = authority_token(rest)?;
230         let (path, rest) = path_token(rest)?;
231         let query = query_token(rest)?;
232         let result = Uri {
233             scheme,
234             authority,
235             path,
236             query,
237         };
238         validity_check(result).map_err(Into::into)
239     }
240 
241     /// Gets a `String`, which contains the path and query.
242     ///
243     /// Returns `None` if path and query are both empty.
244     ///
245     /// # Examples
246     ///
247     /// ```
248     /// use ylong_http::request::uri::Uri;
249     ///
250     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
251     /// assert_eq!(uri.path_and_query().unwrap(), String::from("/foo?a=1"));
252     /// ```
path_and_query(&self) -> Option<String>253     pub fn path_and_query(&self) -> Option<String> {
254         let mut builder = String::new();
255         if let Some(path) = self.path() {
256             builder.push_str(path.as_str());
257         }
258         if let Some(query) = self.query() {
259             builder.push('?');
260             builder.push_str(query.as_str());
261         }
262         if builder.is_empty() {
263             return None;
264         }
265         Some(builder)
266     }
267 
268     /// Splits the `Uri` into its parts.
269     ///
270     /// # Examples
271     ///
272     /// ```
273     /// use ylong_http::request::uri::{Scheme, Uri};
274     ///
275     /// let uri = Uri::from_bytes(b"http://example.com:80/foo?a=1").unwrap();
276     /// let (scheme, auth, path, query) = uri.into_parts();
277     /// assert_eq!(scheme, Some(Scheme::HTTP));
278     /// assert_eq!(auth.unwrap().to_string(), String::from("example.com:80"));
279     /// assert_eq!(path.unwrap().as_str(), "/foo");
280     /// assert_eq!(query.unwrap().as_str(), "a=1");
281     /// ```
282     #[rustfmt::skip] // rust fmt check will add "," after `self`
into_parts( self ) -> ( Option<Scheme>, Option<Authority>, Option<Path>, Option<Query>, )283     pub fn into_parts(
284         self
285     ) -> (
286         Option<Scheme>,
287         Option<Authority>,
288         Option<Path>,
289         Option<Query>,
290     ) {
291         (self.scheme, self.authority, self.path, self.query)
292     }
293 }
294 
295 impl ToString for Uri {
to_string(&self) -> String296     fn to_string(&self) -> String {
297         let mut builder = String::new();
298         if let Some(scheme) = self.scheme() {
299             builder.push_str(scheme.as_str());
300             builder.push_str("://");
301         }
302         if let Some(host) = self.host() {
303             builder.push_str(host.as_str());
304         }
305         if let Some(port) = self.port() {
306             builder.push(':');
307             builder.push_str(port.as_str());
308         }
309         if let Some(path) = self.path() {
310             builder.push_str(path.as_str());
311         }
312         if let Some(query) = self.query() {
313             builder.push('?');
314             builder.push_str(query.as_str());
315         }
316         builder
317     }
318 }
319 
320 impl<'a> TryFrom<&'a [u8]> for Uri {
321     type Error = HttpError;
322 
try_from(s: &'a [u8]) -> Result<Self, Self::Error>323     fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> {
324         Self::from_bytes(s)
325     }
326 }
327 
328 impl<'a> TryFrom<&'a str> for Uri {
329     type Error = HttpError;
330 
try_from(s: &'a str) -> Result<Self, Self::Error>331     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
332         Self::from_bytes(s.as_bytes())
333     }
334 }
335 
336 /// A builder of `Uri`, which you can use it to construct a [`Uri`].
337 ///
338 /// [`Uri`]: Uri
339 ///
340 /// # Example
341 ///
342 /// ```
343 /// use ylong_http::request::uri::Uri;
344 ///
345 /// let uri = Uri::builder()
346 ///     .scheme("http")
347 ///     .authority("example.com:80")
348 ///     .path("/foo")
349 ///     .query("a=1")
350 ///     .build()
351 ///     .unwrap();
352 /// ```
353 pub struct UriBuilder {
354     unprocessed: Result<Uri, InvalidUri>,
355 }
356 
357 impl UriBuilder {
358     /// Creates a new, default `UriBuilder`.
359     ///
360     /// # Examples
361     ///
362     /// ```
363     /// use ylong_http::request::uri::UriBuilder;
364     ///
365     /// let uri = UriBuilder::new();
366     /// ```
new() -> Self367     pub fn new() -> Self {
368         UriBuilder::default()
369     }
370 
371     /// Sets the `Scheme` of `Uri`.
372     ///
373     /// # Examples
374     ///
375     /// ```
376     /// use ylong_http::request::uri::UriBuilder;
377     ///
378     /// // This method takes a generic parameter that supports multiple types.
379     /// let builder = UriBuilder::new().scheme("http");
380     /// let builder = UriBuilder::new().scheme("http".as_bytes());
381     /// ```
scheme<T>(mut self, scheme: T) -> Self where Scheme: TryFrom<T>, InvalidUri: From<<Scheme as TryFrom<T>>::Error>,382     pub fn scheme<T>(mut self, scheme: T) -> Self
383     where
384         Scheme: TryFrom<T>,
385         InvalidUri: From<<Scheme as TryFrom<T>>::Error>,
386     {
387         self.unprocessed = self.unprocessed.and_then(move |mut unprocessed| {
388             let scheme = scheme.try_into()?;
389             unprocessed.scheme = Some(scheme);
390             Ok(unprocessed)
391         });
392         self
393     }
394 
395     /// Sets the `Authority` of `Uri`.
396     ///
397     /// # Examples
398     ///
399     /// ```
400     /// use ylong_http::request::uri::UriBuilder;
401     ///
402     /// // This method takes a generic parameter that supports multiple types.
403     /// let builder = UriBuilder::new().authority("example.com:80");
404     /// let builder = UriBuilder::new().authority("example.com:80".as_bytes());
405     /// ```
authority<T>(mut self, auth: T) -> Self where Authority: TryFrom<T>, InvalidUri: From<<Authority as TryFrom<T>>::Error>,406     pub fn authority<T>(mut self, auth: T) -> Self
407     where
408         Authority: TryFrom<T>,
409         InvalidUri: From<<Authority as TryFrom<T>>::Error>,
410     {
411         self.unprocessed = self.unprocessed.and_then(move |mut unprocessed| {
412             let auth = auth.try_into()?;
413             unprocessed.authority = Some(auth);
414             Ok(unprocessed)
415         });
416         self
417     }
418 
419     /// Sets the `Path` of `Uri`.
420     ///
421     /// # Examples
422     ///
423     /// ```
424     /// use ylong_http::request::uri::UriBuilder;
425     ///
426     /// let mut builder = UriBuilder::new().path("/foo");
427     /// let mut builder = UriBuilder::new().path("/foo".as_bytes());
428     /// ```
path<T>(mut self, path: T) -> Self where Path: TryFrom<T>, InvalidUri: From<<Path as TryFrom<T>>::Error>,429     pub fn path<T>(mut self, path: T) -> Self
430     where
431         Path: TryFrom<T>,
432         InvalidUri: From<<Path as TryFrom<T>>::Error>,
433     {
434         self.unprocessed = self.unprocessed.and_then(move |mut unprocessed| {
435             let path = path.try_into()?;
436             unprocessed.path = Some(path);
437             Ok(unprocessed)
438         });
439         self
440     }
441 
442     /// Sets the `Query` of `Uri`.
443     ///
444     /// # Examples
445     ///
446     /// ```
447     /// use ylong_http::request::uri::UriBuilder;
448     ///
449     /// let builder = UriBuilder::new().query("a=1");
450     /// let builder = UriBuilder::new().query("a=1".as_bytes());
451     /// ```
query<T>(mut self, query: T) -> Self where Query: TryFrom<T>, InvalidUri: From<<Query as TryFrom<T>>::Error>,452     pub fn query<T>(mut self, query: T) -> Self
453     where
454         Query: TryFrom<T>,
455         InvalidUri: From<<Query as TryFrom<T>>::Error>,
456     {
457         self.unprocessed = self.unprocessed.and_then(move |mut unprocessed| {
458             let query = query.try_into()?;
459             unprocessed.query = Some(query);
460             Ok(unprocessed)
461         });
462         self
463     }
464 
465     /// Consumes the builder and constructs a valid `Uri`.
466     ///
467     /// # Examples
468     ///
469     /// ```
470     /// use ylong_http::request::uri::UriBuilder;
471     ///
472     /// let uri = UriBuilder::new()
473     ///     .scheme("http")
474     ///     .authority("example.com:80")
475     ///     .path("/foo")
476     ///     .query("a=1")
477     ///     .build()
478     ///     .unwrap();
479     /// ```
build(self) -> Result<Uri, HttpError>480     pub fn build(self) -> Result<Uri, HttpError> {
481         self.unprocessed
482             .and_then(validity_check)
483             .map_err(Into::into)
484     }
485 }
486 
487 impl Default for UriBuilder {
default() -> UriBuilder488     fn default() -> UriBuilder {
489         UriBuilder {
490             unprocessed: Ok(Uri {
491                 scheme: None,
492                 authority: None,
493                 path: None,
494                 query: None,
495             }),
496         }
497     }
498 }
499 
500 /// Scheme component of [`Uri`].
501 ///
502 /// [`Uri`]: Uri
503 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
504 pub struct Scheme {
505     proto: Protocol,
506 }
507 
508 impl Scheme {
509     /// HTTP protocol Scheme.
510     pub const HTTP: Scheme = Scheme {
511         proto: Protocol::Http,
512     };
513 
514     /// HTTPS protocol Scheme.
515     pub const HTTPS: Scheme = Scheme {
516         proto: Protocol::Https,
517     };
518 
519     /// Converts a byte slice into a `Scheme`.
520     ///
521     /// This method only accepts `b"http"` and `b"https"` as input.
522     ///
523     /// # Examples
524     ///
525     /// ```
526     /// use ylong_http::request::uri::Scheme;
527     ///
528     /// let scheme = Scheme::from_bytes(b"http").unwrap();
529     /// ```
from_bytes(bytes: &[u8]) -> Result<Scheme, InvalidUri>530     pub fn from_bytes(bytes: &[u8]) -> Result<Scheme, InvalidUri> {
531         if bytes.eq_ignore_ascii_case(b"http") {
532             Ok(Protocol::Http.into())
533         } else if bytes.eq_ignore_ascii_case(b"https") {
534             Ok(Protocol::Https.into())
535         } else {
536             Err(InvalidUri::InvalidScheme)
537         }
538     }
539 
540     /// Returns a string slice containing the entire `Scheme`.
541     ///
542     /// # Examples
543     ///
544     /// ```
545     /// use ylong_http::request::uri::Scheme;
546     ///
547     /// let scheme = Scheme::from_bytes(b"http").unwrap();
548     /// assert_eq!(scheme.as_str(), "http");
549     /// ```
as_str(&self) -> &str550     pub fn as_str(&self) -> &str {
551         match &self.proto {
552             Protocol::Http => "http",
553             Protocol::Https => "https",
554         }
555     }
556 }
557 
558 impl From<Protocol> for Scheme {
from(proto: Protocol) -> Self559     fn from(proto: Protocol) -> Self {
560         Scheme { proto }
561     }
562 }
563 
564 impl<'a> TryFrom<&'a [u8]> for Scheme {
565     type Error = InvalidUri;
566 
try_from(bytes: &'a [u8]) -> Result<Self, Self::Error>567     fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
568         Scheme::from_bytes(bytes)
569     }
570 }
571 
572 impl<'a> TryFrom<&'a str> for Scheme {
573     type Error = InvalidUri;
574 
try_from(s: &'a str) -> Result<Self, Self::Error>575     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
576         TryFrom::try_from(s.as_bytes())
577     }
578 }
579 
580 /// Authority component of [`Uri`].
581 ///
582 /// [`Uri`]: Uri
583 #[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
584 pub struct Authority {
585     host: Host,
586     port: Option<Port>,
587 }
588 
589 impl Authority {
590     /// Converts a byte slice into a `Authority`.
591     ///
592     /// # Examples
593     ///
594     /// ```
595     /// use ylong_http::request::uri::Authority;
596     ///
597     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
598     /// ```
from_bytes(bytes: &[u8]) -> Result<Authority, InvalidUri>599     pub fn from_bytes(bytes: &[u8]) -> Result<Authority, InvalidUri> {
600         if bytes.is_empty() {
601             return Err(InvalidUri::UriMissAuthority);
602         }
603         let (authority, rest) = authority_token(bytes)?;
604         if !rest.is_empty() || authority.is_none() {
605             return Err(InvalidUri::InvalidAuthority);
606         }
607         Ok(authority.unwrap())
608     }
609 
610     /// Gets a immutable reference to `Host`.
611     ///
612     /// # Examples
613     ///
614     /// ```
615     /// use ylong_http::request::uri::{Authority, Host};
616     ///
617     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
618     /// let host = authority.host();
619     /// assert_eq!(host.as_str(), "example.com");
620     /// ```
host(&self) -> &Host621     pub fn host(&self) -> &Host {
622         &self.host
623     }
624 
625     /// Gets a immutable reference to `Port`.
626     ///
627     /// # Examples
628     ///
629     /// ```
630     /// use ylong_http::request::uri::{Authority, Port};
631     ///
632     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
633     /// let port = authority.port().unwrap();
634     /// assert_eq!(port.as_str(), "80");
635     /// ```
port(&self) -> Option<&Port>636     pub fn port(&self) -> Option<&Port> {
637         self.port.as_ref()
638     }
639 
640     /// Returns a string containing the entire `Authority`.
641     ///
642     /// # Examples
643     ///
644     /// ```
645     /// use ylong_http::request::uri::{Authority, Port};
646     ///
647     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
648     /// assert_eq!(authority.to_str(), "example.com:80".to_string());
649     /// ```
to_str(&self) -> String650     pub fn to_str(&self) -> String {
651         let mut auth = self.host.as_str().to_string();
652         if let Some(ref p) = self.port {
653             auth.push(':');
654             auth.push_str(p.as_str());
655         };
656         auth
657     }
658 
659     /// Splits the `Authority` into its parts.
660     ///
661     /// # Examples
662     ///
663     /// ```
664     /// use ylong_http::request::uri::Authority;
665     ///
666     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
667     /// let (host, port) = authority.into_parts();
668     /// assert_eq!(host.as_str(), "example.com");
669     /// assert_eq!(port.unwrap().as_u16().unwrap(), 80);
670     /// ```
into_parts(self) -> (Host, Option<Port>)671     pub fn into_parts(self) -> (Host, Option<Port>) {
672         (self.host, self.port)
673     }
674 }
675 
676 impl<'a> TryFrom<&'a [u8]> for Authority {
677     type Error = InvalidUri;
678 
try_from(bytes: &'a [u8]) -> Result<Self, Self::Error>679     fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
680         Authority::from_bytes(bytes)
681     }
682 }
683 
684 impl<'a> TryFrom<&'a str> for Authority {
685     type Error = InvalidUri;
686 
try_from(s: &'a str) -> Result<Self, Self::Error>687     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
688         TryFrom::try_from(s.as_bytes())
689     }
690 }
691 
692 impl ToString for Authority {
to_string(&self) -> String693     fn to_string(&self) -> String {
694         let mut builder = String::new();
695         builder.push_str(self.host().as_str());
696         if let Some(port) = self.port() {
697             builder.push(':');
698             builder.push_str(port.as_str());
699         }
700         builder
701     }
702 }
703 
704 /// Host part of [`Authority`].
705 ///
706 /// [`Authority`]: Authority
707 #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
708 pub struct Host(String);
709 
710 impl Host {
711     /// Returns a string slice containing the entire `Host`.
712     ///
713     /// # Examples
714     ///
715     /// ```
716     /// use ylong_http::request::uri::Authority;
717     ///
718     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
719     /// let host = authority.host();
720     /// assert_eq!(host.as_str(), "example.com");
721     /// ```
as_str(&self) -> &str722     pub fn as_str(&self) -> &str {
723         self.0.as_str()
724     }
725 }
726 
727 impl ToString for Host {
to_string(&self) -> String728     fn to_string(&self) -> String {
729         self.0.to_owned()
730     }
731 }
732 
733 /// Port part of [`Authority`].
734 ///
735 /// [`Authority`]: Authority
736 #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
737 pub struct Port(String);
738 
739 impl Port {
740     /// Returns a string slice containing the entire `Port`.
741     ///
742     /// # Examples
743     ///
744     /// ```
745     /// use ylong_http::request::uri::{Authority, Port};
746     ///
747     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
748     /// let port = authority.port().unwrap();
749     /// assert_eq!(port.as_str(), "80");
750     /// ```
as_str(&self) -> &str751     pub fn as_str(&self) -> &str {
752         self.0.as_str()
753     }
754 
755     /// Returns a u16 value of the `Port`.
756     ///
757     /// # Examples
758     ///
759     /// ```
760     /// use ylong_http::request::uri::{Authority, Port};
761     ///
762     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
763     /// let port = authority.port().unwrap();
764     /// assert_eq!(port.as_u16().unwrap(), 80);
765     /// ```
as_u16(&self) -> Result<u16, HttpError>766     pub fn as_u16(&self) -> Result<u16, HttpError> {
767         self.0
768             .parse::<u16>()
769             .map_err(|_| ErrorKind::Uri(InvalidUri::InvalidPort).into())
770     }
771 }
772 
773 /// Path component of [`Uri`].
774 ///
775 /// [`Uri`]: Uri
776 #[derive(Clone, Debug, Default)]
777 pub struct Path(String);
778 
779 impl Path {
780     /// Converts a byte slice into a `Path`.
781     ///
782     /// # Examples
783     ///
784     /// ```
785     /// use ylong_http::request::uri::Path;
786     ///
787     /// let path = Path::from_bytes(b"/foo").unwrap();
788     /// assert_eq!(path.as_str(), "/foo");
789     /// ```
from_bytes(bytes: &[u8]) -> Result<Path, InvalidUri>790     pub fn from_bytes(bytes: &[u8]) -> Result<Path, InvalidUri> {
791         let (path, rest) = path_token(bytes)?;
792         if rest.is_empty() {
793             path.ok_or(InvalidUri::UriMissPath)
794         } else {
795             Err(InvalidUri::InvalidPath)
796         }
797     }
798 
799     /// Returns a string slice containing the entire `Path`.
800     ///
801     /// # Examples
802     ///
803     /// ```
804     /// use ylong_http::request::uri::Path;
805     ///
806     /// let path = Path::from_bytes(b"/foo").unwrap();
807     /// assert_eq!(path.as_str(), "/foo");
808     /// ```
as_str(&self) -> &str809     pub fn as_str(&self) -> &str {
810         self.0.as_str()
811     }
812 }
813 
814 impl<'a> TryFrom<&'a [u8]> for Path {
815     type Error = InvalidUri;
816 
try_from(bytes: &'a [u8]) -> Result<Self, Self::Error>817     fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
818         Path::from_bytes(bytes)
819     }
820 }
821 
822 impl<'a> TryFrom<&'a str> for Path {
823     type Error = InvalidUri;
824 
try_from(s: &'a str) -> Result<Self, Self::Error>825     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
826         TryFrom::try_from(s.as_bytes())
827     }
828 }
829 
830 /// Query component of [`Uri`].
831 ///
832 /// [`Uri`]: Uri
833 #[derive(Clone, Debug, Default)]
834 pub struct Query(String);
835 
836 impl Query {
837     /// Converts a byte slice into a `Query`.
838     ///
839     /// # Examples
840     ///
841     /// ```
842     /// use ylong_http::request::uri::Query;
843     ///
844     /// let query = Query::from_bytes(b"a=1").unwrap();
845     /// assert_eq!(query.as_str(), "a=1");
846     /// ```
from_bytes(bytes: &[u8]) -> Result<Query, InvalidUri>847     pub fn from_bytes(bytes: &[u8]) -> Result<Query, InvalidUri> {
848         let query = query_token(bytes)?;
849         query.ok_or(InvalidUri::UriMissQuery)
850     }
851 
852     /// Returns a string slice containing the entire `Query`.
853     ///
854     /// # Examples
855     ///
856     /// ```
857     /// use ylong_http::request::uri::Query;
858     ///
859     /// let query = Query::from_bytes(b"a=1").unwrap();
860     /// assert_eq!(query.as_str(), "a=1");
861     /// ```
as_str(&self) -> &str862     pub fn as_str(&self) -> &str {
863         self.0.as_str()
864     }
865 }
866 
867 impl<'a> TryFrom<&'a [u8]> for Query {
868     type Error = InvalidUri;
869 
try_from(s: &'a [u8]) -> Result<Self, Self::Error>870     fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> {
871         Query::from_bytes(s)
872     }
873 }
874 
875 impl<'a> TryFrom<&'a str> for Query {
876     type Error = InvalidUri;
877 
try_from(s: &'a str) -> Result<Self, Self::Error>878     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
879         TryFrom::try_from(s.as_bytes())
880     }
881 }
882 
883 /// `Protocol` indicates the scheme type supported by [`Uri`].
884 ///
885 /// [`Uri`]: Uri
886 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
887 enum Protocol {
888     Http,
889     Https,
890 }
891 
892 /// Error types generated during [`Uri`] construction due to different causes.
893 ///
894 /// [`Uri`]: Uri
895 #[derive(Debug, Eq, PartialEq)]
896 pub enum InvalidUri {
897     /// Invalid scheme
898     InvalidScheme,
899     /// Invalid authority
900     InvalidAuthority,
901     /// Invalid path
902     InvalidPath,
903     /// Invalid byte
904     InvalidByte,
905     /// Invalid format
906     InvalidFormat,
907     /// Invalid port
908     InvalidPort,
909     /// Missing scheme
910     UriMissScheme,
911     /// Missing path
912     UriMissPath,
913     /// Missing query
914     UriMissQuery,
915     /// Missing authority
916     UriMissAuthority,
917     /// Missing host
918     UriMissHost,
919     /// Contains Userinfo
920     UriContainUserinfo,
921     /// Too long
922     UriTooLong,
923 }
924 
925 impl From<Infallible> for InvalidUri {
from(_: Infallible) -> Self926     fn from(_: Infallible) -> Self {
927         unimplemented!()
928     }
929 }
930 
bytes_to_str(bytes: &[u8]) -> &str931 fn bytes_to_str(bytes: &[u8]) -> &str {
932     unsafe { std::str::from_utf8_unchecked(bytes) }
933 }
934 
scheme_token(bytes: &[u8]) -> Result<(Option<Scheme>, &[u8]), InvalidUri>935 fn scheme_token(bytes: &[u8]) -> Result<(Option<Scheme>, &[u8]), InvalidUri> {
936     const HTTP_SCHEME_LENGTH: usize = "http://".len();
937     const HTTPS_SCHEME_LENGTH: usize = "https://".len();
938     // Obtains the position of colons that separate schemes.
939     let pos = match bytes.iter().enumerate().find(|(_, &b)| b == b':') {
940         Some((index, _))
941             if index != 0
942                 && bytes[index..].len() > 2
943                 && bytes[index + 1..index + 3].eq_ignore_ascii_case(b"//") =>
944         {
945             index
946         }
947         Some((0, _)) => return Err(InvalidUri::InvalidScheme),
948         _ => return Ok((None, bytes)),
949     };
950     // Currently, only HTTP and HTTPS are supported. Therefore, you need to verify
951     // the scheme content.
952     if bytes[..pos].eq_ignore_ascii_case(b"http") {
953         Ok((Some(Protocol::Http.into()), &bytes[HTTP_SCHEME_LENGTH..]))
954     } else if bytes[..pos].eq_ignore_ascii_case(b"https") {
955         Ok((Some(Protocol::Https.into()), &bytes[HTTPS_SCHEME_LENGTH..]))
956     } else {
957         Err(InvalidUri::InvalidScheme)
958     }
959 }
960 
authority_token(bytes: &[u8]) -> Result<(Option<Authority>, &[u8]), InvalidUri>961 fn authority_token(bytes: &[u8]) -> Result<(Option<Authority>, &[u8]), InvalidUri> {
962     let mut end = bytes.len();
963     let mut colon_num = 0;
964     let mut left_bracket = false;
965     let mut right_bracket = false;
966     for (i, &b) in bytes.iter().enumerate() {
967         match b {
968             b'/' | b'?' | b'#' => {
969                 end = i;
970                 break;
971             }
972             b'[' => {
973                 if i == 0 {
974                     left_bracket = true;
975                 } else if left_bracket {
976                     return Err(InvalidUri::InvalidAuthority);
977                 }
978             }
979             b']' => {
980                 if left_bracket {
981                     if right_bracket {
982                         return Err(InvalidUri::InvalidAuthority);
983                     } else {
984                         right_bracket = true;
985                         // The ':' between '[' and ']' is in ipv6 and should be ignored.
986                         colon_num = 0;
987                     }
988                 }
989             }
990             // TODO According to RFC3986, the character @ can be one of the reserved characters,
991             // which needs to be improved after being familiar with the rules.
992             b'@' => {
993                 return Err(InvalidUri::UriContainUserinfo);
994             }
995             b':' => {
996                 colon_num += 1;
997             }
998             other => {
999                 if !URI_VALUE_BYTES[other as usize] {
1000                     return Err(InvalidUri::InvalidByte);
1001                 }
1002             }
1003         }
1004     }
1005     // The authority does not exist.
1006     if end == 0 {
1007         return Ok((None, &bytes[end..]));
1008     }
1009 
1010     // Incomplete square brackets
1011     if left_bracket ^ right_bracket {
1012         return Err(InvalidUri::InvalidAuthority);
1013     }
1014     // There are multiple colons in addition to IPv6.
1015     if colon_num > 1 {
1016         return Err(InvalidUri::InvalidAuthority);
1017     }
1018     let authority = host_port(&bytes[..end], colon_num)?;
1019     Ok((Some(authority), &bytes[end..]))
1020 }
1021 
path_token(bytes: &[u8]) -> Result<(Option<Path>, &[u8]), InvalidUri>1022 fn path_token(bytes: &[u8]) -> Result<(Option<Path>, &[u8]), InvalidUri> {
1023     let mut end = bytes.len();
1024     for (i, &b) in bytes.iter().enumerate() {
1025         match b {
1026             b'?' | b'#' => {
1027                 end = i;
1028                 break;
1029             }
1030             _ => {
1031                 if !URI_VALUE_BYTES[b as usize] {
1032                     return Err(InvalidUri::InvalidByte);
1033                 }
1034             }
1035         }
1036     }
1037     if end != 0 {
1038         let path = bytes_to_str(&bytes[..end]).to_string();
1039         Ok((Some(Path(path)), &bytes[end..]))
1040     } else {
1041         Ok((None, &bytes[end..]))
1042     }
1043 }
1044 
query_token(s: &[u8]) -> Result<Option<Query>, InvalidUri>1045 fn query_token(s: &[u8]) -> Result<Option<Query>, InvalidUri> {
1046     if s.is_empty() {
1047         return Ok(None);
1048     }
1049     let bytes = if s[0].eq_ignore_ascii_case(&b'?') {
1050         &s[1..]
1051     } else {
1052         s
1053     };
1054     let mut end = bytes.len();
1055     for (i, &b) in bytes.iter().enumerate() {
1056         match b {
1057             b'#' => {
1058                 end = i;
1059                 break;
1060             }
1061             _ => {
1062                 if !URI_VALUE_BYTES[b as usize] {
1063                     return Err(InvalidUri::InvalidByte);
1064                 }
1065             }
1066         }
1067     }
1068     if end == 0 {
1069         return Ok(None);
1070     }
1071     let query = bytes_to_str(&bytes[..end]);
1072     Ok(Some(Query(query.to_string())))
1073 }
1074 
host_port(auth: &[u8], colon_num: i32) -> Result<Authority, InvalidUri>1075 fn host_port(auth: &[u8], colon_num: i32) -> Result<Authority, InvalidUri> {
1076     let authority = bytes_to_str(auth);
1077     if colon_num != 0 {
1078         match authority.rsplit_once(':') {
1079             Some((host, port)) => {
1080                 if host.is_empty() {
1081                     Err(InvalidUri::UriMissHost)
1082                 } else if port.is_empty() {
1083                     Ok(Authority {
1084                         host: Host(host.to_string()),
1085                         port: None,
1086                     })
1087                 } else {
1088                     port.parse::<u16>().map_err(|_| InvalidUri::InvalidPort)?;
1089                     Ok(Authority {
1090                         host: Host(host.to_string()),
1091                         port: Some(Port(port.to_string())),
1092                     })
1093                 }
1094             }
1095             None => Err(InvalidUri::UriMissAuthority),
1096         }
1097     } else {
1098         Ok(Authority {
1099             host: Host(authority.to_string()),
1100             port: None,
1101         })
1102     }
1103 }
1104 
validity_check(unchecked_uri: Uri) -> Result<Uri, InvalidUri>1105 fn validity_check(unchecked_uri: Uri) -> Result<Uri, InvalidUri> {
1106     match (
1107         &unchecked_uri.scheme,
1108         &unchecked_uri.authority,
1109         &unchecked_uri.path,
1110         &unchecked_uri.query,
1111     ) {
1112         (Some(_), None, _, _) => Err(InvalidUri::UriMissAuthority),
1113         (None, Some(_), Some(_), _) => Err(InvalidUri::UriMissScheme),
1114         (None, Some(_), _, Some(_)) => Err(InvalidUri::UriMissScheme),
1115         (None, None, None, None) => Err(InvalidUri::InvalidFormat),
1116         _ => Ok(unchecked_uri),
1117     }
1118 }
1119 
1120 #[rustfmt::skip]
1121 const URI_VALUE_BYTES: [bool; 256] = {
1122     const __: bool = false;
1123     const TT: bool = true;
1124     [
1125 //      \0                                  HT  LF          CR
1126         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
1127         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 1F
1128 //      \w  !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
1129         __, TT, __, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, // 2F
1130 //      0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
1131         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, __, TT, __, TT, // 3F
1132 //      @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1133         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, // 4F
1134 //      P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
1135         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, __, TT, __, TT, // 5F
1136 //      `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1137         __, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, // 6F
1138 //      p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~   del
1139         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, __, __, __, TT, __, // 7F
1140 //      Expand ascii
1141         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8F
1142         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9F
1143         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // AF
1144         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // BF
1145         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // CF
1146         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // DF
1147         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // EF
1148         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // FF
1149     ]
1150 };
1151 
1152 #[cfg(test)]
1153 mod ut_uri {
1154     use super::{InvalidUri, Scheme, Uri, UriBuilder};
1155     use crate::error::{ErrorKind, HttpError};
1156 
1157     macro_rules! test_builder_valid {
1158         ($res1:expr, $res2:expr) => {{
1159             let uri = UriBuilder::new()
1160                 .scheme($res1.0)
1161                 .authority($res1.1)
1162                 .path($res1.2)
1163                 .query($res1.3)
1164                 .build()
1165                 .unwrap();
1166             assert_eq!(uri.scheme().unwrap().as_str(), $res2.0);
1167             assert_eq!(uri.host().unwrap().as_str(), $res2.1);
1168             assert_eq!(uri.port().unwrap().as_str(), $res2.2);
1169             assert_eq!(uri.path().unwrap().as_str(), $res2.3);
1170             assert_eq!(uri.query().unwrap().as_str(), $res2.4);
1171             assert_eq!(uri.to_string(), $res2.5)
1172         }};
1173     }
1174 
1175     /// UT test cases for `build_from_builder`.
1176     ///
1177     /// # Brief
1178     /// 1. Creates UriBuilder by calling UriBuilder::new().
1179     /// 2. Sets Scheme by calling scheme().
1180     /// 3. Sets authority by calling authority().
1181     /// 4. Sets path by calling path().
1182     /// 5. Sets query by calling query().
1183     /// 6. Creates Uri by calling build().
1184     /// 7. Gets string slice value of uri components by calling as_str().
1185     /// 8. Gets string value of uri by calling to_string().
1186     /// 9. Checks if the test result is correct by assert_eq!().
1187     #[test]
build_from_builder()1188     fn build_from_builder() {
1189         test_builder_valid!(
1190             ("http", "hyper.rs:80", "/foo", "a=1"),
1191             (
1192                 "http",
1193                 "hyper.rs",
1194                 "80",
1195                 "/foo",
1196                 "a=1",
1197                 "http://hyper.rs:80/foo?a=1"
1198             )
1199         );
1200         test_builder_valid!(
1201             (Scheme::HTTP, "hyper.rs:80", "/foo", "a=1"),
1202             (
1203                 "http",
1204                 "hyper.rs",
1205                 "80",
1206                 "/foo",
1207                 "a=1",
1208                 "http://hyper.rs:80/foo?a=1"
1209             )
1210         );
1211         test_builder_valid!(
1212             ("https", "hyper.rs:80", "/foo", "a=1"),
1213             (
1214                 "https",
1215                 "hyper.rs",
1216                 "80",
1217                 "/foo",
1218                 "a=1",
1219                 "https://hyper.rs:80/foo?a=1"
1220             )
1221         );
1222         test_builder_valid!(
1223             (Scheme::HTTPS, "hyper.rs:80", "/foo", "a=1"),
1224             (
1225                 "https",
1226                 "hyper.rs",
1227                 "80",
1228                 "/foo",
1229                 "a=1",
1230                 "https://hyper.rs:80/foo?a=1"
1231             )
1232         );
1233     }
1234 
1235     /// UT test cases for `build_from_instance`.
1236     ///
1237     /// # Brief
1238     /// 1. Creates UriBuilder by calling Uri::builder().
1239     /// 2. Sets Scheme by calling scheme().
1240     /// 3. Sets authority by calling authority().
1241     /// 4. Sets path by calling path().
1242     /// 5. Sets query by calling query().
1243     /// 6. Creates Uri by calling build().
1244     /// 7. Gets string slice value of uri components by calling as_str().
1245     /// 8. Gets string value of uri by calling to_string().
1246     /// 9. Checks if the test result is correct by assert_eq!().
1247     #[test]
build_from_instance()1248     fn build_from_instance() {
1249         let uri = Uri::builder()
1250             .scheme(Scheme::HTTP)
1251             .authority("hyper.rs:80")
1252             .path("/foo")
1253             .query("a=1")
1254             .build()
1255             .unwrap();
1256         assert_eq!(uri.scheme().unwrap().as_str(), "http");
1257         assert_eq!(uri.host().unwrap().as_str(), "hyper.rs");
1258         assert_eq!(uri.port().unwrap().as_str(), "80");
1259         assert_eq!(uri.path().unwrap().as_str(), "/foo");
1260         assert_eq!(uri.query().unwrap().as_str(), "a=1");
1261         assert_eq!(uri.to_string(), "http://hyper.rs:80/foo?a=1")
1262     }
1263 
1264     /// UT test cases for `build_from_str`.
1265     ///
1266     /// # Brief
1267     /// 1. Creates Uri by calling from_bytes().
1268     /// 2. Gets string slice value of uri components by calling as_str().
1269     /// 3. Gets u16 value of port by call as_u16().
1270     /// 4. Gets string value of uri by calling to_string().
1271     /// 5. Checks if the test result is correct by assert_eq!().
1272     #[test]
build_from_str()1273     fn build_from_str() {
1274         let uri = Uri::from_bytes("http://hyper.rs:80/foo?a=1".as_bytes()).unwrap();
1275         assert_eq!(uri.scheme().unwrap().as_str(), "http");
1276         assert_eq!(uri.host().unwrap().as_str(), "hyper.rs");
1277         assert_eq!(uri.port().unwrap().as_str(), "80");
1278         assert_eq!(uri.port().unwrap().as_u16().unwrap(), 80);
1279         assert_eq!(uri.path().unwrap().as_str(), "/foo");
1280         assert_eq!(uri.query().unwrap().as_str(), "a=1");
1281         assert_eq!(uri.to_string(), "http://hyper.rs:80/foo?a=1")
1282     }
1283 
1284     /// UT test cases for `Uri::from_bytes`.
1285     ///
1286     /// # Brief
1287     /// 1. Creates Uri by calling `Uri::from_bytes()`.
1288     /// 2. Checks if the test results are correct.
1289     #[test]
ut_uri_from_bytes()1290     fn ut_uri_from_bytes() {
1291         macro_rules! uri_test_case {
1292             ($raw: expr, $tar: expr, $(,)?) => {
1293                 match (Uri::from_bytes($raw), $tar) {
1294                     (Ok(res), Ok(tar)) => assert_eq!(
1295                         (
1296                             res.scheme().map(|scheme| scheme.as_str()),
1297                             res.host().map(|host| host.as_str()),
1298                             res.port().map(|port| port.as_str()),
1299                             res.path().map(|path| path.as_str()),
1300                             res.query().map(|query| query.as_str()),
1301                         ),
1302                         tar,
1303                     ),
1304                     (Err(res), Err(tar)) => assert_eq!(res, tar),
1305                     _ => panic!("uri test case failed!"),
1306                 }
1307             };
1308         }
1309 
1310         uri_test_case!(
1311             b"httpss://www.example.com/",
1312             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidScheme))),
1313         );
1314 
1315         uri_test_case!(
1316             b"://www.example.com/",
1317             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidScheme))),
1318         );
1319 
1320         uri_test_case!(
1321             b"https://www.hu awei.com/",
1322             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1323         );
1324 
1325         uri_test_case!(
1326             br#"https://www.hu"awei.com/"#,
1327             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1328         );
1329 
1330         uri_test_case!(
1331             br#"https://www.hu"awei.com/"#,
1332             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1333         );
1334 
1335         uri_test_case!(
1336             br#"https://www.hu"<>\^`awei.com/"#,
1337             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1338         );
1339 
1340         uri_test_case!(
1341             br#"https://www.example.com:a0/"#,
1342             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidPort))),
1343         );
1344 
1345         uri_test_case!(
1346             br#"https://www.example.com:80/message/e<>mail"#,
1347             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1348         );
1349 
1350         uri_test_case!(
1351             br#"https://www.example.com:80/message/email?name='\^'"#,
1352             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1353         );
1354 
1355         uri_test_case!(
1356             br#"https:/www.example.com:80/message/email?name=arya"#,
1357             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1358         );
1359 
1360         uri_test_case!(
1361             br#"https:/www.example.com:80"#,
1362             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1363         );
1364 
1365         uri_test_case!(
1366             br#"https:/www.example.com"#,
1367             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1368         );
1369 
1370         uri_test_case!(
1371             br#"https://www.huaw:ei.com:80"#,
1372             Err(HttpError::from(ErrorKind::Uri(
1373                 InvalidUri::InvalidAuthority
1374             ))),
1375         );
1376 
1377         uri_test_case!(
1378             br#"https://www.huaw:ei.com:80"#,
1379             Err(HttpError::from(ErrorKind::Uri(
1380                 InvalidUri::InvalidAuthority
1381             ))),
1382         );
1383 
1384         uri_test_case!(
1385             br#"https://name=1234@www.example.com:80/message/email?name=arya"#,
1386             Err(HttpError::from(ErrorKind::Uri(
1387                 InvalidUri::UriContainUserinfo
1388             ))),
1389         );
1390 
1391         uri_test_case!(
1392             br#"www.example.com:80/message/email?name=arya"#,
1393             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1394         );
1395 
1396         uri_test_case!(
1397             br#"https://[0:0:0:0:0:0:0:0:80/message/email?name=arya"#,
1398             Err(HttpError::from(ErrorKind::Uri(
1399                 InvalidUri::InvalidAuthority
1400             ))),
1401         );
1402 
1403         uri_test_case!(
1404             br#"https:///foo?a=1"#,
1405             Err(HttpError::from(ErrorKind::Uri(
1406                 InvalidUri::UriMissAuthority
1407             ))),
1408         );
1409 
1410         uri_test_case!(
1411             b"https://www.example.com/",
1412             Ok((
1413                 Some("https"),
1414                 Some("www.example.com"),
1415                 None,
1416                 Some("/"),
1417                 None
1418             )),
1419         );
1420 
1421         uri_test_case!(
1422             b"https://www.example.com:80/foo?a=1",
1423             Ok((
1424                 Some("https"),
1425                 Some("www.example.com"),
1426                 Some("80"),
1427                 Some("/foo"),
1428                 Some("a=1"),
1429             )),
1430         );
1431 
1432         uri_test_case!(
1433             b"https://www.example.com:80/foo?a=1#fragment",
1434             Ok((
1435                 Some("https"),
1436                 Some("www.example.com"),
1437                 Some("80"),
1438                 Some("/foo"),
1439                 Some("a=1"),
1440             )),
1441         );
1442 
1443         uri_test_case!(
1444             b"https://www.example.com:80?a=1",
1445             Ok((
1446                 Some("https"),
1447                 Some("www.example.com"),
1448                 Some("80"),
1449                 None,
1450                 Some("a=1"),
1451             )),
1452         );
1453 
1454         uri_test_case!(
1455             b"https://www.example.com?a=1",
1456             Ok((
1457                 Some("https"),
1458                 Some("www.example.com"),
1459                 None,
1460                 None,
1461                 Some("a=1"),
1462             )),
1463         );
1464 
1465         uri_test_case!(
1466             b"https://www.example.com?",
1467             Ok((Some("https"), Some("www.example.com"), None, None, None)),
1468         );
1469 
1470         uri_test_case!(
1471             b"https://www.example.com:80",
1472             Ok((
1473                 Some("https"),
1474                 Some("www.example.com"),
1475                 Some("80"),
1476                 None,
1477                 None,
1478             )),
1479         );
1480 
1481         uri_test_case!(
1482             b"https://www.example.com",
1483             Ok((Some("https"), Some("www.example.com"), None, None, None)),
1484         );
1485 
1486         uri_test_case!(
1487             b"https://www.example.com#fragment",
1488             Ok((Some("https"), Some("www.example.com"), None, None, None)),
1489         );
1490 
1491         uri_test_case!(
1492             b"www.example.com",
1493             Ok((None, Some("www.example.com"), None, None, None)),
1494         );
1495 
1496         uri_test_case!(
1497             b"/foo?a=1",
1498             Ok((None, None, None, Some("/foo"), Some("a=1"))),
1499         );
1500 
1501         uri_test_case!(
1502             b"https://[0:0:0:0:0:0:0:0]",
1503             Ok((Some("https"), Some("[0:0:0:0:0:0:0:0]"), None, None, None)),
1504         );
1505 
1506         uri_test_case!(
1507             b"https://[0:0:0:0:0:0:0:0]:80",
1508             Ok((
1509                 Some("https"),
1510                 Some("[0:0:0:0:0:0:0:0]"),
1511                 Some("80"),
1512                 None,
1513                 None,
1514             )),
1515         );
1516     }
1517 
1518     /// UT test cases for `Uri::authority`.
1519     ///
1520     /// # Brief
1521     /// 1. Creates Uri by calling `Uri::authority()`.
1522     /// 2. Checks if the test results are correct.
1523     #[test]
ut_uri_authority()1524     fn ut_uri_authority() {
1525         let uri = Uri::from_bytes(b"http://example.com:8080/foo?a=1").unwrap();
1526         let authority = uri.authority().unwrap();
1527         assert_eq!(authority.host.as_str(), "example.com");
1528         assert_eq!(authority.port().unwrap().as_str(), "8080");
1529     }
1530 
1531     /// UT test cases for `Uri::path_and_query`.
1532     ///
1533     /// # Brief
1534     /// 1. Creates Uri by calling `Uri::path_and_query()`.
1535     /// 2. Checks if the test results are correct.
1536     #[test]
ut_uri_path_and_query()1537     fn ut_uri_path_and_query() {
1538         let uri = Uri::from_bytes(b"http://example.com:8080/foo?a=1").unwrap();
1539         assert_eq!(uri.path_and_query().unwrap(), "/foo?a=1");
1540 
1541         let uri = Uri::from_bytes(b"http://example.com:8080").unwrap();
1542         assert_eq!(uri.path_and_query(), None);
1543     }
1544 }
1545