From ee92301fb960146700ef7d483d0f632888480f46 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 5 May 2019 20:17:54 +0200 Subject: [PATCH] add "maintenance mode" --- Rocket.toml.dist | 3 ++ dist/templates/maintenance.html.hbs | 8 ++++ src/web/maintenance.rs | 68 +++++++++++++++++++++++++++++ src/web/mod.rs | 13 ++++++ 4 files changed, 92 insertions(+) create mode 100644 dist/templates/maintenance.html.hbs create mode 100644 src/web/maintenance.rs diff --git a/Rocket.toml.dist b/Rocket.toml.dist index d861279..a0e2c91 100644 --- a/Rocket.toml.dist +++ b/Rocket.toml.dist @@ -15,6 +15,7 @@ keys_external_dir = "state/keys-external" token_dir = "state/tokens" tmp_dir = "state/tmp" mail_rate_limit = 60 +maintenance_file = "state/maintenance" [staging] base-URI = "https://keys.openpgp.org" @@ -29,6 +30,7 @@ assets_dir = "public/assets" token_dir = "tokens" tmp_dir = "tmp" mail_rate_limit = 60 +maintenance_file = "maintenance" [production] base-URI = "https://keys.openpgp.org" @@ -43,3 +45,4 @@ assets_dir = "public/assets" token_dir = "tokens" tmp_dir = "tmp" mail_rate_limit = 3600 +maintenance_file = "maintenance" diff --git a/dist/templates/maintenance.html.hbs b/dist/templates/maintenance.html.hbs new file mode 100644 index 0000000..1e7d895 --- /dev/null +++ b/dist/templates/maintenance.html.hbs @@ -0,0 +1,8 @@ +{{#> layout }} +

Maintenance Mode

+ +

+ {{message}} +

+ +{{/layout}} diff --git a/src/web/maintenance.rs b/src/web/maintenance.rs new file mode 100644 index 0000000..1c1a16e --- /dev/null +++ b/src/web/maintenance.rs @@ -0,0 +1,68 @@ +use rocket::{Request, Data}; +use rocket::fairing::{Fairing, Info, Kind}; +use rocket_contrib::templates::Template; +use rocket::http::Method; + +use std::fs; +use std::path::PathBuf; + +use web::MyResponse; + +pub struct MaintenanceMode { + maintenance_file: PathBuf, +} + +mod templates { + #[derive(Serialize)] + pub struct MaintenanceMode { + pub message: String, + pub commit: String, + pub version: String, + } +} + +impl Fairing for MaintenanceMode { + fn info(&self) -> Info { + Info { + name: "Maintenance Mode", + kind: Kind::Request + } + } + + fn on_request(&self, request: &mut Request, _: &Data) { + if !self.is_relevant_path(request.uri().path()) { + return; + } + if let Some(message) = self.get_maintenance_message() { + request.set_uri(uri!(maintenance_error: message)); + request.set_method(Method::Get); + } + } +} + +impl MaintenanceMode { + pub fn new(maintenance_file: PathBuf) -> Self { + MaintenanceMode { maintenance_file } + } + + fn is_relevant_path(&self, path: &str) -> bool { + path.starts_with("/publish") || path.starts_with("/manage") + } + + fn get_maintenance_message(&self) -> Option { + if !self.maintenance_file.exists() { + return None; + } + fs::read_to_string(&self.maintenance_file).ok() + } +} + +#[get("/maintenance/")] +pub fn maintenance_error(message: String) -> MyResponse { + let ctx = templates::MaintenanceMode{ + message, + version: env!("VERGEN_SEMVER").to_string(), + commit: env!("VERGEN_SHA_SHORT").to_string(), + }; + MyResponse::ServerError(Template::render("maintenance", ctx)) +} diff --git a/src/web/mod.rs b/src/web/mod.rs index d86b784..5d342cd 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -24,6 +24,9 @@ use std::convert::TryInto; mod hkp; mod manage; +mod maintenance; + +use web::maintenance::MaintenanceMode; use rocket::http::hyper::header::ContentDisposition; @@ -338,6 +341,8 @@ fn rocket_factory(rocket: rocket::Rocket) -> Result { manage::vks_manage_key, manage::vks_manage_post, manage::vks_manage_unpublish, + // Maintenance error page + maintenance::maintenance_error, ]; let db_service = configure_db_service(rocket.config())?; @@ -346,9 +351,11 @@ fn rocket_factory(rocket: rocket::Rocket) -> Result { let stateless_token_service = configure_stateless_token_service(rocket.config())?; let mail_service = configure_mail_service(rocket.config())?; let rate_limiter = configure_rate_limiter(rocket.config())?; + let maintenance_mode = configure_maintenance_mode(rocket.config())?; Ok(rocket .attach(Template::fairing()) + .attach(maintenance_mode) .manage(hagrid_state) .manage(stateless_token_service) .manage(stateful_token_service) @@ -431,6 +438,12 @@ fn configure_rate_limiter(config: &Config) -> Result { Ok(RateLimiter::new(timeout_secs)) } +fn configure_maintenance_mode(config: &Config) -> Result { + let maintenance_file: PathBuf = config.get_str("maintenance_file") + .unwrap_or("maintenance").into(); + Ok(MaintenanceMode::new(maintenance_file)) +} + #[cfg(test)] pub mod tests { use regex;