mirror of https://github.com/rwf2/Rocket.git
Avoid using 'glob' to walk templates directory.
Previously, `dyn_templates` walked the user-provided `template_dir` path by constructing a glob pattern prefixed with `template_dir`. If `template_dir` contained characters recognized by the glob pattern parser, then at best the pattern failed to parse, and at worst, incorrect directories were searched. This commit removes the use of `glob` to walk the templates directory and instead uses `walkdir`, obviating the issues described above. Fixes #2627.
This commit is contained in:
parent
a32ea70835
commit
a7536a3c6e
|
@ -17,7 +17,7 @@ tera = ["tera_"]
|
|||
handlebars = ["handlebars_"]
|
||||
|
||||
[dependencies]
|
||||
glob = "0.3"
|
||||
walkdir = "2.4"
|
||||
notify = "6"
|
||||
normpath = "1"
|
||||
|
||||
|
|
|
@ -26,6 +26,12 @@ impl Context {
|
|||
/// template engine, and store all of the initialized state in a `Context`
|
||||
/// structure, which is returned if all goes well.
|
||||
pub fn initialize(root: &Path, callback: &Callback) -> Option<Context> {
|
||||
fn is_file_with_ext(entry: &walkdir::DirEntry, ext: &str) -> bool {
|
||||
let is_file = entry.file_type().is_file();
|
||||
let has_ext = entry.path().extension().map_or(false, |e| e == ext);
|
||||
is_file && has_ext
|
||||
}
|
||||
|
||||
let root = match root.normalize() {
|
||||
Ok(root) => root.into_path_buf(),
|
||||
Err(e) => {
|
||||
|
@ -35,18 +41,23 @@ impl Context {
|
|||
};
|
||||
|
||||
let mut templates: HashMap<String, TemplateInfo> = HashMap::new();
|
||||
for ext in Engines::ENABLED_EXTENSIONS {
|
||||
let mut glob_path = root.join("**").join("*");
|
||||
glob_path.set_extension(ext);
|
||||
let glob_path = glob_path.to_str().expect("valid glob path string");
|
||||
for &ext in Engines::ENABLED_EXTENSIONS {
|
||||
for entry in walkdir::WalkDir::new(&root).follow_links(true) {
|
||||
let entry = match entry {
|
||||
Ok(entry) if is_file_with_ext(&entry, ext) => entry,
|
||||
Ok(_) | Err(_) => continue,
|
||||
};
|
||||
|
||||
for path in glob::glob(glob_path).unwrap().filter_map(Result::ok) {
|
||||
let (name, data_type_str) = split_path(&root, &path);
|
||||
let (name, data_type_str) = split_path(&root, entry.path());
|
||||
if let Some(info) = templates.get(&*name) {
|
||||
warn_!("Template name '{}' does not have a unique path.", name);
|
||||
info_!("Existing path: {:?}", info.path);
|
||||
info_!("Additional path: {:?}", path);
|
||||
warn_!("Using existing path for template '{}'.", name);
|
||||
warn_!("Template name '{}' does not have a unique source.", name);
|
||||
match info.path {
|
||||
Some(ref path) => info_!("Existing path: {:?}", path),
|
||||
None => info_!("Existing Content-Type: {}", info.data_type),
|
||||
}
|
||||
|
||||
info_!("Additional path: {:?}", entry.path());
|
||||
warn_!("Keeping existing template '{}'.", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -55,7 +66,7 @@ impl Context {
|
|||
.unwrap_or(ContentType::Text);
|
||||
|
||||
templates.insert(name, TemplateInfo {
|
||||
path: Some(path.clone()),
|
||||
path: Some(entry.into_path()),
|
||||
engine_ext: ext,
|
||||
data_type,
|
||||
});
|
||||
|
|
|
@ -237,6 +237,16 @@ mod tera_tests {
|
|||
assert_eq!(md_rendered, Some((ContentType::HTML, ESCAPED_EXPECTED.into())));
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_globby_paths() {
|
||||
use rocket::local::asynchronous::Client;
|
||||
|
||||
let client = Client::debug(rocket()).await.unwrap();
|
||||
let req = client.get("/");
|
||||
let metadata = Metadata::from_request(&req).await.unwrap();
|
||||
assert!(metadata.contains_template("tera/[test]/html_test"));
|
||||
}
|
||||
|
||||
// u128 is not supported. enable when it is.
|
||||
// #[test]
|
||||
// fn test_tera_u128() {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{% extends "tera/base" %}
|
||||
{% block title %}{{ title }}{% endblock title %}
|
||||
{% block content %}
|
||||
{{ content }}
|
||||
{% endblock content %}
|
Loading…
Reference in New Issue