add "maintenance mode"

This commit is contained in:
Vincent Breitmoser 2019-05-05 20:17:54 +02:00
parent 330b443153
commit ee92301fb9
4 changed files with 92 additions and 0 deletions

View File

@ -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"

8
dist/templates/maintenance.html.hbs vendored Normal file
View File

@ -0,0 +1,8 @@
{{#> layout }}
<h2>Maintenance Mode</h2>
<p>
{{message}}
</p>
{{/layout}}

68
src/web/maintenance.rs Normal file
View File

@ -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<String> {
if !self.maintenance_file.exists() {
return None;
}
fs::read_to_string(&self.maintenance_file).ok()
}
}
#[get("/maintenance/<message>")]
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))
}

View File

@ -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<rocket::Rocket> {
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<rocket::Rocket> {
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<RateLimiter> {
Ok(RateLimiter::new(timeout_secs))
}
fn configure_maintenance_mode(config: &Config) -> Result<MaintenanceMode> {
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;