feat: add error page support completed
Diff
src/error_page.rs | 39 +++++++++++++++++++++++++++++++++-----
src/main.rs | 22 +++++++++++++++-------
src/staticfiles.rs | 56 ++++++++++++++++++++++++++++++++++++++++---------------
3 files changed, 90 insertions(+), 27 deletions(-)
@@ -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;
pub struct ErrorPage {
pub page50x: std::string::String,
pub page404: std::string::String,
}
impl ErrorPage {
pub fn new<P: AsRef<Path>>(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<Response> {
@@ -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),
}
}
}
@@ -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");
@@ -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"));
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 {
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);
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
}
}