mirror of
https://github.com/rwf2/Rocket.git
synced 2025-01-18 23:49:09 +00:00
Use Figment's 'Value' in contrib templating.
Previously, 'serde_json::Value' was used to store the serialized template context. This value does not represent all of serde's data model. This means we may fail to serialize a valid Rust value into it, for instance, 128-bit integers. This is reduced with Figment's 'Value', which supports the majority if not all of the serde data model. At present, all supported templating engines use 'serde_json::Value', so in practice, this commit has no effect but to reduce local dependencies and provide better error messages for bad contexts.
This commit is contained in:
parent
a875da1666
commit
0b2fcb9f4b
@ -16,8 +16,6 @@ tera = ["tera_"]
|
|||||||
handlebars = ["handlebars_"]
|
handlebars = ["handlebars_"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serde = "1.0"
|
|
||||||
serde_json = "1.0.26"
|
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
notify = "4.0.6"
|
notify = "4.0.6"
|
||||||
normpath = "0.3"
|
normpath = "0.3"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::Serialize;
|
use rocket::serde::Serialize;
|
||||||
|
|
||||||
use crate::TemplateInfo;
|
use crate::TemplateInfo;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use serde::Serialize;
|
use rocket::serde::Serialize;
|
||||||
|
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
pub use crate::handlebars::Handlebars;
|
pub use crate::handlebars::Handlebars;
|
||||||
@ -29,12 +29,8 @@ impl Engine for Handlebars<'static> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
match Handlebars::render(self, name, &context) {
|
Handlebars::render(self, name, &context)
|
||||||
Ok(string) => Some(string),
|
.map_err(|e| error_!("Handlebars: {}", e))
|
||||||
Err(e) => {
|
.ok()
|
||||||
error_!("Error rendering Handlebars template '{}': {}", name, e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,8 +118,8 @@
|
|||||||
//!
|
//!
|
||||||
//! Templates are rendered with the `render` method. The method takes in the
|
//! Templates are rendered with the `render` method. The method takes in the
|
||||||
//! name of a template and a context to render the template with. The context
|
//! name of a template and a context to render the template with. The context
|
||||||
//! can be any type that implements [`Serialize`] from [`serde`] and would
|
//! can be any type that implements [`Serialize`] and would serialize to an
|
||||||
//! serialize to an `Object` value.
|
//! `Object` value.
|
||||||
//!
|
//!
|
||||||
//! ## Automatic Reloading
|
//! ## Automatic Reloading
|
||||||
//!
|
//!
|
||||||
@ -127,8 +127,6 @@
|
|||||||
//! will be automatically reloaded from disk if any changes have been made to
|
//! will be automatically reloaded from disk if any changes have been made to
|
||||||
//! the templates directory since the previous request. In release builds,
|
//! the templates directory since the previous request. In release builds,
|
||||||
//! template reloading is disabled to improve performance and cannot be enabled.
|
//! template reloading is disabled to improve performance and cannot be enabled.
|
||||||
//!
|
|
||||||
//! [`Serialize`]: serde::Serialize
|
|
||||||
|
|
||||||
#![doc(html_root_url = "https://api.rocket.rs/v0.5-rc/rocket_dyn_templates")]
|
#![doc(html_root_url = "https://api.rocket.rs/v0.5-rc/rocket_dyn_templates")]
|
||||||
#![doc(html_favicon_url = "https://rocket.rs/images/favicon.ico")]
|
#![doc(html_favicon_url = "https://rocket.rs/images/favicon.ico")]
|
||||||
@ -166,18 +164,16 @@ pub use self::metadata::Metadata;
|
|||||||
use self::fairing::TemplateFairing;
|
use self::fairing::TemplateFairing;
|
||||||
use self::context::{Context, ContextManager};
|
use self::context::{Context, ContextManager};
|
||||||
|
|
||||||
use serde::Serialize;
|
|
||||||
use serde_json::{Value, to_value};
|
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
use rocket::{Rocket, Orbit, Ignite, Sentinel};
|
use rocket::{Rocket, Orbit, Ignite, Sentinel};
|
||||||
use rocket::request::Request;
|
use rocket::request::Request;
|
||||||
use rocket::fairing::Fairing;
|
use rocket::fairing::Fairing;
|
||||||
use rocket::response::{self, Responder};
|
use rocket::response::{self, Responder};
|
||||||
use rocket::http::{ContentType, Status};
|
use rocket::http::{ContentType, Status};
|
||||||
|
use rocket::figment::{value::Value, error::Error};
|
||||||
|
use rocket::serde::Serialize;
|
||||||
|
|
||||||
const DEFAULT_TEMPLATE_DIR: &str = "templates";
|
const DEFAULT_TEMPLATE_DIR: &str = "templates";
|
||||||
|
|
||||||
@ -191,7 +187,7 @@ const DEFAULT_TEMPLATE_DIR: &str = "templates";
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Template {
|
pub struct Template {
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
value: Option<Value>
|
value: Result<Value, Error>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -299,7 +295,7 @@ impl Template {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn try_custom<F: Send + Sync + 'static>(f: F) -> impl Fairing
|
pub fn try_custom<F: Send + Sync + 'static>(f: F) -> impl Fairing
|
||||||
where F: Fn(&mut Engines) -> Result<(), Box<dyn Error>>
|
where F: Fn(&mut Engines) -> Result<(), Box<dyn std::error::Error>>
|
||||||
{
|
{
|
||||||
TemplateFairing { callback: Box::new(f) }
|
TemplateFairing { callback: Box::new(f) }
|
||||||
}
|
}
|
||||||
@ -325,7 +321,7 @@ impl Template {
|
|||||||
pub fn render<S, C>(name: S, context: C) -> Template
|
pub fn render<S, C>(name: S, context: C) -> Template
|
||||||
where S: Into<Cow<'static, str>>, C: Serialize
|
where S: Into<Cow<'static, str>>, C: Serialize
|
||||||
{
|
{
|
||||||
Template { name: name.into(), value: to_value(context).ok() }
|
Template { name: name.into(), value: Value::serialize(context) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render the template named `name` with the context `context` into a
|
/// Render the template named `name` with the context `context` into a
|
||||||
@ -386,13 +382,13 @@ impl Template {
|
|||||||
let info = ctxt.templates.get(name).ok_or_else(|| {
|
let info = ctxt.templates.get(name).ok_or_else(|| {
|
||||||
let ts: Vec<_> = ctxt.templates.keys().map(|s| s.as_str()).collect();
|
let ts: Vec<_> = ctxt.templates.keys().map(|s| s.as_str()).collect();
|
||||||
error_!("Template '{}' does not exist.", name);
|
error_!("Template '{}' does not exist.", name);
|
||||||
info_!("Known templates: {}", ts.join(", "));
|
info_!("Known templates: {}.", ts.join(", "));
|
||||||
info_!("Searched in {:?}.", ctxt.root);
|
info_!("Searched in {:?}.", ctxt.root);
|
||||||
Status::InternalServerError
|
Status::InternalServerError
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let value = self.value.ok_or_else(|| {
|
let value = self.value.map_err(|e| {
|
||||||
error_!("The provided template context failed to serialize.");
|
error_!("Template context failed to serialize: {}.", e);
|
||||||
Status::InternalServerError
|
Status::InternalServerError
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use serde::Serialize;
|
use rocket::serde::Serialize;
|
||||||
|
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
|
|
||||||
@ -42,16 +42,9 @@ impl Engine for Tera {
|
|||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let tera_ctx = match Context::from_serialize(context) {
|
let tera_ctx = Context::from_serialize(context)
|
||||||
Ok(ctx) => ctx,
|
.map_err(|e| error_!("Tera context error: {}.", e))
|
||||||
Err(_) => {
|
.ok()?;
|
||||||
error_!(
|
|
||||||
"Error generating context when rendering Tera template '{}'.",
|
|
||||||
name
|
|
||||||
);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match Tera::render(self, name, &tera_ctx) {
|
match Tera::render(self, name, &tera_ctx) {
|
||||||
Ok(string) => Some(string),
|
Ok(string) => Some(string),
|
||||||
|
@ -126,6 +126,21 @@ mod tera_tests {
|
|||||||
assert_eq!(template, Some(ESCAPED_EXPECTED.into()));
|
assert_eq!(template, Some(ESCAPED_EXPECTED.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// u128 is not supported. enable when it is.
|
||||||
|
// #[test]
|
||||||
|
// fn test_tera_u128() {
|
||||||
|
// const EXPECTED: &'static str
|
||||||
|
// = "\nh_start\ntitle: 123\nh_end\n\n\n1208925819614629174706176\n\nfoot\n";
|
||||||
|
//
|
||||||
|
// let client = Client::debug(rocket()).unwrap();
|
||||||
|
// let mut map = HashMap::new();
|
||||||
|
// map.insert("title", 123);
|
||||||
|
// map.insert("number", 1u128 << 80);
|
||||||
|
//
|
||||||
|
// let template = Template::show(client.rocket(), "tera/txt_test", &map);
|
||||||
|
// assert_eq!(template, Some(EXPECTED.into()));
|
||||||
|
// }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_template_metadata_with_tera() {
|
fn test_template_metadata_with_tera() {
|
||||||
let client = Client::debug(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
@ -151,11 +166,11 @@ mod handlebars_tests {
|
|||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::local::blocking::Client;
|
use rocket::local::blocking::Client;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_handlebars_templates() {
|
||||||
const EXPECTED: &'static str
|
const EXPECTED: &'static str
|
||||||
= "Hello _test_!\n\n<main> <script /> hi </main>\nDone.\n\n";
|
= "Hello _test_!\n\n<main> <script /> hi </main>\nDone.\n\n";
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_handlebars_templates() {
|
|
||||||
let client = Client::debug(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
map.insert("title", "_test_");
|
map.insert("title", "_test_");
|
||||||
@ -166,6 +181,21 @@ mod handlebars_tests {
|
|||||||
assert_eq!(template, Some(EXPECTED.into()));
|
assert_eq!(template, Some(EXPECTED.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// u128 is not supported. enable when it is.
|
||||||
|
// #[test]
|
||||||
|
// fn test_handlebars_u128() {
|
||||||
|
// const EXPECTED: &'static str
|
||||||
|
// = "Hello 123!\n\n<main> 1208925819614629174706176 </main>\nDone.\n\n";
|
||||||
|
//
|
||||||
|
// let client = Client::debug(rocket()).unwrap();
|
||||||
|
// let mut map = HashMap::new();
|
||||||
|
// map.insert("title", 123);
|
||||||
|
// map.insert("number", 1u128 << 80);
|
||||||
|
//
|
||||||
|
// let template = Template::show(client.rocket(), "hbs/test", &map);
|
||||||
|
// assert_eq!(template, Some(EXPECTED.into()));
|
||||||
|
// }
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_template_metadata_with_handlebars() {
|
fn test_template_metadata_with_handlebars() {
|
||||||
let client = Client::debug(rocket()).unwrap();
|
let client = Client::debug(rocket()).unwrap();
|
||||||
|
Loading…
Reference in New Issue
Block a user