Clean up LaunchError docs. Add Rocket::{config, routes} example.

This commit also:

  * Cleans up the stored URIs in routes.
  * Removes LaunchError as a root export.
  * Adds a URI::base() method.
This commit is contained in:
Sergio Benitez 2017-06-12 15:08:34 -07:00
parent 7cf3367183
commit 3fcf6c43dc
7 changed files with 99 additions and 30 deletions

View File

@ -36,7 +36,7 @@ pub enum LaunchErrorKind {
Unknown(Box<::std::error::Error + Send + Sync>)
}
/// An error that occurred during launch.
/// An error that occurs during launch.
///
/// A `LaunchError` is returned by
/// [rocket::launch](/rocket/struct.Rocket.html#method.launch) when launching an
@ -64,7 +64,7 @@ pub enum LaunchErrorKind {
/// ```
///
/// When a value of this type panics, the corresponding error message is pretty
/// printed to the console. The following snippet illustrates this:
/// printed to the console. The following illustrates this:
///
/// ```rust
/// # if false {
@ -75,6 +75,18 @@ pub enum LaunchErrorKind {
/// drop(error);
/// # }
/// ```
///
/// # Usage
///
/// A `LaunchError` value should usually be allowed to `drop` without
/// inspection. There are two exceptions to this suggestion.
///
/// 1. If you are writing a library or high-level application on-top of
/// Rocket, you likely want to inspect the value before it drops to avoid a
/// Rocket-specific `panic!`. This typically means simply printing the
/// value.
///
/// 2. You want to display your own error messages.
pub struct LaunchError {
handled: AtomicBool,
kind: LaunchErrorKind

View File

@ -129,11 +129,11 @@ pub mod config;
pub mod data;
pub mod handler;
pub mod fairing;
pub mod error;
mod router;
mod rocket;
mod codegen;
mod error;
mod catcher;
mod ext;
@ -144,9 +144,9 @@ mod ext;
#[doc(inline)] pub use outcome::Outcome;
#[doc(inline)] pub use data::Data;
#[doc(inline)] pub use config::Config;
#[doc(inline)] pub use error::Error;
pub use router::Route;
pub use request::{Request, State};
pub use error::{Error, LaunchError};
pub use catcher::Catcher;
pub use rocket::Rocket;

View File

@ -485,9 +485,10 @@ impl Rocket {
}
for mut route in routes {
let path = format!("{}/{}", base, route.path);
let uri = URI::new(format!("{}/{}", base, route.uri));
route.set_base(base);
route.set_path(path);
route.set_uri(uri.to_string());
info_!("{}", route);
self.router.add(route);
@ -605,9 +606,7 @@ impl Rocket {
/// fn main() {
/// # if false { // We don't actually want to launch the server in an example.
/// rocket::ignite()
/// .attach(AdHoc::on_launch(|_| {
/// println!("Rocket is about to launch! You just see...");
/// }))
/// .attach(AdHoc::on_launch(|_| println!("Rocket is launching!")))
/// .launch();
/// # }
/// }
@ -646,7 +645,7 @@ impl Rocket {
/// documentation](/rocket/struct.LaunchError.html) for more
/// information.
///
/// # Examples
/// # Example
///
/// ```rust
/// # if false {
@ -691,13 +690,65 @@ impl Rocket {
})
}
/// Retrieves all of the mounted routes.
/// Returns an iterator over all of the routes mounted on this instance of
/// Rocket.
///
/// # Example
///
/// ```rust
/// # #![feature(plugin)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// use rocket::Rocket;
/// use rocket::fairing::AdHoc;
///
/// #[get("/hello")]
/// fn hello() -> &'static str {
/// "Hello, world!"
/// }
///
/// fn main() {
/// let rocket = rocket::ignite()
/// .mount("/", routes![hello])
/// .mount("/hi", routes![hello]);
///
/// for route in rocket.routes() {
/// match route.base() {
/// "/" => assert_eq!(route.uri.path(), "/hello"),
/// "/hi" => assert_eq!(route.uri.path(), "/hi/hello"),
/// _ => unreachable!("only /hello, /hi/hello are expected")
/// }
/// }
///
/// assert_eq!(rocket.routes().count(), 2);
/// }
/// ```
#[inline(always)]
pub fn routes<'a>(&'a self) -> impl Iterator<Item=&'a Route> + 'a {
self.router.routes()
}
/// Retrieve the active configuration.
/// Returns the active configuration.
///
/// # Example
///
/// ```rust
/// # #![feature(plugin)]
/// # #![plugin(rocket_codegen)]
/// # extern crate rocket;
/// use rocket::Rocket;
/// use rocket::fairing::AdHoc;
///
/// fn main() {
/// # if false { // We don't actually want to launch the server in an example.
/// rocket::ignite()
/// .attach(AdHoc::on_launch(|rocket| {
/// println!("Rocket launch config: {:?}", rocket.config());
/// }))
/// .launch();
/// # }
/// }
/// ```
#[inline(always)]
pub fn config(&self) -> &Config {
&self.config

View File

@ -94,7 +94,7 @@ impl Collider for Route {
fn collides_with(&self, b: &Route) -> bool {
self.method == b.method
&& self.rank == b.rank
&& self.path.collides_with(&b.path)
&& self.uri.collides_with(&b.uri)
&& match (self.format.as_ref(), b.format.as_ref()) {
(Some(mt_a), Some(mt_b)) => mt_a.collides_with(mt_b),
(Some(_), None) => true,
@ -114,8 +114,8 @@ impl Collider for Route {
impl<'r> Collider<Request<'r>> for Route {
fn collides_with(&self, req: &Request<'r>) -> bool {
self.method == req.method()
&& self.path.collides_with(req.uri())
&& self.path.query().map_or(true, |_| req.uri().query().is_some())
&& self.uri.collides_with(req.uri())
&& self.uri.query().map_or(true, |_| req.uri().query().is_some())
&& match self.format {
Some(ref mt_a) => match req.format() {
Some(ref mt_b) => mt_a.collides_with(mt_b),

View File

@ -241,7 +241,7 @@ mod test {
macro_rules! assert_ranked_routes {
($routes:expr, $to:expr, $want:expr) => ({
let router = router_with_routes($routes);
let route_path = route(&router, Get, $to).unwrap().path.as_str();
let route_path = route(&router, Get, $to).unwrap().uri.as_str();
assert_eq!(route_path as &str, $want as &str);
})
}
@ -296,7 +296,7 @@ mod test {
assert!(routed_to.len() == expected.len());
for (got, expected) in routed_to.iter().zip(expected.iter()) {
assert_eq!(got.rank, expected.0);
assert_eq!(got.path.as_str(), expected.1);
assert_eq!(got.uri.as_str(), expected.1);
}
})
}
@ -365,7 +365,7 @@ mod test {
let expected = &[$($want),+];
assert!(routed_to.len() == expected.len());
for (got, expected) in routed_to.iter().zip(expected.iter()) {
assert_eq!(got.path.as_str(), expected as &str);
assert_eq!(got.uri.as_str(), expected as &str);
}
})
}

View File

@ -16,9 +16,9 @@ pub struct Route {
pub handler: Handler,
/// The base mount point of this `Route`.
pub base: URI<'static>,
/// The path (in Rocket format) that should be matched against. This path
/// The uri (in Rocket format) that should be matched against. This uri
/// already includes the base mount point.
pub path: URI<'static>,
pub uri: URI<'static>,
/// The rank of this route. Lower ranks have higher priorities.
pub rank: isize,
/// The media type this route matches against.
@ -51,25 +51,31 @@ impl Route {
handler: handler,
rank: default_rank(&uri),
base: URI::from("/"),
path: uri,
uri: uri,
format: None,
}
}
/// Creates a new route with the given rank, method, path, and handler.
pub fn ranked<S>(rank: isize, m: Method, path: S, handler: Handler) -> Route
pub fn ranked<S>(rank: isize, m: Method, uri: S, handler: Handler) -> Route
where S: AsRef<str>
{
Route {
method: m,
handler: handler,
base: URI::from("/"),
path: URI::from(path.as_ref().to_string()),
uri: URI::from(uri.as_ref().to_string()),
rank: rank,
format: None,
}
}
/// Retrieves the base mount point of this route.
#[inline]
pub fn base(&self) -> &str {
self.base.path()
}
/// Sets the base mount point of the route. Does not update the rank or any
/// other parameters.
pub fn set_base<S>(&mut self, path: S) where S: AsRef<str> {
@ -78,8 +84,8 @@ impl Route {
/// Sets the path of the route. Does not update the rank or any other
/// parameters.
pub fn set_path<S>(&mut self, path: S) where S: AsRef<str> {
self.path = URI::from(path.as_ref().to_string());
pub fn set_uri<S>(&mut self, uri: S) where S: AsRef<str> {
self.uri = URI::from(uri.as_ref().to_string());
}
// FIXME: Decide whether a component has to be fully variable or not. That
@ -88,11 +94,11 @@ impl Route {
/// Given a URI, returns a vector of slices of that URI corresponding to the
/// dynamic segments in this route.
pub(crate) fn get_param_indexes(&self, uri: &URI) -> Vec<(usize, usize)> {
let route_segs = self.path.segments();
let route_segs = self.uri.segments();
let uri_segs = uri.segments();
let start_addr = uri.path().as_ptr() as usize;
let mut result = Vec::with_capacity(self.path.segment_count());
let mut result = Vec::with_capacity(self.uri.segment_count());
for (route_seg, uri_seg) in route_segs.zip(uri_segs) {
let i = (uri_seg.as_ptr() as usize) - start_addr;
if route_seg.ends_with("..>") {
@ -115,7 +121,7 @@ impl Clone for Route {
handler: self.handler,
rank: self.rank,
base: self.base.clone(),
path: self.path.clone(),
uri: self.uri.clone(),
format: self.format.clone(),
}
}
@ -123,7 +129,7 @@ impl Clone for Route {
impl fmt::Display for Route {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} {}", Green.paint(&self.method), Blue.paint(&self.path))?;
write!(f, "{} {}", Green.paint(&self.method), Blue.paint(&self.uri))?;
if self.rank > 1 {
write!(f, " [{}]", White.paint(&self.rank))?;

View File

@ -8,7 +8,7 @@ use rocket::Route;
#[get("/<path..>")]
fn files(route: &Route, path: PathBuf) -> String {
format!("{}/{}", route.base.path(), path.to_string_lossy())
format!("{}/{}", route.base(), path.to_string_lossy())
}
mod route_guard_tests {