mirror of https://github.com/rwf2/Rocket.git
Add templating support in contrib crate.
The contrib crate now contains support for both Handlebars and Tera. No documentation yet. resolves #5
This commit is contained in:
parent
53e5377482
commit
f74e286e31
|
@ -22,6 +22,7 @@ members = [
|
|||
"examples/from_request",
|
||||
"examples/stream",
|
||||
"examples/json",
|
||||
"examples/handlebars_templates",
|
||||
]
|
||||
|
||||
[replace]
|
||||
|
|
|
@ -6,11 +6,28 @@ authors = ["Sergio Benitez <sb@sergio.bz>"]
|
|||
[features]
|
||||
default = ["json"]
|
||||
json = ["serde", "serde_json"]
|
||||
tera_templates = ["tera", "templates"]
|
||||
handlebars_templates = ["handlebars", "templates"]
|
||||
|
||||
# Internal use only.
|
||||
templates = ["serde", "serde_json", "lazy_static_macro", "glob"]
|
||||
lazy_static_macro = ["lazy_static"]
|
||||
|
||||
[dependencies]
|
||||
rocket = { path = "../lib/" }
|
||||
log = "*"
|
||||
|
||||
# JSON module dependencies
|
||||
# JSON and templating dependencies.
|
||||
serde = { version = "*", optional = true }
|
||||
serde_json = { version = "*", optional = true }
|
||||
|
||||
# Templating dependencies only.
|
||||
handlebars = { version = "*", optional = true, features = ["serde_type"] }
|
||||
glob = { version = "*", optional = true }
|
||||
lazy_static = { version = "*", optional = true }
|
||||
|
||||
# Tera dependency
|
||||
[dependencies.tera]
|
||||
git = "https://github.com/SergioBenitez/tera"
|
||||
branch = "array-get-filter"
|
||||
optional = true
|
||||
|
|
|
@ -44,6 +44,7 @@ use self::serde_json::Error as JSONError;
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
#[derive(Debug)]
|
||||
pub struct JSON<T>(pub T);
|
||||
|
||||
impl<T> JSON<T> {
|
||||
|
|
|
@ -32,9 +32,19 @@
|
|||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate rocket;
|
||||
|
||||
#[cfg_attr(feature = "lazy_static_macro", macro_use)]
|
||||
#[cfg(feature = "lazy_static_macro")]
|
||||
extern crate lazy_static;
|
||||
|
||||
#[cfg_attr(feature = "json", macro_use)]
|
||||
#[cfg(feature = "json")]
|
||||
mod json;
|
||||
|
||||
#[cfg(feature = "templates")]
|
||||
mod templates;
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
pub use json::JSON;
|
||||
|
||||
#[cfg(feature = "templates")]
|
||||
pub use templates::Template;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
extern crate handlebars;
|
||||
|
||||
use std::sync::RwLock;
|
||||
|
||||
use super::serde::Serialize;
|
||||
use super::TemplateInfo;
|
||||
|
||||
use self::handlebars::Handlebars;
|
||||
|
||||
lazy_static! {
|
||||
static ref HANDLEBARS: RwLock<Handlebars> = RwLock::new(Handlebars::new());
|
||||
}
|
||||
|
||||
pub const EXT: &'static str = "hbs";
|
||||
|
||||
pub fn render<T>(name: &str, info: &TemplateInfo, context: &T) -> Option<String>
|
||||
where T: Serialize
|
||||
{
|
||||
// FIXME: Expose a callback to register each template at launch => no lock.
|
||||
if HANDLEBARS.read().unwrap().get_template(name).is_none() {
|
||||
let p = &info.full_path;
|
||||
if let Err(e) = HANDLEBARS.write().unwrap().register_template_file(name, p) {
|
||||
error_!("Handlebars template '{}' failed registry: {:?}", name, e);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
match HANDLEBARS.read().unwrap().render(name, context) {
|
||||
Ok(string) => Some(string),
|
||||
Err(e) => {
|
||||
error_!("Error rendering Handlebars template '{}': {}", name, e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
#[macro_export]
|
||||
macro_rules! engine_set {
|
||||
($($feature:expr => $engine:ident),+) => ({
|
||||
use std::collections::HashSet;
|
||||
let mut set = HashSet::new();
|
||||
$(
|
||||
#[cfg(feature = $feature)]
|
||||
fn $engine(set: &mut HashSet<String>) {
|
||||
set.insert($engine::EXT.to_string());
|
||||
}
|
||||
|
||||
#[cfg(not(feature = $feature))]
|
||||
fn $engine(_: &mut HashSet<String>) { }
|
||||
|
||||
$engine(&mut set);
|
||||
)+
|
||||
set
|
||||
});
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! render_set {
|
||||
($name:expr, $info:expr, $ctxt:expr, $($feature:expr => $engine:ident),+) => ({$(
|
||||
#[cfg(feature = $feature)]
|
||||
fn $engine<T: Serialize>(name: &str, info: &TemplateInfo, c: &T)
|
||||
-> Option<Template> {
|
||||
if info.extension == $engine::EXT {
|
||||
let rendered = $engine::render(name, info, c);
|
||||
return Some(Template(rendered, info.data_type.clone()));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(not(feature = $feature))]
|
||||
fn $engine<T: Serialize>(_: &str, _: &TemplateInfo, _: &T)
|
||||
-> Option<Template> { None }
|
||||
|
||||
if let Some(template) = $engine($name, &$info, &$ctxt) {
|
||||
return template
|
||||
}
|
||||
)+});
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
extern crate serde;
|
||||
extern crate serde_json;
|
||||
extern crate glob;
|
||||
|
||||
#[cfg(feature = "tera_templates")]
|
||||
pub mod tera_templates;
|
||||
|
||||
#[cfg(feature = "handlebars_templates")]
|
||||
pub mod handlebars_templates;
|
||||
|
||||
#[macro_use] mod macros;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use self::serde::Serialize;
|
||||
use rocket::response::{data, Outcome, FreshHyperResponse, Responder};
|
||||
use rocket::Rocket;
|
||||
use self::glob::glob;
|
||||
|
||||
lazy_static! {
|
||||
static ref TEMPLATES: HashMap<String, TemplateInfo> = discover_templates();
|
||||
static ref TEMPLATE_DIR: String =
|
||||
Rocket::config("template_dir").unwrap_or("templates").to_string();
|
||||
}
|
||||
|
||||
/// Removes the file path's extension or does nothing if there is none.
|
||||
fn remove_extension<P: AsRef<Path>>(path: P) -> PathBuf {
|
||||
PathBuf::from(path.as_ref().file_stem().unwrap())
|
||||
}
|
||||
|
||||
fn discover_templates() -> HashMap<String, TemplateInfo> {
|
||||
// Keep this set in-sync with the `render_set` invocation.
|
||||
let engines = engine_set![
|
||||
"tera_templates" => tera_templates,
|
||||
"handlebars_templates" => handlebars_templates
|
||||
];
|
||||
|
||||
let mut templates = HashMap::new();
|
||||
for ext in engines {
|
||||
let mut path: PathBuf = [&*TEMPLATE_DIR, "**", "*"].iter().collect();
|
||||
path.set_extension(ext);
|
||||
for p in glob(path.to_str().unwrap()).unwrap().filter_map(Result::ok) {
|
||||
let canonical_path = remove_extension(&p);
|
||||
let name = remove_extension(&canonical_path);
|
||||
let data_type = canonical_path.extension();
|
||||
templates.insert(name.to_string_lossy().into_owned(), TemplateInfo {
|
||||
full_path: p.to_path_buf(),
|
||||
path: p.strip_prefix(&*TEMPLATE_DIR).unwrap().to_path_buf(),
|
||||
canonical_path: canonical_path.clone(),
|
||||
extension: p.extension().unwrap().to_string_lossy().into_owned(),
|
||||
data_type: data_type.map(|d| d.to_string_lossy().into_owned())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
templates
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Template(Option<String>, Option<String>);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TemplateInfo {
|
||||
full_path: PathBuf,
|
||||
path: PathBuf,
|
||||
canonical_path: PathBuf,
|
||||
extension: String,
|
||||
data_type: Option<String>
|
||||
}
|
||||
|
||||
impl Template {
|
||||
pub fn render<S, T>(name: S, context: T) -> Template
|
||||
where S: AsRef<str>, T: Serialize
|
||||
{
|
||||
let name = name.as_ref();
|
||||
let template = TEMPLATES.get(name);
|
||||
if template.is_none() {
|
||||
error_!("Template '{}' does not exist.", name);
|
||||
return Template(None, None);
|
||||
}
|
||||
|
||||
// Keep this set in-sync with the `engine_set` invocation.
|
||||
render_set!(name, template.unwrap(), context,
|
||||
"tera_templates" => tera_templates,
|
||||
"handlebars_templates" => handlebars_templates
|
||||
);
|
||||
|
||||
unreachable!("A template extension was discovered but not rendered.")
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for Template {
|
||||
fn respond<'a>(&mut self, res: FreshHyperResponse<'a>) -> Outcome<'a> {
|
||||
match self.0 {
|
||||
// FIXME: Detect the data type using the extension in self.1.
|
||||
// Refactor response::named_file to use the extension map there.
|
||||
Some(ref render) => data::HTML(render.as_str()).respond(res),
|
||||
None => Outcome::Bad(res),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
extern crate tera;
|
||||
|
||||
use std::path::PathBuf;
|
||||
use self::tera::Renderer;
|
||||
|
||||
use super::serde::Serialize;
|
||||
use super::serde_json;
|
||||
use super::{TemplateInfo, TEMPLATE_DIR};
|
||||
|
||||
lazy_static! {
|
||||
static ref TERA: tera::Tera = {
|
||||
let path: PathBuf = [&*TEMPLATE_DIR, "**", "*.tera"].iter().collect();
|
||||
tera::Tera::new(path.to_str().unwrap())
|
||||
};
|
||||
}
|
||||
|
||||
pub const EXT: &'static str = "tera";
|
||||
|
||||
pub fn render<T>(name: &str, info: &TemplateInfo, context: &T) -> Option<String>
|
||||
where T: Serialize
|
||||
{
|
||||
let template = match TERA.get_template(&info.path.to_string_lossy()) {
|
||||
Ok(template) => template,
|
||||
Err(_) => {
|
||||
error_!("Tera template '{}' does not exist.", name);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let value = serde_json::to_value(&context);
|
||||
let mut renderer = Renderer::new_with_json(template, &TERA, value);
|
||||
match renderer.render() {
|
||||
Ok(string) => Some(string),
|
||||
Err(e) => {
|
||||
error_!("Error rendering Tera template '{}': {}", name, e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "handlebars_templates"
|
||||
version = "0.0.1"
|
||||
authors = ["Sergio Benitez <sb@sergio.bz>"]
|
||||
workspace = "../../"
|
||||
|
||||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
serde = "*"
|
||||
serde_macros = "*"
|
||||
serde_json = "*"
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
path = "../../contrib"
|
||||
default-features = false
|
||||
features = ["handlebars_templates"]
|
|
@ -0,0 +1,44 @@
|
|||
#![feature(plugin, custom_derive)]
|
||||
#![plugin(rocket_codegen, serde_macros)]
|
||||
|
||||
extern crate rocket_contrib;
|
||||
extern crate rocket;
|
||||
extern crate serde_json;
|
||||
|
||||
use rocket::{Rocket, Request, Error};
|
||||
use rocket::response::Redirect;
|
||||
use rocket_contrib::Template;
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct TemplateContext {
|
||||
name: String,
|
||||
items: Vec<String>
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn index() -> Redirect {
|
||||
Redirect::to("/hello/Unknown")
|
||||
}
|
||||
|
||||
#[get("/hello/<name>")]
|
||||
fn get(name: String) -> Template {
|
||||
let context = TemplateContext {
|
||||
name: name,
|
||||
items: vec!["One", "Two", "Three"].iter().map(|s| s.to_string()).collect()
|
||||
};
|
||||
|
||||
Template::render("index", context)
|
||||
}
|
||||
|
||||
#[error(404)]
|
||||
fn not_found<'r>(_: Error, req: &'r Request<'r>) -> Template {
|
||||
let mut map = std::collections::HashMap::new();
|
||||
map.insert("path", req.uri().as_str());
|
||||
Template::render("404", map)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut rocket = Rocket::new("localhost", 8000);
|
||||
rocket.catch(errors![not_found]);
|
||||
rocket.mount_and_launch("/", routes![index, get]);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>404</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>404: Hey! There's nothing here.</h1>
|
||||
The page at {{ path }} does not exist!
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Handlebars Demo</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{name}}</h1>
|
||||
<h3>Here are your items:</h3>
|
||||
<ul>
|
||||
{{#each items}}
|
||||
<Li>{{this}}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -8,9 +8,17 @@ workspace = "../../"
|
|||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
lazy_static = "*"
|
||||
tera = { git = "https://github.com/Keats/tera" }
|
||||
serde = "0.8"
|
||||
serde_json = "0.8"
|
||||
serde_macros = "0.8"
|
||||
diesel = { git = "https://github.com/SergioBenitez/diesel", features = ["sqlite"] }
|
||||
diesel_codegen = { git = "https://github.com/SergioBenitez/diesel", default_features = false, features = ["sqlite"] }
|
||||
|
||||
[dependencies.tera]
|
||||
git = "https://github.com/SergioBenitez/tera"
|
||||
branch = "array-get-filter"
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
path = "../../contrib"
|
||||
default_features = false
|
||||
features = [ "tera_templates" ]
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#![plugin(rocket_codegen, serde_macros, diesel_codegen)]
|
||||
|
||||
extern crate rocket;
|
||||
extern crate tera;
|
||||
#[macro_use] extern crate diesel;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[macro_use] extern crate rocket_contrib;
|
||||
extern crate serde_json;
|
||||
|
||||
mod static_files;
|
||||
|
@ -12,63 +12,64 @@ mod task;
|
|||
|
||||
use rocket::Rocket;
|
||||
use rocket::response::{Flash, Redirect};
|
||||
use rocket_contrib::Template;
|
||||
use task::Task;
|
||||
|
||||
lazy_static!(static ref TERA: tera::Tera = tera::Tera::new("static/*.html"););
|
||||
#[derive(Debug, Serialize)]
|
||||
struct Context<'a, 'b>{msg: Option<(&'a str, &'b str)>, tasks: Vec<Task>}
|
||||
|
||||
fn ctxt(msg: Option<(&str, &str)>) -> tera::Context {
|
||||
let unwrapped_msg = msg.unwrap_or(("", ""));
|
||||
let mut context = tera::Context::new();
|
||||
context.add("has_msg", &msg.is_some());
|
||||
context.add("msg_type", &unwrapped_msg.0.to_string());
|
||||
context.add("msg", &unwrapped_msg.1.to_string());
|
||||
context.add("tasks", &Task::all());
|
||||
context
|
||||
impl<'a, 'b> Context<'a, 'b> {
|
||||
pub fn err(msg: &'a str) -> Context<'static, 'a> {
|
||||
Context{msg: Some(("error", msg)), tasks: Task::all()}
|
||||
}
|
||||
|
||||
pub fn raw(msg: Option<(&'a str, &'b str)>) -> Context<'a, 'b> {
|
||||
Context{msg: msg, tasks: Task::all()}
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/", form = "<todo>")]
|
||||
fn new(todo: Task) -> Result<Flash<Redirect>, tera::TeraResult<String>> {
|
||||
fn new(todo: Task) -> Result<Flash<Redirect>, Template> {
|
||||
if todo.description.is_empty() {
|
||||
let context = ctxt(Some(("error", "Description cannot be empty.")));
|
||||
Err(TERA.render("index.html", context))
|
||||
Err(Template::render("index", Context::err("Description cannot be empty.")))
|
||||
} else if todo.insert() {
|
||||
Ok(Flash::success(Redirect::to("/"), "Todo successfully added."))
|
||||
} else {
|
||||
let context = ctxt(Some(("error", "Whoops! The server failed.")));
|
||||
Err(TERA.render("index.html", context))
|
||||
Err(Template::render("index", Context::err("Whoops! The server failed.")))
|
||||
}
|
||||
}
|
||||
|
||||
// Should likely do something to simulate PUT.
|
||||
#[get("/<id>/toggle")]
|
||||
fn toggle(id: i32) -> Result<Redirect, tera::TeraResult<String>> {
|
||||
fn toggle(id: i32) -> Result<Redirect, Template> {
|
||||
if Task::toggle_with_id(id) {
|
||||
Ok(Redirect::to("/"))
|
||||
} else {
|
||||
let context = ctxt(Some(("error", "Could not toggle that task.")));
|
||||
Err(TERA.render("index.html", context))
|
||||
Err(Template::render("index", Context::err("Couldn't toggle task.")))
|
||||
}
|
||||
}
|
||||
|
||||
// Should likely do something to simulate DELETE.
|
||||
#[get("/<id>/delete")]
|
||||
fn delete(id: i32) -> Result<Flash<Redirect>, tera::TeraResult<String>> {
|
||||
fn delete(id: i32) -> Result<Flash<Redirect>, Template> {
|
||||
if Task::delete_with_id(id) {
|
||||
Ok(Flash::success(Redirect::to("/"), "Todo was deleted."))
|
||||
} else {
|
||||
let context = ctxt(Some(("error", "Could not delete that task.")));
|
||||
Err(TERA.render("index.html", context))
|
||||
Err(Template::render("index", Context::err("Couldn't delete task.")))
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn index(msg: Option<Flash<()>>) -> tera::TeraResult<String> {
|
||||
TERA.render("index.html", ctxt(msg.as_ref().map(|m| (m.name(), m.msg()))))
|
||||
fn index(msg: Option<Flash<()>>) -> Template {
|
||||
Template::render("index", match msg {
|
||||
Some(ref msg) => Context::raw(Some((msg.name(), msg.msg()))),
|
||||
None => Context::raw(None),
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut rocket = Rocket::new("127.0.0.1", 8000);
|
||||
rocket.mount("/", routes![index, static_files::all])
|
||||
.mount("/todo/", routes![new, delete, toggle]);
|
||||
.mount("/todo/", routes![new, toggle, delete]);
|
||||
rocket.launch();
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
<div class="ten columns">
|
||||
<input type="text" placeholder="enter a task description..."
|
||||
name="description" id="description" value="" autofocus
|
||||
class="u-full-width {% if has_msg %}field-{{msg_type}}{% endif %}" />
|
||||
{% if has_msg %}
|
||||
<small class="field-{{msg_type}}-msg">
|
||||
{{ msg }}
|
||||
class="u-full-width {% if msg %}field-{{msg|first}}{% endif %}" />
|
||||
{% if msg %}
|
||||
<small class="field-{{msg|first}}-msg">
|
||||
{{ msg | get(i=1) }}
|
||||
</small>
|
||||
{% endif %}
|
||||
</div>
|
|
@ -3,6 +3,8 @@ use std::convert::AsRef;
|
|||
use hyper::header::{SetCookie, CookiePair};
|
||||
use request::{Request, FromRequest};
|
||||
|
||||
const FLASH_COOKIE_NAME: &'static str = "_flash";
|
||||
|
||||
pub struct Flash<R> {
|
||||
name: String,
|
||||
message: String,
|
||||
|
@ -30,9 +32,9 @@ impl<R: Responder> Flash<R> {
|
|||
Flash::new(responder, "error", msg)
|
||||
}
|
||||
|
||||
pub fn cookie_pair(&self) -> CookiePair {
|
||||
fn cookie_pair(&self) -> CookiePair {
|
||||
let content = format!("{}{}{}", self.name.len(), self.name, self.message);
|
||||
let mut pair = CookiePair::new("_flash".to_string(), content);
|
||||
let mut pair = CookiePair::new(FLASH_COOKIE_NAME.to_string(), content);
|
||||
pair.path = Some("/".to_string());
|
||||
pair.max_age = Some(300);
|
||||
pair
|
||||
|
@ -78,10 +80,10 @@ impl<'r, 'c> FromRequest<'r, 'c> for Flash<()> {
|
|||
|
||||
fn from_request(request: &'r Request<'c>) -> Result<Self, Self::Error> {
|
||||
trace_!("Flash: attemping to retrieve message.");
|
||||
request.cookies().find("_flash").ok_or(()).and_then(|cookie| {
|
||||
request.cookies().find(FLASH_COOKIE_NAME).ok_or(()).and_then(|cookie| {
|
||||
// Clear the flash message.
|
||||
trace_!("Flash: retrieving message: {:?}", cookie);
|
||||
request.cookies().remove("flash");
|
||||
request.cookies().remove(FLASH_COOKIE_NAME);
|
||||
|
||||
// Parse the flash.
|
||||
let content = cookie.pair().1;
|
||||
|
|
|
@ -39,7 +39,8 @@ impl Rocket {
|
|||
Ok(req) => req,
|
||||
Err(ref reason) => {
|
||||
let mock_request = Request::mock(Method::Get, uri.as_str());
|
||||
return self.handle_internal_error(reason, &mock_request, res);
|
||||
debug_!("Bad request: {}", reason);
|
||||
return self.handle_internal_error(&mock_request, res);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -65,10 +66,7 @@ impl Rocket {
|
|||
res = match outcome {
|
||||
Outcome::Complete | Outcome::FailStop => return,
|
||||
Outcome::FailForward(r) => r,
|
||||
Outcome::Bad(r) => {
|
||||
let reason = "Reason: bad response.";
|
||||
return self.handle_internal_error(reason, &request, r)
|
||||
}
|
||||
Outcome::Bad(r) => return self.handle_internal_error(&request, r)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -77,10 +75,9 @@ impl Rocket {
|
|||
}
|
||||
|
||||
// Call on internal server error.
|
||||
fn handle_internal_error<'r>(&self, reason: &str, request: &'r Request<'r>,
|
||||
fn handle_internal_error<'r>(&self, request: &'r Request<'r>,
|
||||
response: FreshHyperResponse) {
|
||||
error!("Internal server error.");
|
||||
debug!("{}", reason);
|
||||
error_!("Internal server error.");
|
||||
let catcher = self.catchers.get(&500).unwrap();
|
||||
catcher.handle(Error::Internal, request).respond(response);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue