diff --git a/CHANGES.md b/CHANGES.md index 1b149db8..acf8ddf3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,10 @@ * Added HttpRequest::mime_type() method +* Added StaticFiles::index_file() + +* Added basic websocket client + ## 0.3.3 (2018-01-25) diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index cea4732e..1319a88d 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -55,7 +55,8 @@ fn main() { // websocket route .resource("/ws/", |r| r.method(Method::GET).f(ws_index)) // static files - .handler("/", fs::StaticFiles::new("../static/", true))) + .handler("/", fs::StaticFiles::new("../static/", true) + .index_file("index.html"))) // start http server on 127.0.0.1:8080 .bind("127.0.0.1:8080").unwrap() .start(); diff --git a/guide/src/qs_12.md b/guide/src/qs_12.md index 28670935..2b17bed6 100644 --- a/guide/src/qs_12.md +++ b/guide/src/qs_12.md @@ -42,3 +42,8 @@ fn main() { First parameter is a base directory. Second 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. + +Instead of showing files listing for directory, it is possible to redirect to specific +index file. Use +[*StaticFiles::index_file()*](../actix_web/s/struct.StaticFiles.html#method.index_file) +method to configure this redirect. diff --git a/src/fs.rs b/src/fs.rs index 7a4dd229..547a3c41 100644 --- a/src/fs.rs +++ b/src/fs.rs @@ -15,7 +15,7 @@ use handler::{Handler, Responder}; use headers::ContentEncoding; use httprequest::HttpRequest; use httpresponse::HttpResponse; -use httpcodes::HTTPOk; +use httpcodes::{HTTPOk, HTTPFound}; /// A file with an associated name; responds with the Content-Type based on the /// file extension. @@ -177,6 +177,7 @@ impl Responder for Directory { pub enum FilesystemElement { File(NamedFile), Directory(Directory), + Redirect(HttpResponse), } impl Responder for FilesystemElement { @@ -187,6 +188,7 @@ impl Responder for FilesystemElement { match self { FilesystemElement::File(file) => file.respond_to(req), FilesystemElement::Directory(dir) => dir.respond_to(req), + FilesystemElement::Redirect(resp) => Ok(resp), } } } @@ -210,6 +212,7 @@ impl Responder for FilesystemElement { pub struct StaticFiles { directory: PathBuf, accessible: bool, + index: Option, show_index: bool, _chunk_size: usize, _follow_symlinks: bool, @@ -221,7 +224,7 @@ impl StaticFiles { /// `dir` - base directory /// /// `index` - show index for directory - pub fn new>(dir: D, index: bool) -> StaticFiles { + pub fn new>(dir: T, index: bool) -> StaticFiles { let dir = dir.into(); let (dir, access) = match dir.canonicalize() { @@ -242,12 +245,21 @@ impl StaticFiles { StaticFiles { directory: dir, accessible: access, + index: None, show_index: index, _chunk_size: 0, _follow_symlinks: false, } } + /// Set index file + /// + /// Redirects to specific index file for directory "/" instead of + /// showing files listing. + pub fn index_file>(mut self, index: T) -> StaticFiles { + self.index = Some(index.into()); + self + } } impl Handler for StaticFiles { @@ -270,7 +282,15 @@ impl Handler for StaticFiles { let path = self.directory.join(&relpath).canonicalize()?; if path.is_dir() { - if self.show_index { + if let Some(ref redir_index) = self.index { + let mut base = Path::new(req.path()).join(relpath); + base.push(redir_index); + Ok(FilesystemElement::Redirect( + HTTPFound + .build() + .header("LOCATION", base.to_string_lossy().as_ref()) + .finish().unwrap())) + } else if self.show_index { Ok(FilesystemElement::Directory(Directory::new(self.directory.clone(), path))) } else { Err(io::Error::new(io::ErrorKind::NotFound, "not found")) @@ -285,7 +305,7 @@ impl Handler for StaticFiles { #[cfg(test)] mod tests { use super::*; - use http::header; + use http::{header, StatusCode}; #[test] fn test_named_file() { @@ -318,4 +338,15 @@ mod tests { assert!(resp.body().is_binary()); assert!(format!("{:?}", resp.body()).contains("README.md")); } + + #[test] + fn test_redirec_to_index() { + let mut st = StaticFiles::new(".", false).index_file("index.html"); + let mut req = HttpRequest::default(); + req.match_info_mut().add("tail", "guide"); + + let resp = st.handle(req).respond_to(HttpRequest::default()).unwrap(); + assert_eq!(resp.status(), StatusCode::FOUND); + assert_eq!(resp.headers().get(header::LOCATION).unwrap(), "/guide/index.html"); + } }