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 config;
|
||||||
pub mod manager;
|
pub mod manager;
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
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 {
|
impl FromStr for Name {
|
||||||
type Err = <trust_dns_rr::Name as FromStr>::Err;
|
type Err = <trust_dns_rr::Name as FromStr>::Err;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ struct DomainSyncArgs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'svc> Service {
|
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)
|
let content_type = mime_guess::from_path(path)
|
||||||
.first_or_octet_stream()
|
.first_or_octet_stream()
|
||||||
.to_string();
|
.to_string();
|
||||||
@ -103,20 +103,19 @@ impl<'svc> Service {
|
|||||||
{
|
{
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => {
|
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 {
|
if status_code == 500 {
|
||||||
panic!("failed to build {}: {}", path, err);
|
panic!("failed to build {}: {}", path, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.serve(
|
self.internal_error(format!("failed to build {}: {}", path, err).as_str())
|
||||||
500,
|
|
||||||
"error.txt",
|
|
||||||
format!("failed to build {}: {}", path, err).into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
where
|
||||||
T: Serialize,
|
T: Serialize,
|
||||||
{
|
{
|
||||||
@ -134,7 +133,7 @@ impl<'svc> Service {
|
|||||||
self.serve(status_code, name, rendered.into())
|
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)]
|
#[derive(Serialize)]
|
||||||
struct Response<'a> {
|
struct Response<'a> {
|
||||||
error_msg: &'a str,
|
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
|
where
|
||||||
T: Serialize,
|
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 mut path_owned;
|
||||||
|
|
||||||
let path = match path.ends_with('/') {
|
let path = match path.ends_with('/') {
|
||||||
@ -185,7 +192,7 @@ impl<'svc> Service {
|
|||||||
self.render_error_page(404, "File not found")
|
self.render_error_page(404, "File not found")
|
||||||
}
|
}
|
||||||
Err(domain::manager::GetFileError::Unexpected(e)) => {
|
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("");
|
let query = req.uri().query().unwrap_or("");
|
||||||
match serde_urlencoded::from_str::<In>(query) {
|
match serde_urlencoded::from_str::<In>(query) {
|
||||||
Ok(args) => f(args).await,
|
Ok(args) => f(args).await,
|
||||||
Err(err) => self.serve(
|
Err(err) => {
|
||||||
400,
|
self.render_error_page(400, format!("failed to parse query args: {}", err).as_str())
|
||||||
"error.txt",
|
}
|
||||||
format!("failed to parse query args: {}", err).into(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,8 +223,13 @@ impl<'svc> Service {
|
|||||||
Ok(config) => Some(config),
|
Ok(config) => Some(config),
|
||||||
Err(domain::manager::GetConfigError::NotFound) => None,
|
Err(domain::manager::GetConfigError::NotFound) => None,
|
||||||
Err(domain::manager::GetConfigError::Unexpected(e)) => {
|
Err(domain::manager::GetConfigError::Unexpected(e)) => {
|
||||||
return self
|
return self.internal_error(
|
||||||
.render_error_page(500, format!("retrieving configuration: {}", e).as_str());
|
format!(
|
||||||
|
"retrieving configuration for domain {}: {}",
|
||||||
|
&args.domain, e
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -256,8 +266,9 @@ impl<'svc> Service {
|
|||||||
let config_hash = match config.hash() {
|
let config_hash = match config.hash() {
|
||||||
Ok(hash) => hash,
|
Ok(hash) => hash,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return self
|
return self.internal_error(
|
||||||
.render_error_page(500, format!("failed to hash domain config: {e}").as_str())
|
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() {
|
let domains = match self.domain_manager.all_domains() {
|
||||||
Ok(domains) => domains,
|
Ok(domains) => domains,
|
||||||
Err(e) => {
|
Err(e) => return self.internal_error(format!("failed get all domains: {e}").as_str()),
|
||||||
return self.render_error_page(500, format!("failed get all domains: {e}").as_str())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut domains: Vec<String> = domains
|
let mut domains: Vec<String> = domains
|
||||||
@ -406,7 +415,10 @@ impl<'svc> Service {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
(&Method::GET, "/domains.html") => self.domains(),
|
(&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