Skip to content

Commit

Permalink
Fix normalization and Windows issues.
Browse files Browse the repository at this point in the history
  • Loading branch information
SergioBenitez committed Oct 24, 2018
1 parent e0973d9 commit 26db5ec
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 64 deletions.
8 changes: 8 additions & 0 deletions contrib/lib/src/templates/fairing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ mod context {
crate fn context<'a>(&'a self) -> impl Deref<Target=Context> + 'a {
&self.0
}

crate fn is_reloading(&self) -> bool {
false
}
}
}

Expand Down Expand Up @@ -75,6 +79,10 @@ mod context {
self.context.read().unwrap()
}

crate fn is_reloading(&self) -> bool {
self.watcher.is_some()
}

fn context_mut<'a>(&'a self) -> impl DerefMut<Target=Context> + 'a {
self.context.write().unwrap()
}
Expand Down
26 changes: 26 additions & 0 deletions contrib/lib/src/templates/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,13 @@ impl<'a> Metadata<'a> {
/// # Example
///
/// ```rust
/// # #![feature(proc_macro_hygiene, decl_macro)]
/// # #[macro_use] extern crate rocket;
/// # extern crate rocket_contrib;
/// #
/// use rocket_contrib::templates::Metadata;
///
/// #[get("/")]
/// fn handler(metadata: Metadata) {
/// // Returns `true` if the template with name `"name"` was loaded.
/// let loaded = metadata.contains_template("name");
Expand All @@ -56,6 +61,27 @@ impl<'a> Metadata<'a> {
pub fn contains_template(&self, name: &str) -> bool {
self.0.context().templates.contains_key(name)
}

/// Returns `true` if template reloading is enabled.
///
/// # Example
///
/// ```rust
/// # #![feature(proc_macro_hygiene, decl_macro)]
/// # #[macro_use] extern crate rocket;
/// # extern crate rocket_contrib;
/// #
/// use rocket_contrib::templates::Metadata;
///
/// #[get("/")]
/// fn handler(metadata: Metadata) {
/// // Returns `true` if template reloading is enabled.
/// let reloading = metadata.reloading();
/// }
/// ```
pub fn reloading(&self) -> bool {
self.0.is_reloading()
}
}

/// Retrieves the template metadata. If a template fairing hasn't been attached,
Expand Down
15 changes: 13 additions & 2 deletions contrib/lib/tests/templates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ mod templates_tests {
}
}

#[get("/is_reloading")]
fn is_reloading(md: Metadata) -> Option<()> {
if md.reloading() { Some(()) } else { None }
}

fn template_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("tests").join("templates")
}
Expand All @@ -32,7 +37,7 @@ mod templates_tests {
.expect("valid configuration");

::rocket::custom(config).attach(Template::fairing())
.mount("/", routes![template_check])
.mount("/", routes![template_check, is_reloading])
}

#[cfg(feature = "tera_templates")]
Expand Down Expand Up @@ -142,8 +147,14 @@ mod templates_tests {
let reload_path = template_root().join("hbs").join("reload.txt.hbs");
write_file(&reload_path, INITIAL_TEXT);

// verify that the initial content is correct
// set up the client. if we can't reload templates, then just quit
let client = Client::new(rocket()).unwrap();
let res = client.get("/is_reloading").dispatch();
if res.status() != Status::Ok {
return;
}

// verify that the initial content is correct
let initial_rendered = Template::show(client.rocket(), RELOAD_TEMPLATE, ());
assert_eq!(initial_rendered, Some(INITIAL_TEXT.into()));

Expand Down
2 changes: 1 addition & 1 deletion contrib/lib/tests/templates/hbs/reload.txt.hbs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
reload
initial
11 changes: 4 additions & 7 deletions core/codegen/tests/compile-test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use std::{io, fs::Metadata, time::SystemTime};

#[derive(Copy, Clone)]
enum Kind {
Dynamic, Static
#[allow(dead_code)]
Dynamic,
Static
}

impl Kind {
Expand All @@ -17,11 +19,6 @@ impl Kind {
Kind::Static => ".rlib"
}
}

fn prefix(self) -> &'static str {
#[cfg(windows)] { "" }
#[cfg(not(windows))] { "lib" }
}
}

