diff --git a/src/web/error.rs b/src/web/error.rs index 2a29404ef..11cbab701 100644 --- a/src/web/error.rs +++ b/src/web/error.rs @@ -10,6 +10,7 @@ pub enum Nope { ResourceNotFound, CrateNotFound, NoResults, + InternalServerError, } impl fmt::Display for Nope { @@ -18,6 +19,7 @@ impl fmt::Display for Nope { Nope::ResourceNotFound => "Requested resource not found", Nope::CrateNotFound => "Requested crate not found", Nope::NoResults => "Search yielded no results", + Nope::InternalServerError => "Internal server error", }) } } @@ -59,6 +61,13 @@ impl Handler for Nope { .to_resp("releases") } } + Nope::InternalServerError => { + // something went wrong, details should have been logged + Page::new("internal server error".to_owned()) + .set_status(status::InternalServerError) + .title("Internal server error") + .to_resp("error") + } } } } diff --git a/src/web/mod.rs b/src/web/mod.rs index 930e93e51..32172068d 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -138,26 +138,42 @@ impl CratesfyiHandler { impl Handler for CratesfyiHandler { fn handle(&self, req: &mut Request) -> IronResult { + fn if_404( + e: IronError, + handle: impl FnOnce() -> IronResult, + ) -> IronResult { + if e.response.status == Some(status::NotFound) { + handle() + } else { + Err(e) + } + }; + // try serving shared rustdoc resources first, then router, then db/static file handler // return 404 if none of them return Ok self.shared_resource_handler .handle(req) - .or_else(|e| self.router_handler.handle(req).or(Err(e))) - .or_else(|e| { - // if router fails try to serve files from database first - self.database_file_handler.handle(req).or(Err(e)) - }) - .or_else(|e| { - // and then try static handler. if all of them fails, return 404 - self.static_handler.handle(req).or(Err(e)) - }) + .or_else(|e| if_404(e, || self.router_handler.handle(req))) + .or_else(|e| if_404(e, || self.database_file_handler.handle(req))) + .or_else(|e| if_404(e, || self.static_handler.handle(req))) .or_else(|e| { let err = if let Some(err) = e.error.downcast::() { *err - } else if e.error.downcast::().is_some() { + } else if e.error.downcast::().is_some() + || e.response.status == Some(status::NotFound) + { error::Nope::ResourceNotFound + } else if e.response.status == Some(status::InternalServerError) { + log::error!("internal server error: {}", e.error); + error::Nope::InternalServerError } else { - panic!("all cratesfyi errors should be of type Nope"); + log::error!( + "No error page for status {:?}; {}", + e.response.status, + e.error + ); + // TODO: add in support for other errors that are actually used + error::Nope::InternalServerError }; if let error::Nope::ResourceNotFound = err { @@ -181,7 +197,7 @@ impl Handler for CratesfyiHandler { } } - debug!("Path not found: {}", DebugPath(&req.url)); + debug!("Path not found: {}; {}", DebugPath(&req.url), e.error); } Self::chain(self.pool.clone(), err).handle(req)