diff --git a/codegen/tests/tests.rs b/codegen/tests/tests.rs index 1a38b218..81ba66ec 100644 --- a/codegen/tests/tests.rs +++ b/codegen/tests/tests.rs @@ -8,8 +8,14 @@ fn run_mode(mode: &'static str) { config.mode = cfg_mode; config.src_base = PathBuf::from(format!("tests/{}", mode)); - config.target_rustcflags = Some("-L ../target/debug/ -L ../target/debug/deps/".to_owned()); + let flags = [ + "-L ../target/debug/", + "-L ../target/debug/deps/", + "-L target/debug/", + "-L target/debug/deps/" + ].join(" "); + config.target_rustcflags = Some(flags); compiletest::run_tests(&config); } diff --git a/examples/extended_validation/src/files.rs b/examples/extended_validation/src/files.rs index da31c529..80e1c752 100644 --- a/examples/extended_validation/src/files.rs +++ b/examples/extended_validation/src/files.rs @@ -1,13 +1,14 @@ -use rocket; -use std::fs::File; -use std::io::Error as IOError; +use rocket::response::NamedFile; -#[get(path = "/")] -pub fn index() -> File { - File::open("static/index.html").unwrap() +use std::io; +use std::path::{Path, PathBuf}; + +#[get("/")] +fn index() -> io::Result { + NamedFile::open("static/index.html") } -#[get("/")] -pub fn files(file: &str) -> Result { - File::open(format!("static/{}", file)) +#[get("/")] +fn files(file: PathBuf) -> io::Result { + NamedFile::open(Path::new("static/").join(file)) } diff --git a/examples/forms/src/files.rs b/examples/forms/src/files.rs index 63c0c3d9..80e1c752 100644 --- a/examples/forms/src/files.rs +++ b/examples/forms/src/files.rs @@ -1,13 +1,14 @@ -use rocket; -use std::fs::File; -use std::io::Error as IOError; +use rocket::response::NamedFile; -#[route(GET, path = "/")] -pub fn index() -> File { - File::open("static/index.html").unwrap() +use std::io; +use std::path::{Path, PathBuf}; + +#[get("/")] +fn index() -> io::Result { + NamedFile::open("static/index.html") } -#[route(GET, path = "/")] -pub fn files(file: &str) -> Result { - File::open(format!("static/{}", file)) +#[get("/")] +fn files(file: PathBuf) -> io::Result { + NamedFile::open(Path::new("static/").join(file)) } diff --git a/examples/static_files/src/main.rs b/examples/static_files/src/main.rs index 459e6c73..f66cd249 100644 --- a/examples/static_files/src/main.rs +++ b/examples/static_files/src/main.rs @@ -4,18 +4,18 @@ extern crate rocket; use rocket::Rocket; -use std::fs::File; -use std::io::Error as IOError; +use std::io; +use rocket::response::NamedFile; use std::path::{Path, PathBuf}; #[get("/")] -fn index() -> File { - File::open("static/index.html").unwrap() +fn index() -> io::Result { + NamedFile::open("static/index.html") } #[get("/")] -fn files(file: PathBuf) -> Result { - File::open(Path::new("static/").join(file)) +fn files(file: PathBuf) -> io::Result { + NamedFile::open(Path::new("static/").join(file)) } fn main() { diff --git a/examples/todo/src/static_files.rs b/examples/todo/src/static_files.rs index aa32f53a..61ed862a 100644 --- a/examples/todo/src/static_files.rs +++ b/examples/todo/src/static_files.rs @@ -1,8 +1,8 @@ -use std::fs::File; +use rocket::response::NamedFile; use std::io; use std::path::{Path, PathBuf}; #[get("/", rank = 5)] -fn all(path: PathBuf) -> io::Result { - File::open(Path::new("static/").join(path)) +fn all(path: PathBuf) -> io::Result { + NamedFile::open(Path::new("static/").join(path)) } diff --git a/lib/src/response/data_type.rs b/lib/src/response/data_type.rs index 27f4bbae..6d312074 100644 --- a/lib/src/response/data_type.rs +++ b/lib/src/response/data_type.rs @@ -18,3 +18,5 @@ impl_data_type_responder!(JSON: Application/Json); impl_data_type_responder!(XML: Application/Xml); impl_data_type_responder!(HTML: Text/Html); impl_data_type_responder!(Plain: Text/Plain); +impl_data_type_responder!(CSS: Text/Css); +impl_data_type_responder!(JavaScript: Application/Javascript); diff --git a/lib/src/response/mod.rs b/lib/src/response/mod.rs index 5e06ee38..b03d793a 100644 --- a/lib/src/response/mod.rs +++ b/lib/src/response/mod.rs @@ -5,6 +5,7 @@ mod with_status; mod outcome; mod flash; mod data_type; +mod named_file; pub use hyper::server::Response as HyperResponse; pub use hyper::net::Fresh as HyperFresh; @@ -19,6 +20,7 @@ pub use self::redirect::Redirect; pub use self::with_status::StatusResponse; pub use self::outcome::Outcome; pub use self::flash::Flash; +pub use self::named_file::NamedFile; use std::ops::{Deref, DerefMut}; diff --git a/lib/src/response/named_file.rs b/lib/src/response/named_file.rs new file mode 100644 index 00000000..f8803839 --- /dev/null +++ b/lib/src/response/named_file.rs @@ -0,0 +1,48 @@ +use response::*; +use std::fs::File; +use std::path::{Path, PathBuf}; +use response::mime::{Mime, TopLevel, SubLevel}; +use std::io; + +pub struct NamedFile(PathBuf, File); + +impl NamedFile { + pub fn open>(path: P) -> io::Result { + let file = File::open(path.as_ref())?; + Ok(NamedFile(path.as_ref().to_path_buf(), file)) + } + + pub fn path(&self) -> &Path { + self.0.as_path() + } +} + +impl Responder for NamedFile { + fn respond<'a>(&mut self, mut res: FreshHyperResponse<'a>) -> Outcome<'a> { + if let Some(ext) = self.path().extension() { + let ext_string = ext.to_string_lossy().to_lowercase(); + let (top_level, sub_level) = match ext_string.as_str() { + "txt" => (TopLevel::Text, SubLevel::Plain), + "html" => (TopLevel::Text, SubLevel::Html), + "xml" => (TopLevel::Application, SubLevel::Xml), + "js" => (TopLevel::Application, SubLevel::Javascript), + "css" => (TopLevel::Text, SubLevel::Css), + "json" => (TopLevel::Application, SubLevel::Json), + "png" => (TopLevel::Image, SubLevel::Png), + "gif" => (TopLevel::Image, SubLevel::Gif), + "bmp" => (TopLevel::Image, SubLevel::Bmp), + "jpeg" => (TopLevel::Image, SubLevel::Jpeg), + "jpg" => (TopLevel::Image, SubLevel::Jpeg), + _ => (TopLevel::Star, SubLevel::Star), + }; + + if top_level != TopLevel::Star && sub_level != SubLevel::Star { + let mime = Mime(top_level, sub_level, vec![]); + res.headers_mut().set(header::ContentType(mime)); + } + } + + self.1.respond(res) + } +} + diff --git a/lib/src/response/stream.rs b/lib/src/response/stream.rs index 3e58d7b1..92523712 100644 --- a/lib/src/response/stream.rs +++ b/lib/src/response/stream.rs @@ -1,4 +1,3 @@ -// TODO: Allow streamed responses. // const CHUNK_SIZE: u32 = 4096; // pub struct Stream(T); // impl Responder for Stream { diff --git a/lib/src/rocket.rs b/lib/src/rocket.rs index 5ebfbefe..d3d47e4c 100644 --- a/lib/src/rocket.rs +++ b/lib/src/rocket.rs @@ -52,7 +52,10 @@ impl Rocket { // Dispatch the request to the handler and update the cookies. let mut responder = (route.handler)(&request); - res.headers_mut().set(SetCookie(request.cookies().delta())); + let cookie_delta = request.cookies().delta(); + if cookie_delta.len() > 0 { + res.headers_mut().set(SetCookie(cookie_delta)); + } // Get the response. let outcome = responder.respond(res);