diff --git a/core/lib/src/lib.rs b/core/lib/src/lib.rs index 0aafb253..937b531d 100644 --- a/core/lib/src/lib.rs +++ b/core/lib/src/lib.rs @@ -123,6 +123,7 @@ pub mod handler; pub mod fairing; pub mod error; pub mod catcher; +pub mod router; // Reexport of HTTP everything. pub mod http { @@ -139,7 +140,6 @@ pub mod http { } mod shutdown; -mod router; mod rocket; mod server; mod codegen; @@ -153,7 +153,7 @@ mod cookies; #[doc(inline)] pub use crate::data::Data; #[doc(inline)] pub use crate::config::Config; #[doc(inline)] pub use crate::catcher::Catcher; -pub use crate::router::Route; +#[doc(inline)] pub use crate::router::Route; pub use crate::request::Request; pub use crate::rocket::Rocket; pub use crate::shutdown::Shutdown; diff --git a/core/lib/src/router/mod.rs b/core/lib/src/router/mod.rs index 95487101..d1ef2fb5 100644 --- a/core/lib/src/router/mod.rs +++ b/core/lib/src/router/mod.rs @@ -10,14 +10,13 @@ use crate::http::Method; use crate::handler::dummy; pub use self::route::Route; -pub use self::segment::Segment; pub use self::uri::RouteUri; // type Selector = (Method, usize); type Selector = Method; #[derive(Debug, Default)] -pub struct Router { +pub(crate) struct Router { routes: HashMap>, } diff --git a/core/lib/src/router/uri.rs b/core/lib/src/router/uri.rs index a3c31efe..efabc658 100644 --- a/core/lib/src/router/uri.rs +++ b/core/lib/src/router/uri.rs @@ -3,18 +3,64 @@ use std::borrow::Cow; use crate::http::uri::{self, Origin}; use crate::http::ext::IntoOwned; -use crate::router::Segment; use crate::form::ValueField; +use crate::router::segment::Segment; +/// A URI or a route, used to match against requests. +/// +/// A route URI is composed of two components: +/// +/// * `base` +/// +/// Otherwise known as the route's "mount point", the `base` is a static +/// [`Origin`] that prefixes the route URI. All route URIs have a `base`. +/// When routes are created manually with [`Route::new()`], the base +/// defaults to `/`. When mounted via [`Rocket::mount()`], the base is +/// explicitly specified as the first argument. +/// +/// ```rust +/// use rocket::Route; +/// use rocket::http::Method; +/// # use rocket::handler::dummy as handler; +/// +/// let route = Route::new(Method::Get, "/foo/", handler); +/// assert_eq!(route.uri.base(), "/"); +/// +/// let rocket = rocket::ignite().mount("/base", vec![route]); +/// let routes: Vec<_> = rocket.routes().collect(); +/// assert_eq!(routes[0].uri.base(), "/base"); +/// ``` +/// +/// * `origin` +/// +/// Otherwise known as the "route URI", the `origin` is an [`Origin`] with +/// potentially dynamic (`` or ``) segments. It is prefixed with +/// the `base`. This is the URI which is matched against incoming requests +/// for routing. +/// +/// ```rust +/// use rocket::Route; +/// use rocket::http::Method; +/// # use rocket::handler::dummy as handler; +/// +/// let route = Route::new(Method::Get, "/foo/", handler); +/// assert_eq!(route.uri, "/foo/"); +/// +/// let rocket = rocket::ignite().mount("/base", vec![route]); +/// let routes: Vec<_> = rocket.routes().collect(); +/// assert_eq!(routes[0].uri, "/base/foo/"); +/// ``` +/// +/// [`Rocket::mount()`]: crate::Rocket::mount() #[derive(Clone)] pub struct RouteUri<'a> { /// The source string for this URI. source: Cow<'a, str>, - /// The mount point of this `Route`. + /// The mount point. pub base: Origin<'a>, - /// The URI _without_ the `base`. + /// The URI _without_ the `base` mount point. pub unmounted_origin: Origin<'a>, - /// The URI _with_ the base. This is the canoncical route URI. + /// The URI _with_ the base mount point. This is the canoncical route URI. pub origin: Origin<'a>, /// Cached metadata about this URI. pub(crate) metadata: Metadata, @@ -154,33 +200,12 @@ impl<'a> RouteUri<'a> { &self.source } - #[inline(always)] - - /// The full URI as an [`&Origin`][`crate::http::uri::Origin`]. - /// - /// # Example - /// - /// ```rust - /// use rocket::Route; - /// use rocket::http::{Method, uri::Origin}; - /// # use rocket::handler::{dummy as handler, Outcome, HandlerFuture}; - /// - /// let index = Route::new(Method::Get, "/foo/bar?a=1", handler); - /// assert_eq!(index.uri.as_origin(), &Origin::parse("/foo/bar?a=1").unwrap()); - /// let index = index.map_base(|base| format!("{}{}", "/boo", base)).unwrap(); - /// assert_eq!(index.uri.as_origin(), &Origin::parse("/boo/foo/bar?a=1").unwrap()); - /// ``` - pub fn as_origin(&self) -> &Origin<'a> { - &self.origin - } - - /// Get the default rank of a route with this URI. /// /// The route's default rank is determined based on the presence or absence /// of static and dynamic paths and queries. See the documentation for /// [`Route::new`][`crate::Route::new`] for a table summarizing the exact default ranks. - pub fn default_rank(&self) -> isize { + pub(crate) fn default_rank(&self) -> isize { let static_path = self.metadata.static_path; let wild_query = self.query().map(|_| self.metadata.wild_query); match (static_path, wild_query) { @@ -229,7 +254,7 @@ impl<'a> std::ops::Deref for RouteUri<'a> { type Target = Origin<'a>; fn deref(&self) -> &Self::Target { - self.as_origin() + &self.origin } } @@ -243,7 +268,20 @@ impl fmt::Debug for RouteUri<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RouteUri") .field("base", &self.base) - .field("uri", &self.as_origin()) + .field("unmounted_origin", &self.unmounted_origin) + .field("origin", &self.origin) .finish() } } + +impl<'a, 'b> PartialEq> for RouteUri<'a> { + fn eq(&self, other: &Origin<'b>) -> bool { &self.origin == other } +} + +impl PartialEq for RouteUri<'_> { + fn eq(&self, other: &str) -> bool { self.as_str() == other } +} + +impl PartialEq<&str> for RouteUri<'_> { + fn eq(&self, other: &&str) -> bool { self.as_str() == *other } +}