Create template registry once and lazy.
Instead of creating a new Handlebars instance each call to send_email it's now a rocket fairing that's initialized lazily.
This commit is contained in:
parent
b6dae24d66
commit
242c73290c
26
src/mail.rs
26
src/mail.rs
|
@ -14,19 +14,15 @@ pub struct Context{
|
|||
pub domain: String,
|
||||
}
|
||||
|
||||
fn send_mail<T>(to: &Email, subject: &str, template_dir: &str,
|
||||
template_base: &str, from: &str, ctx: T)
|
||||
fn send_mail<T>(to: &Email, subject: &str, mail_templates: &Handlebars,
|
||||
template: &str, from: &str, ctx: T)
|
||||
-> Result<()> where T: Serialize + Clone
|
||||
{
|
||||
// TODO: Should be done only on startup
|
||||
let tmpl = format!("{}/{}", template_dir, template_base);
|
||||
let mut handlebars = Handlebars::new();
|
||||
handlebars.register_template_file("html", format!("{}-html.hbs", tmpl)).unwrap();
|
||||
handlebars.register_template_file("txt", format!("{}-txt.hbs", tmpl)).unwrap();
|
||||
|
||||
let tmpl_html = format!("{}-html", template);
|
||||
let tmpl_txt = format!("{}-txt", template);
|
||||
let (html, txt) = {
|
||||
if let (Ok(inner_html), Ok(inner_txt)) =
|
||||
(handlebars.render("html", &ctx), handlebars.render("txt", &ctx)) {
|
||||
(mail_templates.render(&tmpl_html, &ctx), mail_templates.render(&tmpl_txt, &ctx)) {
|
||||
(Some(inner_html), Some(inner_txt))
|
||||
} else {
|
||||
(None, None)
|
||||
|
@ -47,7 +43,7 @@ fn send_mail<T>(to: &Email, subject: &str, template_dir: &str,
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn send_verification_mail(userid: &Email, token: &str, template_dir: &str,
|
||||
pub fn send_verification_mail(userid: &Email, token: &str, mail_templates: &Handlebars,
|
||||
domain: &str, from: &str)
|
||||
-> Result<()>
|
||||
{
|
||||
|
@ -57,11 +53,11 @@ pub fn send_verification_mail(userid: &Email, token: &str, template_dir: &str,
|
|||
domain: domain.to_string(),
|
||||
};
|
||||
|
||||
send_mail(userid, "Please verify your email address", template_dir,
|
||||
"verify-email", from, ctx)
|
||||
send_mail(userid, "Please verify your email address", mail_templates,
|
||||
"verify", from, ctx)
|
||||
}
|
||||
|
||||
pub fn send_confirmation_mail(userid: &Email, token: &str, template_dir: &str,
|
||||
pub fn send_confirmation_mail(userid: &Email, token: &str, mail_templates: &Handlebars,
|
||||
domain: &str, from: &str)
|
||||
-> Result<()>
|
||||
{
|
||||
|
@ -71,6 +67,6 @@ pub fn send_confirmation_mail(userid: &Email, token: &str, template_dir: &str,
|
|||
domain: domain.to_string(),
|
||||
};
|
||||
|
||||
send_mail(userid, "Please confirm deletion of your key", template_dir,
|
||||
"confirm-email", from, ctx)
|
||||
send_mail(userid, "Please confirm deletion of your key", mail_templates,
|
||||
"confirm", from, ctx)
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ use rocket::request::{self, Request, FromRequest};
|
|||
use rocket::response::status::Custom;
|
||||
use rocket::response::NamedFile;
|
||||
use rocket::fairing::AdHoc;
|
||||
|
||||
use rocket_contrib::templates::Template;
|
||||
|
||||
use handlebars::Handlebars;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
mod upload;
|
||||
|
@ -50,9 +51,9 @@ mod templates {
|
|||
}
|
||||
|
||||
struct StaticDir(String);
|
||||
pub struct MailTemplateDir(String);
|
||||
pub struct Domain(String);
|
||||
pub struct From(String);
|
||||
pub struct MailTemplates(Handlebars);
|
||||
|
||||
impl<'a, 'r> FromRequest<'a, 'r> for queries::Hkp {
|
||||
type Error = ();
|
||||
|
@ -190,7 +191,7 @@ fn verify(db: rocket::State<Polymorphic>, token: String)
|
|||
|
||||
#[get("/vks/delete/<fpr>")]
|
||||
fn delete(db: rocket::State<Polymorphic>, fpr: String,
|
||||
tmpl: State<MailTemplateDir>, domain: State<Domain>, from: State<From>)
|
||||
tmpl: State<MailTemplates>, domain: State<Domain>, from: State<From>)
|
||||
-> result::Result<Template, Custom<String>>
|
||||
{
|
||||
use mail::send_confirmation_mail;
|
||||
|
@ -435,14 +436,6 @@ pub fn serve(opt: &Opt, db: Polymorphic) -> Result<()> {
|
|||
|
||||
Ok(rocket.manage(StaticDir(static_dir)))
|
||||
}))
|
||||
.attach(AdHoc::on_attach("template_dir", |rocket| {
|
||||
let static_dir = rocket.config()
|
||||
.get_str("template_dir")
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
Ok(rocket.manage(MailTemplateDir(static_dir)))
|
||||
}))
|
||||
.attach(AdHoc::on_attach("domain", |rocket| {
|
||||
let domain = rocket.config()
|
||||
.get_str("domain")
|
||||
|
@ -459,6 +452,25 @@ pub fn serve(opt: &Opt, db: Polymorphic) -> Result<()> {
|
|||
|
||||
Ok(rocket.manage(From(from)))
|
||||
}))
|
||||
.attach(AdHoc::on_attach("mail_templates", |rocket| {
|
||||
let dir: PathBuf = rocket.config()
|
||||
.get_str("template_dir")
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.into();
|
||||
let confirm_html = dir.join("confirm-email-html.hbs");
|
||||
let confirm_txt = dir.join("confirm-email-txt.hbs");
|
||||
let verify_html = dir.join("verify-email-html.hbs");
|
||||
let verify_txt = dir.join("verify-email-txt.hbs");
|
||||
let mut handlebars = Handlebars::new();
|
||||
|
||||
handlebars.register_template_file("confirm-html", confirm_html).unwrap();
|
||||
handlebars.register_template_file("confirm-txt", confirm_txt).unwrap();
|
||||
handlebars.register_template_file("verify-html", verify_html).unwrap();
|
||||
handlebars.register_template_file("verify-txt", verify_txt).unwrap();
|
||||
|
||||
Ok(rocket.manage(MailTemplates(handlebars)))
|
||||
}))
|
||||
|
||||
.mount("/", routes)
|
||||
.manage(db)
|
||||
|
|
|
@ -7,9 +7,11 @@ use rocket::http::{ContentType, Status};
|
|||
use rocket::response::status::Custom;
|
||||
use rocket_contrib::templates::Template;
|
||||
|
||||
use handlebars::Handlebars;
|
||||
|
||||
use types::Email;
|
||||
use mail::send_verification_mail;
|
||||
use web::{From, Domain, MailTemplateDir};
|
||||
use web::{From, Domain, MailTemplates};
|
||||
use database::{Database, Polymorphic};
|
||||
|
||||
use std::io::Read;
|
||||
|
@ -31,7 +33,7 @@ mod template {
|
|||
#[post("/pks/add", data = "<data>")]
|
||||
// signature requires the request to have a `Content-Type`
|
||||
pub fn multipart_upload(db: State<Polymorphic>, cont_type: &ContentType,
|
||||
data: Data, tmpl: State<MailTemplateDir>,
|
||||
data: Data, tmpl: State<MailTemplates>,
|
||||
domain: State<Domain>, from: State<From>)
|
||||
-> Result<Template, Custom<String>>
|
||||
{
|
||||
|
@ -79,7 +81,7 @@ pub fn multipart_upload(db: State<Polymorphic>, cont_type: &ContentType,
|
|||
}
|
||||
}
|
||||
|
||||
fn process_upload(boundary: &str, data: Data, db: &Polymorphic, tmpl: &str,
|
||||
fn process_upload(boundary: &str, data: Data, db: &Polymorphic, mail_templates: &Handlebars,
|
||||
domain: &str, from: &str)
|
||||
-> Result<Template, Custom<String>>
|
||||
{
|
||||
|
@ -87,13 +89,13 @@ fn process_upload(boundary: &str, data: Data, db: &Polymorphic, tmpl: &str,
|
|||
// Entries could implement FromData though that would give zero control over
|
||||
// how the files are saved; Multipart would be a good impl candidate though
|
||||
match Multipart::with_body(data.open(), boundary).save().temp() {
|
||||
Full(entries) => process_multipart(entries, db, tmpl, domain, from),
|
||||
Partial(partial, _) => process_multipart(partial.entries, db, tmpl, domain, from),
|
||||
Full(entries) => process_multipart(entries, db, mail_templates, domain, from),
|
||||
Partial(partial, _) => process_multipart(partial.entries, db, mail_templates, domain, from),
|
||||
Error(err) => Err(Custom(Status::InternalServerError, err.to_string())),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_multipart(entries: Entries, db: &Polymorphic, tmpl: &str,
|
||||
fn process_multipart(entries: Entries, db: &Polymorphic, mail_templates: &Handlebars,
|
||||
domain: &str, from: &str)
|
||||
-> Result<Template, Custom<String>>
|
||||
{
|
||||
|
@ -103,14 +105,14 @@ fn process_multipart(entries: Entries, db: &Polymorphic, tmpl: &str,
|
|||
Custom(Status::InternalServerError, err.to_string())
|
||||
})?;
|
||||
|
||||
process_key(reader, db, tmpl, domain, from)
|
||||
process_key(reader, db, mail_templates, domain, from)
|
||||
}
|
||||
Some(_) | None =>
|
||||
Err(Custom(Status::BadRequest, "Not a PGP public key".into())),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_key<R>(reader: R, db: &Polymorphic, tmpl: &str, domain: &str, from: &str)
|
||||
fn process_key<R>(reader: R, db: &Polymorphic, mail_templates: &Handlebars, domain: &str, from: &str)
|
||||
-> Result<Template, Custom<String>> where R: Read
|
||||
{
|
||||
use sequoia_openpgp::TPK;
|
||||
|
@ -130,7 +132,7 @@ fn process_key<R>(reader: R, db: &Polymorphic, tmpl: &str, domain: &str, from: &
|
|||
let &template::Token{ ref userid, ref token } = tok;
|
||||
|
||||
Email::from_str(userid).and_then(|email| {
|
||||
send_verification_mail(&email, token, tmpl, domain, from)
|
||||
send_verification_mail(&email, token, mail_templates, domain, from)
|
||||
}).map_err(|err| {
|
||||
Custom(Status::InternalServerError, format!("{:?}", err))
|
||||
})?;
|
||||
|
|
Loading…
Reference in New Issue