fn target_path() -> PathBuf {
Expand Down Expand Up @@ -52,7 +49,7 @@ fn best_time_for(metadata: &Metadata) -> SystemTime {

fn extern_dep(name: &str, kind: Kind) -> io::Result<String> {
let deps_root = target_path().join("deps");
let dep_name = format!("{}{}", kind.prefix(), name);
let dep_name = format!("lib{}", name);

let mut dep_path: Option<PathBuf> = None;
for entry in deps_root.read_dir().expect("read_dir call failed") {
Expand Down
5 changes: 3 additions & 2 deletions core/codegen/tests/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::fmt;
use std::path::PathBuf;

use rocket::{Request, Outcome::*};
use rocket::http::ext::Normalize;
use rocket::local::Client;
use rocket::data::{self, Data, FromDataSimple};
use rocket::request::Form;
Expand Down Expand Up @@ -48,7 +49,7 @@ fn post1(
simple: Simple,
) -> String {
let string = format!("{}, {}, {}, {}, {}, {}",
sky, name, a, query.field, path.display(), simple.0);
sky, name, a, query.field, path.normalized_str(), simple.0);

let uri = uri!(post2: a, name.url_decode_lossy(), path, sky, query.into_inner());

Expand All @@ -65,7 +66,7 @@ fn post2(
simple: Simple,
) -> String {
let string = format!("{}, {}, {}, {}, {}, {}",
sky, name, a, query.field, path.display(), simple.0);
sky, name, a, query.field, path.normalized_str(), simple.0);

let uri = uri!(post2: a, name.url_decode_lossy(), path, sky, query.into_inner());

Expand Down
18 changes: 18 additions & 0 deletions core/http/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,21 @@ impl<'a, B: 'static + ToOwned + ?Sized> IntoOwned for Cow<'a, B> {
Cow::Owned(self.into_owned())
}
}

use std::path::Path;

pub trait Normalize {
fn normalized_str(&self) -> Cow<str>;
}

impl<T: AsRef<Path>> Normalize for T {
#[cfg(windows)]
fn normalized_str(&self) -> Cow<str> {
self.as_ref().to_string_lossy().replace('\\', "/").into()
}

#[cfg(not(windows))]
fn normalized_str(&self) -> Cow<str> {
self.as_ref().to_string_lossy()
}
}
10 changes: 5 additions & 5 deletions core/http/src/uri/uri_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt;
use std::path::{Path, PathBuf};
use std::borrow::Cow;

use {RawStr, uri::Uri};
use {RawStr, uri::Uri, ext::Normalize};

use percent_encoding::{utf8_percent_encode, DEFAULT_ENCODE_SET};

Expand Down Expand Up @@ -203,21 +203,21 @@ impl UriDisplay for String {
}
}

/// Percent-encodes each segment in the path.
/// Percent-encodes each segment in the path and normalizes separators.
impl UriDisplay for PathBuf {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let string = self.to_string_lossy();
let string = self.normalized_str();
let enc: Cow<str> = utf8_percent_encode(&string, PATH_ENCODE_SET).into();
write!(f, "{}", enc)
}
}

