• 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     /// Returns the default port of current uri `Scheme`.
558     ///
559     /// # Example
560     ///
561     /// ```
562     /// use ylong_http::request::uri::Scheme;
563     ///
564     /// let scheme = Scheme::from_bytes(b"http").unwrap();
565     /// assert_eq!(scheme.default_port(), 80);
566     /// ```
default_port(&self) -> u16567     pub fn default_port(&self) -> u16 {
568         match *self {
569             Scheme::HTTP => 80,
570             Scheme::HTTPS => 443,
571         }
572     }
573 }
574 
575 impl From<Protocol> for Scheme {
from(proto: Protocol) -> Self576     fn from(proto: Protocol) -> Self {
577         Scheme { proto }
578     }
579 }
580 
581 impl<'a> TryFrom<&'a [u8]> for Scheme {
582     type Error = InvalidUri;
583 
try_from(bytes: &'a [u8]) -> Result<Self, Self::Error>584     fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
585         Scheme::from_bytes(bytes)
586     }
587 }
588 
589 impl<'a> TryFrom<&'a str> for Scheme {
590     type Error = InvalidUri;
591 
try_from(s: &'a str) -> Result<Self, Self::Error>592     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
593         TryFrom::try_from(s.as_bytes())
594     }
595 }
596 
597 /// Authority component of [`Uri`].
598 ///
599 /// [`Uri`]: Uri
600 #[derive(Clone, Debug, Default, Hash, PartialEq, Eq)]
601 pub struct Authority {
602     host: Host,
603     port: Option<Port>,
604 }
605 
606 impl Authority {
607     /// Converts a byte slice into a `Authority`.
608     ///
609     /// # Examples
610     ///
611     /// ```
612     /// use ylong_http::request::uri::Authority;
613     ///
614     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
615     /// ```
from_bytes(bytes: &[u8]) -> Result<Authority, InvalidUri>616     pub fn from_bytes(bytes: &[u8]) -> Result<Authority, InvalidUri> {
617         if bytes.is_empty() {
618             return Err(InvalidUri::UriMissAuthority);
619         }
620         let (authority, rest) = authority_token(bytes)?;
621         if !rest.is_empty() || authority.is_none() {
622             return Err(InvalidUri::InvalidAuthority);
623         }
624         Ok(authority.unwrap())
625     }
626 
627     /// Gets a immutable reference to `Host`.
628     ///
629     /// # Examples
630     ///
631     /// ```
632     /// use ylong_http::request::uri::{Authority, Host};
633     ///
634     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
635     /// let host = authority.host();
636     /// assert_eq!(host.as_str(), "example.com");
637     /// ```
host(&self) -> &Host638     pub fn host(&self) -> &Host {
639         &self.host
640     }
641 
642     /// Gets a immutable reference to `Port`.
643     ///
644     /// # Examples
645     ///
646     /// ```
647     /// use ylong_http::request::uri::{Authority, Port};
648     ///
649     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
650     /// let port = authority.port().unwrap();
651     /// assert_eq!(port.as_str(), "80");
652     /// ```
port(&self) -> Option<&Port>653     pub fn port(&self) -> Option<&Port> {
654         self.port.as_ref()
655     }
656 
657     /// Returns a string containing the entire `Authority`.
658     ///
659     /// # Examples
660     ///
661     /// ```
662     /// use ylong_http::request::uri::{Authority, Port};
663     ///
664     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
665     /// assert_eq!(authority.to_str(), "example.com:80".to_string());
666     /// ```
to_str(&self) -> String667     pub fn to_str(&self) -> String {
668         let mut auth = self.host.as_str().to_string();
669         if let Some(ref p) = self.port {
670             auth.push(':');
671             auth.push_str(p.as_str());
672         };
673         auth
674     }
675 
676     /// Splits the `Authority` into its parts.
677     ///
678     /// # Examples
679     ///
680     /// ```
681     /// use ylong_http::request::uri::Authority;
682     ///
683     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
684     /// let (host, port) = authority.into_parts();
685     /// assert_eq!(host.as_str(), "example.com");
686     /// assert_eq!(port.unwrap().as_u16().unwrap(), 80);
687     /// ```
into_parts(self) -> (Host, Option<Port>)688     pub fn into_parts(self) -> (Host, Option<Port>) {
689         (self.host, self.port)
690     }
691 }
692 
693 impl<'a> TryFrom<&'a [u8]> for Authority {
694     type Error = InvalidUri;
695 
try_from(bytes: &'a [u8]) -> Result<Self, Self::Error>696     fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
697         Authority::from_bytes(bytes)
698     }
699 }
700 
701 impl<'a> TryFrom<&'a str> for Authority {
702     type Error = InvalidUri;
703 
try_from(s: &'a str) -> Result<Self, Self::Error>704     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
705         TryFrom::try_from(s.as_bytes())
706     }
707 }
708 
709 impl ToString for Authority {
to_string(&self) -> String710     fn to_string(&self) -> String {
711         let mut builder = String::new();
712         builder.push_str(self.host().as_str());
713         if let Some(port) = self.port() {
714             builder.push(':');
715             builder.push_str(port.as_str());
716         }
717         builder
718     }
719 }
720 
721 /// Host part of [`Authority`].
722 ///
723 /// [`Authority`]: Authority
724 #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
725 pub struct Host(String);
726 
727 impl Host {
728     /// Returns a string slice containing the entire `Host`.
729     ///
730     /// # Examples
731     ///
732     /// ```
733     /// use ylong_http::request::uri::Authority;
734     ///
735     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
736     /// let host = authority.host();
737     /// assert_eq!(host.as_str(), "example.com");
738     /// ```
as_str(&self) -> &str739     pub fn as_str(&self) -> &str {
740         self.0.as_str()
741     }
742 }
743 
744 impl ToString for Host {
to_string(&self) -> String745     fn to_string(&self) -> String {
746         self.0.to_owned()
747     }
748 }
749 
750 /// Port part of [`Authority`].
751 ///
752 /// [`Authority`]: Authority
753 #[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
754 pub struct Port(String);
755 
756 impl Port {
757     /// Returns a string slice containing the entire `Port`.
758     ///
759     /// # Examples
760     ///
761     /// ```
762     /// use ylong_http::request::uri::{Authority, Port};
763     ///
764     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
765     /// let port = authority.port().unwrap();
766     /// assert_eq!(port.as_str(), "80");
767     /// ```
as_str(&self) -> &str768     pub fn as_str(&self) -> &str {
769         self.0.as_str()
770     }
771 
772     /// Returns a u16 value of the `Port`.
773     ///
774     /// # Examples
775     ///
776     /// ```
777     /// use ylong_http::request::uri::{Authority, Port};
778     ///
779     /// let authority = Authority::from_bytes(b"example.com:80").unwrap();
780     /// let port = authority.port().unwrap();
781     /// assert_eq!(port.as_u16().unwrap(), 80);
782     /// ```
as_u16(&self) -> Result<u16, HttpError>783     pub fn as_u16(&self) -> Result<u16, HttpError> {
784         self.0
785             .parse::<u16>()
786             .map_err(|_| ErrorKind::Uri(InvalidUri::InvalidPort).into())
787     }
788 }
789 
790 /// Path component of [`Uri`].
791 ///
792 /// [`Uri`]: Uri
793 #[derive(Clone, Debug, Default)]
794 pub struct Path(String);
795 
796 impl Path {
797     /// Converts a byte slice into a `Path`.
798     ///
799     /// # Examples
800     ///
801     /// ```
802     /// use ylong_http::request::uri::Path;
803     ///
804     /// let path = Path::from_bytes(b"/foo").unwrap();
805     /// assert_eq!(path.as_str(), "/foo");
806     /// ```
from_bytes(bytes: &[u8]) -> Result<Path, InvalidUri>807     pub fn from_bytes(bytes: &[u8]) -> Result<Path, InvalidUri> {
808         let (path, rest) = path_token(bytes)?;
809         if rest.is_empty() {
810             path.ok_or(InvalidUri::UriMissPath)
811         } else {
812             Err(InvalidUri::InvalidPath)
813         }
814     }
815 
816     /// Returns a string slice containing the entire `Path`.
817     ///
818     /// # Examples
819     ///
820     /// ```
821     /// use ylong_http::request::uri::Path;
822     ///
823     /// let path = Path::from_bytes(b"/foo").unwrap();
824     /// assert_eq!(path.as_str(), "/foo");
825     /// ```
as_str(&self) -> &str826     pub fn as_str(&self) -> &str {
827         self.0.as_str()
828     }
829 }
830 
831 impl<'a> TryFrom<&'a [u8]> for Path {
832     type Error = InvalidUri;
833 
try_from(bytes: &'a [u8]) -> Result<Self, Self::Error>834     fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
835         Path::from_bytes(bytes)
836     }
837 }
838 
839 impl<'a> TryFrom<&'a str> for Path {
840     type Error = InvalidUri;
841 
try_from(s: &'a str) -> Result<Self, Self::Error>842     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
843         TryFrom::try_from(s.as_bytes())
844     }
845 }
846 
847 /// Query component of [`Uri`].
848 ///
849 /// [`Uri`]: Uri
850 #[derive(Clone, Debug, Default)]
851 pub struct Query(String);
852 
853 impl Query {
854     /// Converts a byte slice into a `Query`.
855     ///
856     /// # Examples
857     ///
858     /// ```
859     /// use ylong_http::request::uri::Query;
860     ///
861     /// let query = Query::from_bytes(b"a=1").unwrap();
862     /// assert_eq!(query.as_str(), "a=1");
863     /// ```
from_bytes(bytes: &[u8]) -> Result<Query, InvalidUri>864     pub fn from_bytes(bytes: &[u8]) -> Result<Query, InvalidUri> {
865         let query = query_token(bytes)?;
866         query.ok_or(InvalidUri::UriMissQuery)
867     }
868 
869     /// Returns a string slice containing the entire `Query`.
870     ///
871     /// # Examples
872     ///
873     /// ```
874     /// use ylong_http::request::uri::Query;
875     ///
876     /// let query = Query::from_bytes(b"a=1").unwrap();
877     /// assert_eq!(query.as_str(), "a=1");
878     /// ```
as_str(&self) -> &str879     pub fn as_str(&self) -> &str {
880         self.0.as_str()
881     }
882 }
883 
884 impl<'a> TryFrom<&'a [u8]> for Query {
885     type Error = InvalidUri;
886 
try_from(s: &'a [u8]) -> Result<Self, Self::Error>887     fn try_from(s: &'a [u8]) -> Result<Self, Self::Error> {
888         Query::from_bytes(s)
889     }
890 }
891 
892 impl<'a> TryFrom<&'a str> for Query {
893     type Error = InvalidUri;
894 
try_from(s: &'a str) -> Result<Self, Self::Error>895     fn try_from(s: &'a str) -> Result<Self, Self::Error> {
896         TryFrom::try_from(s.as_bytes())
897     }
898 }
899 
900 /// `Protocol` indicates the scheme type supported by [`Uri`].
901 ///
902 /// [`Uri`]: Uri
903 #[derive(Clone, Debug, Eq, PartialEq, Hash)]
904 enum Protocol {
905     Http,
906     Https,
907 }
908 
909 /// Error types generated during [`Uri`] construction due to different causes.
910 ///
911 /// [`Uri`]: Uri
912 #[derive(Debug, Eq, PartialEq)]
913 pub enum InvalidUri {
914     /// Invalid scheme
915     InvalidScheme,
916     /// Invalid authority
917     InvalidAuthority,
918     /// Invalid path
919     InvalidPath,
920     /// Invalid byte
921     InvalidByte,
922     /// Invalid format
923     InvalidFormat,
924     /// Invalid port
925     InvalidPort,
926     /// Missing scheme
927     UriMissScheme,
928     /// Missing path
929     UriMissPath,
930     /// Missing query
931     UriMissQuery,
932     /// Missing authority
933     UriMissAuthority,
934     /// Missing host
935     UriMissHost,
936     /// Contains Userinfo
937     UriContainUserinfo,
938     /// Too long
939     UriTooLong,
940 }
941 
942 impl From<Infallible> for InvalidUri {
from(_: Infallible) -> Self943     fn from(_: Infallible) -> Self {
944         unimplemented!()
945     }
946 }
947 
bytes_to_str(bytes: &[u8]) -> &str948 fn bytes_to_str(bytes: &[u8]) -> &str {
949     unsafe { std::str::from_utf8_unchecked(bytes) }
950 }
951 
scheme_token(bytes: &[u8]) -> Result<(Option<Scheme>, &[u8]), InvalidUri>952 fn scheme_token(bytes: &[u8]) -> Result<(Option<Scheme>, &[u8]), InvalidUri> {
953     const HTTP_SCHEME_LENGTH: usize = "http://".len();
954     const HTTPS_SCHEME_LENGTH: usize = "https://".len();
955     // Obtains the position of colons that separate schemes.
956     let pos = match bytes.iter().enumerate().find(|(_, &b)| b == b':') {
957         Some((index, _))
958             if index != 0
959                 && bytes[index..].len() > 2
960                 && bytes[index + 1..index + 3].eq_ignore_ascii_case(b"//") =>
961         {
962             index
963         }
964         Some((0, _)) => return Err(InvalidUri::InvalidScheme),
965         _ => return Ok((None, bytes)),
966     };
967     // Currently, only HTTP and HTTPS are supported. Therefore, you need to verify
968     // the scheme content.
969     if bytes[..pos].eq_ignore_ascii_case(b"http") {
970         Ok((Some(Protocol::Http.into()), &bytes[HTTP_SCHEME_LENGTH..]))
971     } else if bytes[..pos].eq_ignore_ascii_case(b"https") {
972         Ok((Some(Protocol::Https.into()), &bytes[HTTPS_SCHEME_LENGTH..]))
973     } else {
974         Err(InvalidUri::InvalidScheme)
975     }
976 }
977 
authority_token(bytes: &[u8]) -> Result<(Option<Authority>, &[u8]), InvalidUri>978 fn authority_token(bytes: &[u8]) -> Result<(Option<Authority>, &[u8]), InvalidUri> {
979     let mut end = bytes.len();
980     let mut colon_num = 0;
981     let mut left_bracket = false;
982     let mut right_bracket = false;
983     for (i, &b) in bytes.iter().enumerate() {
984         match b {
985             b'/' | b'?' | b'#' => {
986                 end = i;
987                 break;
988             }
989             b'[' => {
990                 if i == 0 {
991                     left_bracket = true;
992                 } else if left_bracket {
993                     return Err(InvalidUri::InvalidAuthority);
994                 }
995             }
996             b']' => {
997                 if left_bracket {
998                     if right_bracket {
999                         return Err(InvalidUri::InvalidAuthority);
1000                     } else {
1001                         right_bracket = true;
1002                         // The ':' between '[' and ']' is in ipv6 and should be ignored.
1003                         colon_num = 0;
1004                     }
1005                 }
1006             }
1007             // TODO According to RFC3986, the character @ can be one of the reserved characters,
1008             // which needs to be improved after being familiar with the rules.
1009             b'@' => {
1010                 return Err(InvalidUri::UriContainUserinfo);
1011             }
1012             b':' => {
1013                 colon_num += 1;
1014             }
1015             other => {
1016                 if !URI_VALUE_BYTES[other as usize] {
1017                     return Err(InvalidUri::InvalidByte);
1018                 }
1019             }
1020         }
1021     }
1022     // The authority does not exist.
1023     if end == 0 {
1024         return Ok((None, &bytes[end..]));
1025     }
1026 
1027     // Incomplete square brackets
1028     if left_bracket ^ right_bracket {
1029         return Err(InvalidUri::InvalidAuthority);
1030     }
1031     // There are multiple colons in addition to IPv6.
1032     if colon_num > 1 {
1033         return Err(InvalidUri::InvalidAuthority);
1034     }
1035     let authority = host_port(&bytes[..end], colon_num)?;
1036     Ok((Some(authority), &bytes[end..]))
1037 }
1038 
path_token(bytes: &[u8]) -> Result<(Option<Path>, &[u8]), InvalidUri>1039 fn path_token(bytes: &[u8]) -> Result<(Option<Path>, &[u8]), InvalidUri> {
1040     let mut end = bytes.len();
1041     for (i, &b) in bytes.iter().enumerate() {
1042         match b {
1043             b'?' | b'#' => {
1044                 end = i;
1045                 break;
1046             }
1047             _ => {
1048                 if !URI_VALUE_BYTES[b as usize] {
1049                     return Err(InvalidUri::InvalidByte);
1050                 }
1051             }
1052         }
1053     }
1054     if end != 0 {
1055         let path = bytes_to_str(&bytes[..end]).to_string();
1056         Ok((Some(Path(path)), &bytes[end..]))
1057     } else {
1058         Ok((None, &bytes[end..]))
1059     }
1060 }
1061 
query_token(s: &[u8]) -> Result<Option<Query>, InvalidUri>1062 fn query_token(s: &[u8]) -> Result<Option<Query>, InvalidUri> {
1063     if s.is_empty() {
1064         return Ok(None);
1065     }
1066     let bytes = if s[0].eq_ignore_ascii_case(&b'?') {
1067         &s[1..]
1068     } else {
1069         s
1070     };
1071     let mut end = bytes.len();
1072     for (i, &b) in bytes.iter().enumerate() {
1073         match b {
1074             b'#' => {
1075                 end = i;
1076                 break;
1077             }
1078             _ => {
1079                 if !URI_VALUE_BYTES[b as usize] {
1080                     return Err(InvalidUri::InvalidByte);
1081                 }
1082             }
1083         }
1084     }
1085     if end == 0 {
1086         return Ok(None);
1087     }
1088     let query = bytes_to_str(&bytes[..end]);
1089     Ok(Some(Query(query.to_string())))
1090 }
1091 
host_port(auth: &[u8], colon_num: i32) -> Result<Authority, InvalidUri>1092 fn host_port(auth: &[u8], colon_num: i32) -> Result<Authority, InvalidUri> {
1093     let authority = bytes_to_str(auth);
1094     if colon_num != 0 {
1095         match authority.rsplit_once(':') {
1096             Some((host, port)) => {
1097                 if host.is_empty() {
1098                     Err(InvalidUri::UriMissHost)
1099                 } else if port.is_empty() {
1100                     Ok(Authority {
1101                         host: Host(host.to_string()),
1102                         port: None,
1103                     })
1104                 } else {
1105                     port.parse::<u16>().map_err(|_| InvalidUri::InvalidPort)?;
1106                     Ok(Authority {
1107                         host: Host(host.to_string()),
1108                         port: Some(Port(port.to_string())),
1109                     })
1110                 }
1111             }
1112             None => Err(InvalidUri::UriMissAuthority),
1113         }
1114     } else {
1115         Ok(Authority {
1116             host: Host(authority.to_string()),
1117             port: None,
1118         })
1119     }
1120 }
1121 
validity_check(unchecked_uri: Uri) -> Result<Uri, InvalidUri>1122 fn validity_check(unchecked_uri: Uri) -> Result<Uri, InvalidUri> {
1123     match (
1124         &unchecked_uri.scheme,
1125         &unchecked_uri.authority,
1126         &unchecked_uri.path,
1127         &unchecked_uri.query,
1128     ) {
1129         (Some(_), None, _, _) => Err(InvalidUri::UriMissAuthority),
1130         (None, Some(_), Some(_), _) => Err(InvalidUri::UriMissScheme),
1131         (None, Some(_), _, Some(_)) => Err(InvalidUri::UriMissScheme),
1132         (None, None, None, None) => Err(InvalidUri::InvalidFormat),
1133         _ => Ok(unchecked_uri),
1134     }
1135 }
1136 
1137 #[rustfmt::skip]
1138 const URI_VALUE_BYTES: [bool; 256] = {
1139     const __: bool = false;
1140     const TT: bool = true;
1141     [
1142 //      \0                                  HT  LF          CR
1143         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
1144         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 1F
1145 //      \w  !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
1146         __, TT, __, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, // 2F
1147 //      0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
1148         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, __, TT, __, TT, // 3F
1149 //      @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1150         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, // 4F
1151 //      P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
1152         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, __, TT, __, TT, // 5F
1153 //      `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1154         __, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, // 6F
1155 //      p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~   del
1156         TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, TT, __, __, __, TT, __, // 7F
1157 //      Expand ascii
1158         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8F
1159         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9F
1160         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // AF
1161         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // BF
1162         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // CF
1163         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // DF
1164         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // EF
1165         __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // FF
1166     ]
1167 };
1168 
1169 #[cfg(test)]
1170 mod ut_uri {
1171     use super::{InvalidUri, Scheme, Uri, UriBuilder};
1172     use crate::error::{ErrorKind, HttpError};
1173 
1174     macro_rules! test_builder_valid {
1175         ($res1:expr, $res2:expr) => {{
1176             let uri = UriBuilder::new()
1177                 .scheme($res1.0)
1178                 .authority($res1.1)
1179                 .path($res1.2)
1180                 .query($res1.3)
1181                 .build()
1182                 .unwrap();
1183             assert_eq!(uri.scheme().unwrap().as_str(), $res2.0);
1184             assert_eq!(uri.host().unwrap().as_str(), $res2.1);
1185             assert_eq!(uri.port().unwrap().as_str(), $res2.2);
1186             assert_eq!(uri.path().unwrap().as_str(), $res2.3);
1187             assert_eq!(uri.query().unwrap().as_str(), $res2.4);
1188             assert_eq!(uri.to_string(), $res2.5)
1189         }};
1190     }
1191 
1192     /// UT test cases for `build_from_builder`.
1193     ///
1194     /// # Brief
1195     /// 1. Creates UriBuilder by calling UriBuilder::new().
1196     /// 2. Sets Scheme by calling scheme().
1197     /// 3. Sets authority by calling authority().
1198     /// 4. Sets path by calling path().
1199     /// 5. Sets query by calling query().
1200     /// 6. Creates Uri by calling build().
1201     /// 7. Gets string slice value of uri components by calling as_str().
1202     /// 8. Gets string value of uri by calling to_string().
1203     /// 9. Checks if the test result is correct by assert_eq!().
1204     #[test]
build_from_builder()1205     fn build_from_builder() {
1206         test_builder_valid!(
1207             ("http", "hyper.rs:80", "/foo", "a=1"),
1208             (
1209                 "http",
1210                 "hyper.rs",
1211                 "80",
1212                 "/foo",
1213                 "a=1",
1214                 "http://hyper.rs:80/foo?a=1"
1215             )
1216         );
1217         test_builder_valid!(
1218             (Scheme::HTTP, "hyper.rs:80", "/foo", "a=1"),
1219             (
1220                 "http",
1221                 "hyper.rs",
1222                 "80",
1223                 "/foo",
1224                 "a=1",
1225                 "http://hyper.rs:80/foo?a=1"
1226             )
1227         );
1228         test_builder_valid!(
1229             ("https", "hyper.rs:80", "/foo", "a=1"),
1230             (
1231                 "https",
1232                 "hyper.rs",
1233                 "80",
1234                 "/foo",
1235                 "a=1",
1236                 "https://hyper.rs:80/foo?a=1"
1237             )
1238         );
1239         test_builder_valid!(
1240             (Scheme::HTTPS, "hyper.rs:80", "/foo", "a=1"),
1241             (
1242                 "https",
1243                 "hyper.rs",
1244                 "80",
1245                 "/foo",
1246                 "a=1",
1247                 "https://hyper.rs:80/foo?a=1"
1248             )
1249         );
1250     }
1251 
1252     /// UT test cases for `build_from_instance`.
1253     ///
1254     /// # Brief
1255     /// 1. Creates UriBuilder by calling Uri::builder().
1256     /// 2. Sets Scheme by calling scheme().
1257     /// 3. Sets authority by calling authority().
1258     /// 4. Sets path by calling path().
1259     /// 5. Sets query by calling query().
1260     /// 6. Creates Uri by calling build().
1261     /// 7. Gets string slice value of uri components by calling as_str().
1262     /// 8. Gets string value of uri by calling to_string().
1263     /// 9. Checks if the test result is correct by assert_eq!().
1264     #[test]
build_from_instance()1265     fn build_from_instance() {
1266         let uri = Uri::builder()
1267             .scheme(Scheme::HTTP)
1268             .authority("hyper.rs:80")
1269             .path("/foo")
1270             .query("a=1")
1271             .build()
1272             .unwrap();
1273         assert_eq!(uri.scheme().unwrap().as_str(), "http");
1274         assert_eq!(uri.host().unwrap().as_str(), "hyper.rs");
1275         assert_eq!(uri.port().unwrap().as_str(), "80");
1276         assert_eq!(uri.path().unwrap().as_str(), "/foo");
1277         assert_eq!(uri.query().unwrap().as_str(), "a=1");
1278         assert_eq!(uri.to_string(), "http://hyper.rs:80/foo?a=1")
1279     }
1280 
1281     /// UT test cases for `build_from_str`.
1282     ///
1283     /// # Brief
1284     /// 1. Creates Uri by calling from_bytes().
1285     /// 2. Gets string slice value of uri components by calling as_str().
1286     /// 3. Gets u16 value of port by call as_u16().
1287     /// 4. Gets string value of uri by calling to_string().
1288     /// 5. Checks if the test result is correct by assert_eq!().
1289     #[test]
build_from_str()1290     fn build_from_str() {
1291         let uri = Uri::from_bytes("http://hyper.rs:80/foo?a=1".as_bytes()).unwrap();
1292         assert_eq!(uri.scheme().unwrap().as_str(), "http");
1293         assert_eq!(uri.host().unwrap().as_str(), "hyper.rs");
1294         assert_eq!(uri.port().unwrap().as_str(), "80");
1295         assert_eq!(uri.port().unwrap().as_u16().unwrap(), 80);
1296         assert_eq!(uri.path().unwrap().as_str(), "/foo");
1297         assert_eq!(uri.query().unwrap().as_str(), "a=1");
1298         assert_eq!(uri.to_string(), "http://hyper.rs:80/foo?a=1")
1299     }
1300 
1301     /// UT test cases for `Scheme::default_port`.
1302     ///
1303     /// # Brief
1304     /// 1. Creates Scheme by calling `Scheme::from_bytes`.
1305     /// 3. Gets u16 value of port by calling `Scheme::default_port`.
1306     /// 5. Checks whether the default port is correct.
1307     #[test]
ut_uri_scheme_default_port()1308     fn ut_uri_scheme_default_port() {
1309         let scheme = Scheme::from_bytes(b"http").unwrap();
1310         assert_eq!(scheme.default_port(), 80);
1311         let scheme = Scheme::from_bytes(b"https").unwrap();
1312         assert_eq!(scheme.default_port(), 443);
1313     }
1314 
1315     /// UT test cases for `Uri::from_bytes`.
1316     ///
1317     /// # Brief
1318     /// 1. Creates Uri by calling `Uri::from_bytes()`.
1319     /// 2. Checks if the test results are correct.
1320     #[test]
ut_uri_from_bytes()1321     fn ut_uri_from_bytes() {
1322         macro_rules! uri_test_case {
1323             ($raw: expr, $tar: expr, $(,)?) => {
1324                 match (Uri::from_bytes($raw), $tar) {
1325                     (Ok(res), Ok(tar)) => assert_eq!(
1326                         (
1327                             res.scheme().map(|scheme| scheme.as_str()),
1328                             res.host().map(|host| host.as_str()),
1329                             res.port().map(|port| port.as_str()),
1330                             res.path().map(|path| path.as_str()),
1331                             res.query().map(|query| query.as_str()),
1332                         ),
1333                         tar,
1334                     ),
1335                     (Err(res), Err(tar)) => assert_eq!(res, tar),
1336                     _ => panic!("uri test case failed!"),
1337                 }
1338             };
1339         }
1340 
1341         uri_test_case!(
1342             b"httpss://www.example.com/",
1343             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidScheme))),
1344         );
1345 
1346         uri_test_case!(
1347             b"://www.example.com/",
1348             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidScheme))),
1349         );
1350 
1351         uri_test_case!(
1352             b"https://www.hu awei.com/",
1353             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1354         );
1355 
1356         uri_test_case!(
1357             br#"https://www.hu"awei.com/"#,
1358             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1359         );
1360 
1361         uri_test_case!(
1362             br#"https://www.hu"awei.com/"#,
1363             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1364         );
1365 
1366         uri_test_case!(
1367             br#"https://www.hu"<>\^`awei.com/"#,
1368             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1369         );
1370 
1371         uri_test_case!(
1372             br#"https://www.example.com:a0/"#,
1373             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidPort))),
1374         );
1375 
1376         uri_test_case!(
1377             br#"https://www.example.com:80/message/e<>mail"#,
1378             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1379         );
1380 
1381         uri_test_case!(
1382             br"https://www.example.com:80/message/email?name='\^'",
1383             Err(HttpError::from(ErrorKind::Uri(InvalidUri::InvalidByte))),
1384         );
1385 
1386         uri_test_case!(
1387             br#"https:/www.example.com:80/message/email?name=arya"#,
1388             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1389         );
1390 
1391         uri_test_case!(
1392             br#"https:/www.example.com:80"#,
1393             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1394         );
1395 
1396         uri_test_case!(
1397             br#"https:/www.example.com"#,
1398             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1399         );
1400 
1401         uri_test_case!(
1402             br#"https://www.huaw:ei.com:80"#,
1403             Err(HttpError::from(ErrorKind::Uri(
1404                 InvalidUri::InvalidAuthority
1405             ))),
1406         );
1407 
1408         uri_test_case!(
1409             br#"https://www.huaw:ei.com:80"#,
1410             Err(HttpError::from(ErrorKind::Uri(
1411                 InvalidUri::InvalidAuthority
1412             ))),
1413         );
1414 
1415         uri_test_case!(
1416             br#"https://name=1234@www.example.com:80/message/email?name=arya"#,
1417             Err(HttpError::from(ErrorKind::Uri(
1418                 InvalidUri::UriContainUserinfo
1419             ))),
1420         );
1421 
1422         uri_test_case!(
1423             br#"www.example.com:80/message/email?name=arya"#,
1424             Err(HttpError::from(ErrorKind::Uri(InvalidUri::UriMissScheme))),
1425         );
1426 
1427         uri_test_case!(
1428             br#"https://[0:0:0:0:0:0:0:0:80/message/email?name=arya"#,
1429             Err(HttpError::from(ErrorKind::Uri(
1430                 InvalidUri::InvalidAuthority
1431             ))),
1432         );
1433 
1434         uri_test_case!(
1435             br#"https:///foo?a=1"#,
1436             Err(HttpError::from(ErrorKind::Uri(
1437                 InvalidUri::UriMissAuthority
1438             ))),
1439         );
1440 
1441         uri_test_case!(
1442             b"https://www.example.com/",
1443             Ok((
1444                 Some("https"),
1445                 Some("www.example.com"),
1446                 None,
1447                 Some("/"),
1448                 None
1449             )),
1450         );
1451 
1452         uri_test_case!(
1453             b"https://www.example.com:80/foo?a=1",
1454             Ok((
1455                 Some("https"),
1456                 Some("www.example.com"),
1457                 Some("80"),
1458                 Some("/foo"),
1459                 Some("a=1"),
1460             )),
1461         );
1462 
1463         uri_test_case!(
1464             b"https://www.example.com:80/foo?a=1#fragment",
1465             Ok((
1466                 Some("https"),
1467                 Some("www.example.com"),
1468                 Some("80"),
1469                 Some("/foo"),
1470                 Some("a=1"),
1471             )),
1472         );
1473 
1474         uri_test_case!(
1475             b"https://www.example.com:80?a=1",
1476             Ok((
1477                 Some("https"),
1478                 Some("www.example.com"),
1479                 Some("80"),
1480                 None,
1481                 Some("a=1"),
1482             )),
1483         );
1484 
1485         uri_test_case!(
1486             b"https://www.example.com?a=1",
1487             Ok((
1488                 Some("https"),
1489                 Some("www.example.com"),
1490                 None,
1491                 None,
1492                 Some("a=1"),
1493             )),
1494         );
1495 
1496         uri_test_case!(
1497             b"https://www.example.com?",
1498             Ok((Some("https"), Some("www.example.com"), None, None, None)),
1499         );
1500 
1501         uri_test_case!(
1502             b"https://www.example.com:80",
1503             Ok((
1504                 Some("https"),
1505                 Some("www.example.com"),
1506                 Some("80"),
1507                 None,
1508                 None,
1509             )),
1510         );
1511 
1512         uri_test_case!(
1513             b"https://www.example.com",
1514             Ok((Some("https"), Some("www.example.com"), None, None, None)),
1515         );
1516 
1517         uri_test_case!(
1518             b"https://www.example.com#fragment",
1519             Ok((Some("https"), Some("www.example.com"), None, None, None)),
1520         );
1521 
1522         uri_test_case!(
1523             b"www.example.com",
1524             Ok((None, Some("www.example.com"), None, None, None)),
1525         );
1526 
1527         uri_test_case!(
1528             b"/foo?a=1",
1529             Ok((None, None, None, Some("/foo"), Some("a=1"))),
1530         );
1531 
1532         uri_test_case!(
1533             b"https://[0:0:0:0:0:0:0:0]",
1534             Ok((Some("https"), Some("[0:0:0:0:0:0:0:0]"), None, None, None)),
1535         );
1536 
1537         uri_test_case!(
1538             b"https://[0:0:0:0:0:0:0:0]:80",
1539             Ok((
1540                 Some("https"),
1541                 Some("[0:0:0:0:0:0:0:0]"),
1542                 Some("80"),
1543                 None,
1544                 None,
1545             )),
1546         );
1547     }
1548 
1549     /// UT test cases for `Uri::authority`.
1550     ///
1551     /// # Brief
1552     /// 1. Creates Uri by calling `Uri::authority()`.
1553     /// 2. Checks if the test results are correct.
1554     #[test]
ut_uri_authority()1555     fn ut_uri_authority() {
1556         let uri = Uri::from_bytes(b"http://example.com:8080/foo?a=1").unwrap();
1557         let authority = uri.authority().unwrap();
1558         assert_eq!(authority.host.as_str(), "example.com");
1559         assert_eq!(authority.port().unwrap().as_str(), "8080");
1560     }
1561 
1562     /// UT test cases for `Uri::path_and_query`.
1563     ///
1564     /// # Brief
1565     /// 1. Creates Uri by calling `Uri::path_and_query()`.
1566     /// 2. Checks if the test results are correct.
1567     #[test]
ut_uri_path_and_query()1568     fn ut_uri_path_and_query() {
1569         let uri = Uri::from_bytes(b"http://example.com:8080/foo?a=1").unwrap();
1570         assert_eq!(uri.path_and_query().unwrap(), "/foo?a=1");
1571 
1572         let uri = Uri::from_bytes(b"http://example.com:8080").unwrap();
1573         assert_eq!(uri.path_and_query(), None);
1574     }
1575 }
1576