Improve internal server errors significantly
This commit is contained in:
parent
a3c823c7b2
commit
9d44593e73
@ -3,6 +3,7 @@ pub mod checker;
|
||||
pub mod config;
|
||||
pub mod manager;
|
||||
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
@ -21,6 +22,12 @@ impl Name {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.utf8_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Name {
|
||||
type Err = <trust_dns_rr::Name as FromStr>::Err;
|
||||
|
||||
|
@ -91,7 +91,7 @@ struct DomainSyncArgs {
|
||||
}
|
||||
|
||||
impl<'svc> Service {
|
||||
fn serve(&self, status_code: u16, path: &'_ str, body: Body) -> Response<Body> {
|
||||
fn serve(&self, status_code: u16, path: &str, body: Body) -> Response<Body> {
|
||||
let content_type = mime_guess::from_path(path)
|
||||
.first_or_octet_stream()
|
||||
.to_string();
|
||||
@ -103,20 +103,19 @@ impl<'svc> Service {
|
||||
{
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
// if the status code was already a 500, don't try to render _another_ 500, it'll
|
||||
// probably fail for the same reason. At this point something is incredibly wrong,
|
||||
// just panic.
|
||||
if status_code == 500 {
|
||||
panic!("failed to build {}: {}", path, err);
|
||||
}
|
||||
|
||||
self.serve(
|
||||
500,
|
||||
"error.txt",
|
||||
format!("failed to build {}: {}", path, err).into(),
|
||||
)
|
||||
self.internal_error(format!("failed to build {}: {}", path, err).as_str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render<T>(&self, status_code: u16, name: &'_ str, value: T) -> Response<Body>
|
||||
fn render<T>(&self, status_code: u16, name: &str, value: T) -> Response<Body>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
@ -134,7 +133,7 @@ impl<'svc> Service {
|
||||
self.serve(status_code, name, rendered.into())
|
||||
}
|
||||
|
||||
fn render_error_page(&self, status_code: u16, e: &'_ str) -> Response<Body> {
|
||||
fn render_error_page(&self, status_code: u16, e: &str) -> Response<Body> {
|
||||
#[derive(Serialize)]
|
||||
struct Response<'a> {
|
||||
error_msg: &'a str,
|
||||
@ -150,7 +149,15 @@ impl<'svc> Service {
|
||||
)
|
||||
}
|
||||
|
||||
fn render_page<T>(&self, name: &'_ str, data: T) -> Response<Body>
|
||||
fn internal_error(&self, e: &str) -> Response<Body> {
|
||||
log::error!("Internal error: {e}");
|
||||
self.render_error_page(
|
||||
500,
|
||||
"An unexpected error occurred. The server administrator will be able to help.",
|
||||
)
|
||||
}
|
||||
|
||||
fn render_page<T>(&self, name: &str, data: T) -> Response<Body>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
@ -164,7 +171,7 @@ impl<'svc> Service {
|
||||
)
|
||||
}
|
||||
|
||||
fn serve_origin(&self, domain: domain::Name, path: &'_ str) -> Response<Body> {
|
||||
fn serve_origin(&self, domain: domain::Name, path: &str) -> Response<Body> {
|
||||
let mut path_owned;
|
||||
|
||||
let path = match path.ends_with('/') {
|
||||
@ -185,7 +192,7 @@ impl<'svc> Service {
|
||||
self.render_error_page(404, "File not found")
|
||||
}
|
||||
Err(domain::manager::GetFileError::Unexpected(e)) => {
|
||||
self.render_error_page(500, format!("failed to fetch file {path}: {e}").as_str())
|
||||
self.internal_error(format!("failed to fetch file {path}: {e}").as_str())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,11 +206,9 @@ impl<'svc> Service {
|
||||
let query = req.uri().query().unwrap_or("");
|
||||
match serde_urlencoded::from_str::<In>(query) {
|
||||
Ok(args) => f(args).await,
|
||||
Err(err) => self.serve(
|
||||
400,
|
||||
"error.txt",
|
||||
format!("failed to parse query args: {}", err).into(),
|
||||
),
|
||||
Err(err) => {
|
||||
self.render_error_page(400, format!("failed to parse query args: {}", err).as_str())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,8 +223,13 @@ impl<'svc> Service {
|
||||
Ok(config) => Some(config),
|
||||
Err(domain::manager::GetConfigError::NotFound) => None,
|
||||
Err(domain::manager::GetConfigError::Unexpected(e)) => {
|
||||
return self
|
||||
.render_error_page(500, format!("retrieving configuration: {}", e).as_str());
|
||||
return self.internal_error(
|
||||
format!(
|
||||
"retrieving configuration for domain {}: {}",
|
||||
&args.domain, e
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -256,8 +266,9 @@ impl<'svc> Service {
|
||||
let config_hash = match config.hash() {
|
||||
Ok(hash) => hash,
|
||||
Err(e) => {
|
||||
return self
|
||||
.render_error_page(500, format!("failed to hash domain config: {e}").as_str())
|
||||
return self.internal_error(
|
||||
format!("failed to hash domain config {config:?}: {e}").as_str(),
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
@ -326,9 +337,7 @@ impl<'svc> Service {
|
||||
|
||||
let domains = match self.domain_manager.all_domains() {
|
||||
Ok(domains) => domains,
|
||||
Err(e) => {
|
||||
return self.render_error_page(500, format!("failed get all domains: {e}").as_str())
|
||||
}
|
||||
Err(e) => return self.internal_error(format!("failed get all domains: {e}").as_str()),
|
||||
};
|
||||
|
||||
let mut domains: Vec<String> = domains
|
||||
@ -406,7 +415,10 @@ impl<'svc> Service {
|
||||
.await
|
||||
}
|
||||
(&Method::GET, "/domains.html") => self.domains(),
|
||||
_ => self.render_error_page(404, "Page not found!"),
|
||||
_ => self.render_error_page(
|
||||
404,
|
||||
"This is not the page you're looking for. This page doesn't even exist!",
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user