From 15379d66ec4330c93c0a82cb48b9a53add8ab4a8 Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Tue, 24 Dec 2019 01:10:34 +0100 Subject: [PATCH] feat: add error page support completed --- src/error_page.rs | 39 ++++++++++++++++++++++++++++++++++----- src/main.rs | 22 +++++++++++++++------- src/staticfiles.rs | 56 +++++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 90 insertions(+), 27 deletions(-) diff --git a/src/error_page.rs b/src/error_page.rs index 234f8b0..7a9e41a 100644 --- a/src/error_page.rs +++ b/src/error_page.rs @@ -4,8 +4,26 @@ use iron::mime; use iron::prelude::*; use iron::status; use iron::AfterMiddleware; +use std::fs; +use std::path::Path; -pub struct ErrorPage; +/// Custom Error pages middleware for Iron +pub struct ErrorPage { + /// HTML file content for 50x errors. + pub page50x: std::string::String, + /// HTML file content for 404 errors. + pub page404: std::string::String, +} + +impl ErrorPage { + /// Create a new instance of `ErrorPage` middleware with a given html pages. + pub fn new>(page_50x_path: P, page_404_path: P) -> ErrorPage { + let page50x = fs::read_to_string(page_50x_path).unwrap(); + let page404 = fs::read_to_string(page_404_path).unwrap(); + + ErrorPage { page50x, page404 } + } +} impl AfterMiddleware for ErrorPage { fn after(&self, _: &mut Request, res: Response) -> IronResult { @@ -15,18 +33,29 @@ impl AfterMiddleware for ErrorPage { Some(status::NotFound) => Ok(Response::with(( content_type, status::NotFound, - "404 Not Found", + self.page404.as_str(), ))), Some(status::InternalServerError) => Ok(Response::with(( content_type, status::InternalServerError, - "50x Internal Server Error", + self.page50x.as_str(), ))), - _ => Ok(Response::with(( + Some(status::BadGateway) => Ok(Response::with(( + content_type, + status::BadGateway, + self.page50x.as_str(), + ))), + Some(status::ServiceUnavailable) => Ok(Response::with(( content_type, status::ServiceUnavailable, - "503 Service Unavailable", + self.page50x.as_str(), + ))), + Some(status::GatewayTimeout) => Ok(Response::with(( + content_type, + status::GatewayTimeout, + self.page50x.as_str(), ))), + _ => Ok(res), } } } diff --git a/src/main.rs b/src/main.rs index 6bc28d0..032caae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,20 +8,21 @@ extern crate iron_staticfile_middleware; extern crate log; extern crate structopt; +mod config; +mod error_page; +mod gzip; +mod logger; +mod staticfiles; + use crate::config::Options; use chrono::Local; use env_logger::Builder; use iron::prelude::*; use log::LevelFilter; +use staticfiles::*; use std::io::Write; use structopt::StructOpt; -mod config; -mod error_page; -mod gzip; -mod logger; -mod staticfiles; - fn main() { Builder::new() .format(|buf, record| { @@ -38,9 +39,16 @@ fn main() { let opts = Options::from_args(); + let files = StaticFiles::new(StaticFilesOptions { + root_dir: opts.root, + assets_dir: opts.assets, + page_50x_path: opts.page50x, + page_404_path: opts.page404, + }); + let _address = &format!("{}{}{}", opts.host.to_string(), ":", opts.port.to_string()); - let _server = Iron::new(staticfiles::handler(opts.root, opts.assets)) + let _server = Iron::new(files.handle()) .http(_address) .expect("Unable to start the HTTP Server"); diff --git a/src/staticfiles.rs b/src/staticfiles.rs index 318974f..079faab 100644 --- a/src/staticfiles.rs +++ b/src/staticfiles.rs @@ -6,22 +6,48 @@ use iron::prelude::*; use iron_staticfile_middleware::{Cache, GuessContentType, ModifyWith, Prefix, Staticfile}; use std::time::Duration; -pub fn handler(root_dir: String, assets_dir: String) -> Chain { - let mut chain = - Chain::new(Staticfile::new(root_dir).expect("Directory to serve files was not found")); +/// An Iron middleware for static files-serving. +pub struct StaticFiles { + opts: StaticFilesOptions, +} + +pub struct StaticFilesOptions { + pub root_dir: String, + pub assets_dir: String, + pub page_50x_path: String, + pub page_404_path: String, +} - let one_day = Duration::new(60 * 60 * 24, 0); - let one_year = Duration::new(60 * 60 * 24 * 365, 0); - let default_content_type = "text/html" - .parse() - .expect("Unable to create a default content type header"); +impl StaticFiles { + /// Create a new instance of `StaticFiles` with given options. + pub fn new(opts: StaticFilesOptions) -> StaticFiles { + StaticFiles { opts } + } - chain.link_after(ModifyWith::new(Cache::new(one_day))); - chain.link_after(Prefix::new(&[assets_dir], Cache::new(one_year))); - chain.link_after(GuessContentType::new(default_content_type)); - chain.link_after(GzipMiddleware); - chain.link_after(Logger); - chain.link_after(ErrorPage); + /// Handle static files for current `StaticFiles` middleware. + pub fn handle(&self) -> Chain { + let mut chain = Chain::new( + Staticfile::new(self.opts.root_dir.as_str()) + .expect("Directory to serve files was not found"), + ); + let one_day = Duration::new(60 * 60 * 24, 0); + let one_year = Duration::new(60 * 60 * 24 * 365, 0); + let default_content_type = "text/html" + .parse() + .expect("Unable to create a default content type header"); - chain + chain.link_after(ModifyWith::new(Cache::new(one_day))); + chain.link_after(Prefix::new( + &[self.opts.assets_dir.as_str()], + Cache::new(one_year), + )); + chain.link_after(GuessContentType::new(default_content_type)); + chain.link_after(GzipMiddleware); + chain.link_after(Logger); + chain.link_after(ErrorPage::new( + self.opts.page_50x_path.as_str(), + self.opts.page_404_path.as_str(), + )); + chain + } } -- libgit2 1.7.2