diff --git a/README.md b/README.md index 9502c6501..2f0a8355e 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,16 @@ Actix web is a small, fast, down-to-earth, open source rust web framework. ```rust,ignore use actix_web::*; -fn index(req: HttpRequest) -> String { - format!("Hello {}!", &req.match_info()["name"]) +fn index(req: HttpRequest) -> String +{ + format!("Hello {}!", + &req.match_info()["name"]) } fn main() { - HttpServer::new( - Application::new("/") - .resource("/{name}", |r| r.method(Method::GET).f(index))) + HttpServer::new(Application::new("/") + .resource("/{name}", + |r| r.method(Method::GET).f(index))) .serve::<_, ()>("127.0.0.1:8080"); } ``` diff --git a/examples/basic.rs b/examples/basic.rs index e6fe48227..c77d4adf6 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -80,7 +80,8 @@ fn main() { } })) // static files - .resource("/static", |r| r.h(fs::StaticFiles::new("examples/static/", true))) + .resource("/static/{tail:.*}", + |r| r.h(fs::StaticFiles::new("tail", "examples/static/", true))) // redirect .resource("/", |r| r.method(Method::GET).f(|req| { println!("{:?}", req); diff --git a/examples/websocket.rs b/examples/websocket.rs index 93b407464..124e4526e 100644 --- a/examples/websocket.rs +++ b/examples/websocket.rs @@ -67,7 +67,8 @@ fn main() { // websocket route .resource("/ws/", |r| r.method(Method::GET).f(ws_index)) // static files - .resource("/", |r| r.h(fs::StaticFiles::new("examples/static/", true)))) + .resource("/{tail:.*}", + |r| r.h(fs::StaticFiles::new("tail", "examples/static/", true)))) // start http server on 127.0.0.1:8080 .serve::<_, ()>("127.0.0.1:8080").unwrap(); diff --git a/guide/src/qs_12.md b/guide/src/qs_12.md index 7cabe7449..4d415baf5 100644 --- a/guide/src/qs_12.md +++ b/guide/src/qs_12.md @@ -25,7 +25,9 @@ fn main() { ## Directory To serve files from specific directory and sub-directories `StaticFiles` could be used. -`StaticFiles` could be registered with `Application::route` method. +`StaticFiles` could be registered with `Application::resource` method. +`StaticFiles` requires tail named path expression for resource registration. +And this name has to be used in `StaticFile` constructor. ```rust # extern crate actix_web; @@ -33,11 +35,12 @@ use actix_web::*; fn main() { Application::new("/") - .resource("/static", |r| r.h(fs::StaticFiles::new(".", true))) + .resource("/static/{tail:.*}", |r| r.h(fs::StaticFiles::new("tail", ".", true))) .finish(); } ``` -First parameter is a base directory. Second parameter is *show_index*, if it is set to *true* +First parameter is a name of path pattern. Second parameter is a base directory. +Third parameter is *show_index*, if it is set to *true* directory listing would be returned for directories, if it is set to *false* then *404 Not Found* would be returned instead of directory listing. diff --git a/src/fs.rs b/src/fs.rs index a5a015d1a..963cf2fc8 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -191,7 +191,8 @@ impl FromRequest for FilesystemElement { /// Static files handling /// -/// Can be registered with `Application::route_handler()`. +/// Can be registered with `Application::resource()`. Resource path has to contain +/// tail named pattern and this name has to be used in `StaticFile` constructor. /// /// ```rust /// # extern crate actix_web; @@ -199,11 +200,12 @@ impl FromRequest for FilesystemElement { /// /// fn main() { /// let app = Application::new("/") -/// .resource("/static", |r| r.h(fs::StaticFiles::new(".", true))) +/// .resource("/static/{tail:.*}", |r| r.h(fs::StaticFiles::new("tail", ".", true))) /// .finish(); /// } /// ``` pub struct StaticFiles { + name: String, directory: PathBuf, accessible: bool, show_index: bool, @@ -217,7 +219,7 @@ impl StaticFiles { /// `dir` - base directory /// /// `index` - show index for directory - pub fn new>(dir: D, index: bool) -> StaticFiles { + pub fn new>(name: &str, dir: D, index: bool) -> StaticFiles { let dir = dir.into(); let (dir, access) = match dir.canonicalize() { @@ -236,6 +238,7 @@ impl StaticFiles { }; StaticFiles { + name: name.to_owned(), directory: dir, accessible: access, show_index: index, @@ -253,7 +256,13 @@ impl Handler for StaticFiles { if !self.accessible { Err(io::Error::new(io::ErrorKind::NotFound, "not found")) } else { - let relpath = PathBuf::from_param(&req.path()[req.prefix_len()..]) + let path = if let Some(path) = req.match_info().get(&self.name) { + path + } else { + return Err(io::Error::new(io::ErrorKind::NotFound, "not found")) + }; + + let relpath = PathBuf::from_param(path) .map_err(|_| io::Error::new(io::ErrorKind::NotFound, "not found"))?; // full filepath @@ -291,7 +300,7 @@ mod tests { #[test] fn test_static_files() { - let mut st = StaticFiles::new(".", true); + let mut st = StaticFiles::new("tail", ".", true); st.accessible = false; assert!(st.handle(HttpRequest::default()).is_err()); @@ -299,8 +308,11 @@ mod tests { st.show_index = false; assert!(st.handle(HttpRequest::default()).is_err()); + let mut req = HttpRequest::default(); + req.match_info_mut().add("tail", ""); + st.show_index = true; - let resp = st.handle(HttpRequest::default()).from_request(HttpRequest::default()).unwrap(); + let resp = st.handle(req).from_request(HttpRequest::default()).unwrap(); assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/html; charset=utf-8"); assert!(resp.body().is_binary()); assert!(format!("{:?}", resp.body()).contains("README.md"));