Skip to content

Commit

Permalink
More refactoring.
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonTeixidor committed Aug 25, 2015
1 parent dc8043c commit 9169c1d
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 48 deletions.
10 changes: 9 additions & 1 deletion examples/mount.rs
Expand Up @@ -5,12 +5,20 @@ use nickel::{Nickel, Mountable, StaticFilesHandler};
fn main() {
let mut server = Nickel::new();

/*
* Requests to /t should not end up in this route. Expected output for
* a request to /test/a is /a.
*/
server.mount("/test/", middleware! { |req|
format!("Got request with uri={}", req.origin.uri)
});

/*
* Fall-through behaviour, if StaticFilesHandler does not find a matching file,
* the request uri must be reset so that it can be matched against other middleware.
*/
server.mount("/static/files/", StaticFilesHandler::new("examples/assets/"));
server.mount("/static/files/a", middleware! {
server.mount("/static/files/a/", middleware! {
"No static file called a!"
});

Expand Down
87 changes: 40 additions & 47 deletions src/mount.rs
Expand Up @@ -5,34 +5,35 @@ use middleware::{Continue, Middleware, MiddlewareResult};

use hyper::uri::RequestUri::AbsolutePath;

use std::mem;

pub trait Mountable {
fn mount<M: Middleware>(&mut self, mount_point: &str, middleware: M);
fn mount<M: Middleware>(&mut self, mount_point: &'static str, middleware: M);
}

impl Mountable for Nickel {
fn mount<M: Middleware>(&mut self, mount_point: &str, middleware: M) {
///
/// A trait that makes mounting more convenient. Works the same as
/// manually adding a `Mount` middleware.
///
///
/// # Examples
/// ```{rust}
/// use nickel::{Nickel, StaticFilesHandler, Mountable};
/// let mut server = Nickel::new();
///
/// server.mount("/static_files/", StaticFilesHandler::new("/path/to/serve/"));
/// ```
fn mount<M: Middleware>(&mut self, mount_point: &'static str, middleware: M) {
self.utilize(Mount::new(mount_point, middleware));
}
}

pub struct Mount<M: Middleware> {
mount_point: String,
mount_point: &'static str,
middleware: M
}

fn rewrite_mount_point(mount_point: &str) -> String {
let mut mount_point = mount_point.to_owned();
if let Some('/') = mount_point.chars().last() {
let _ = mount_point.pop();
}
if let Some('/') = mount_point.chars().nth(0) {
mount_point
} else {
mount_point.insert(0, '/');
mount_point
}
}

impl<M: Middleware> Mount<M> {
///
/// Creates a new middleware that mounts a middleware at a mount point.
Expand All @@ -53,43 +54,35 @@ impl<M: Middleware> Mount<M> {
/// StaticFilesHandler::new("/path/to/serve/")
/// ));
/// ```
pub fn new(mount_point: &str, middleware: M) -> Mount<M> {
Mount {
/*
* Ensure that the mount_point string begins with a / but does not end
* with one.
*/
mount_point: rewrite_mount_point(mount_point),
middleware: middleware
pub fn new(mount_point: &'static str, middleware: M) -> Mount<M> {
match (mount_point.chars().last(), mount_point.chars().nth(0)) {
(Some('/'), Some('/')) =>
Mount {
/*
* Ensure that the mount_point string begins with a / but does not end
* with one.
*/
mount_point: mount_point,
middleware: middleware
},
_ => panic!("Mount points must have a leading and trailing slash.")
}
}
}

impl<M: Middleware> Middleware for Mount<M> {
fn invoke<'mw, 'conn>(&'mw self, req: &mut Request<'mw, 'conn>, res: Response<'mw>)
-> MiddlewareResult<'mw> {
if let AbsolutePath(path) = req.origin.uri.clone() {
if path.len() >= self.mount_point.len()
&& &*self.mount_point == &path[0..self.mount_point.len()] {
req.origin.uri = AbsolutePath(path[self.mount_point.len()..].to_owned());
let ret_val = self.middleware.invoke(req, res);
/*
* Restore original uri again, so that middleware further down
* the chain won't get the modified one.
*/
req.origin.uri = AbsolutePath(path);
return ret_val;
}
}
Ok(Continue(res))
}
}
let subpath = match req.origin.uri {
AbsolutePath(ref path) if path.starts_with(self.mount_point) => {
AbsolutePath("/".chars().chain(path[self.mount_point.len()..].chars()).collect())
},
_ => return Ok(Continue(res))
};

#[test]
fn mount_point_rewrites() {
assert_eq!(rewrite_mount_point("/"), "/");
assert_eq!(rewrite_mount_point("/a"), "/a");
assert_eq!(rewrite_mount_point("/a/"), "/a");
assert_eq!(rewrite_mount_point("a/"), "/a");
assert_eq!(rewrite_mount_point("a"), "/a");
let original = mem::replace(&mut req.origin.uri, subpath);
let result = self.middleware.invoke(req, res);
req.origin.uri = original;
result
}
}

0 comments on commit 9169c1d

Please sign in to comment.