use std::net::SocketAddr;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use tracing::error;
use crate::env::EnvError;
#[derive(thiserror::Error)]
pub enum WebServerError {
#[error(transparent)]
Env(#[from] EnvError),
#[error("failed to bind to {addr}")]
Bind {
addr: SocketAddr,
#[source]
source: std::io::Error,
},
#[cfg(feature = "analytics")]
#[error("the browser Sentry DSN is malformed")]
SentryDsn(#[from] crate::analytics::SentryDsnParseError),
#[error("the server stopped unexpectedly")]
Serve(#[source] std::io::Error),
#[cfg(feature = "templates")]
#[error(transparent)]
Template(#[from] crate::templates::TemplateError),
#[cfg(feature = "templates")]
#[error("cannot render: the server was built without `.templates(..)`")]
TemplatesNotConfigured,
#[cfg(feature = "webserver")]
#[error(transparent)]
CacheBuster(#[from] crate::assets::CacheBusterError),
#[cfg(feature = "sitemap")]
#[error(transparent)]
Sitemap(#[from] crate::sitemap::SitemapError),
#[cfg(feature = "feed")]
#[error(transparent)]
Feed(#[from] crate::feed::FeedError),
#[cfg(feature = "feed")]
#[error("cannot serve a feed: the server was built without `.frontend(..)`")]
FeedWithoutFrontend,
#[cfg(feature = "observability")]
#[error(transparent)]
Observability(#[from] crate::observability::ObservabilityError),
#[cfg(feature = "pages")]
#[error("`.pages(..)` requires `.templates(..)`: the sitemap needs the site's base url")]
PagesRequireTemplates,
#[cfg(feature = "pages")]
#[error(
"page path `{path}` contains a route parameter; \
use `dynamic_page_group` with concrete urls, or mark it unlisted"
)]
DynamicPagePathHasParameters { path: String },
}
impl IntoResponse for WebServerError {
fn into_response(self) -> Response {
error!("request failed: {self}");
(StatusCode::INTERNAL_SERVER_ERROR, "internal server error").into_response()
}
}
impl std::fmt::Debug for WebServerError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{self}")?;
let mut source: Option<&(dyn std::error::Error + 'static)> =
std::error::Error::source(self);
while let Some(error) = source {
writeln!(f, " caused by: {error}")?;
source = error.source();
}
Ok(())
}
}