/// Percent-encodes each segment in the path.
/// Percent-encodes each segment in the and normalizes separators.
impl UriDisplay for Path {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let string = self.to_string_lossy();
let string = self.normalized_str();
let enc: Cow<str> = utf8_percent_encode(&string, PATH_ENCODE_SET).into();
write!(f, "{}", enc)
}
Expand Down
3 changes: 3 additions & 0 deletions core/lib/src/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,10 @@ impl Config {
///
/// assert_eq!(config.root(), current_dir().unwrap());
/// assert_eq!(config.root_relative("abc"), config.root().join("abc"));
/// # #[cfg(not(windows))]
/// assert_eq!(config.root_relative("/abc"), Path::new("/abc"));
/// # #[cfg(windows)]
/// # assert_eq!(config.root_relative("C:\\abc"), Path::new("C:\\abc"));
/// ```
pub fn root_relative<P: AsRef<Path>>(&self, path: P) -> PathBuf {
let path = path.as_ref();
Expand Down
38 changes: 1 addition & 37 deletions core/lib/src/ext.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use std::{fmt, io};
use std::borrow::Cow;
use std::path::{Path, PathBuf, Component};
use std::io;

pub trait ReadExt: io::Read {
fn read_max(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
Expand All @@ -19,37 +17,3 @@ pub trait ReadExt: io::Read {
}

impl<T: io::Read> ReadExt for T { }

pub struct NormalizedPath<'a>(&'a Path);

impl<'a> fmt::Display for NormalizedPath<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn to_str<'c>(c: &'c Component) -> Cow<'c, str> {
c.as_os_str().to_string_lossy()
}

let mut components = self.0.components();
match (components.next(), components.next()) {
(Some(Component::RootDir), Some(c)) => write!(f, "/{}", to_str(&c))?,
(Some(a), Some(b)) => write!(f, "{}/{}", to_str(&a), to_str(&b))?,
(Some(c), None) => write!(f, "{}", to_str(&c))?,
_ => return Ok(())
};

for c in components {
write!(f, "/{}", to_str(&c))?;
}

Ok(())
}
}

pub trait Normalize {
fn normalized(&self) -> NormalizedPath;
}

impl<T: AsRef<Path>> Normalize for T {
fn normalized(&self) -> NormalizedPath {
NormalizedPath(self.as_ref())
}
}
2 changes: 1 addition & 1 deletion core/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ extern crate isatty;
#[cfg(test)] #[macro_use] extern crate lazy_static;

#[doc(hidden)] #[macro_use] pub mod logger;
#[doc(hidden)] pub mod ext;
pub mod local;
pub mod request;
pub mod response;
Expand All @@ -142,6 +141,7 @@ mod router;
mod rocket;
mod codegen;
mod catcher;
mod ext;

#[doc(inline)] pub use response::Response;
#[doc(inline)] pub use handler::{Handler, ErrorHandler};
Expand Down
4 changes: 2 additions & 2 deletions core/lib/tests/route_guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
#[macro_use] extern crate rocket;

use std::path::{Path, PathBuf};
use rocket::ext::Normalize;
use rocket::http::ext::Normalize;
use rocket::Route;

#[get("/<path..>")]
fn files(route: &Route, path: PathBuf) -> String {
Path::new(route.base()).join(path).normalized().to_string()
Path::new(route.base()).join(path).normalized_str().to_string()
}

mod route_guard_tests {
Expand Down
6 changes: 3 additions & 3 deletions examples/manual_routes/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ extern crate rocket;
#[cfg(test)]
mod tests;

use std::io;
use std::{io, env};
use std::fs::File;

use rocket::{Request, Handler, Route, Data, Catcher};
Expand Down Expand Up @@ -43,7 +43,7 @@ fn upload<'r>(req: &'r Request, data: Data) -> Outcome<'r> {
return Outcome::failure(Status::BadRequest);
}

let file = File::create("/tmp/upload.txt");
let file = File::create(env::temp_dir().join("upload.txt"));
if let Ok(mut file) = file {
if let Ok(n) = io::copy(&mut data.open(), &mut file) {
return Outcome::from(req, format!("OK: {} bytes uploaded.", n));
Expand All @@ -58,7 +58,7 @@ fn upload<'r>(req: &'r Request, data: Data) -> Outcome<'r> {
}

fn get_upload<'r>(req: &'r Request, _: Data) -> Outcome<'r> {
Outcome::from(req, File::open("/tmp/upload.txt").ok())
Outcome::from(req, File::open(env::temp_dir().join("upload.txt")).ok())
}

fn not_found_handler<'r>(req: &'r Request) -> response::Result<'r> {
Expand Down
4 changes: 2 additions & 2 deletions examples/raw_upload/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

#[cfg(test)] mod tests;

use std::io;
use std::{io, env};
use rocket::Data;

#[post("/upload", format = "plain", data = "<data>")]
fn upload(data: Data) -> io::Result<String> {
data.stream_to_file("/tmp/upload.txt").map(|n| n.to_string())
data.stream_to_file(env::temp_dir().join("upload.txt")).map(|n| n.to_string())
}

#[get("/")]
Expand Down
6 changes: 4 additions & 2 deletions examples/raw_upload/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rocket::local::Client;
use rocket::http::{Status, ContentType};

use std::env;
use std::io::Read;
use std::fs::{self, File};

Expand All @@ -16,7 +17,8 @@ fn test_index() {
#[test]
fn test_raw_upload() {
// Delete the upload file before we begin.
let _ = fs::remove_file("/tmp/upload.txt");
let upload_file = env::temp_dir().join("upload.txt");
let _ = fs::remove_file(&upload_file);

// Do the upload. Make sure we get the expected results.
let client = Client::new(super::rocket()).unwrap();
Expand All @@ -30,7 +32,7 @@ fn test_raw_upload() {

// Ensure we find the body in the /tmp/upload.txt file.
let mut file_contents = String::new();
let mut file = File::open("/tmp/upload.txt").expect("open upload.txt file");
let mut file = File::open(&upload_file).expect("open upload.txt file");
file.read_to_string(&mut file_contents).expect("read upload.txt");
assert_eq!(&file_contents, UPLOAD_CONTENTS);
}

0 comments on commit 26db5ec

Please sign in to comment.