webserver_base/webserver/
error.rs1use std::net::SocketAddr;
4
5use axum::http::StatusCode;
6use axum::response::{IntoResponse, Response};
7use tracing::error;
8
9use crate::env::EnvError;
10
11#[derive(thiserror::Error)]
17pub enum WebServerError {
18 #[error(transparent)]
20 Env(#[from] EnvError),
21
22 #[error("failed to bind to {addr}")]
24 Bind {
25 addr: SocketAddr,
26 #[source]
27 source: std::io::Error,
28 },
29
30 #[cfg(feature = "analytics")]
32 #[error("the browser Sentry DSN is malformed")]
33 SentryDsn(#[from] crate::analytics::SentryDsnParseError),
34
35 #[error("the server stopped unexpectedly")]
37 Serve(#[source] std::io::Error),
38
39 #[cfg(feature = "templates")]
41 #[error(transparent)]
42 Template(#[from] crate::templates::TemplateError),
43
44 #[cfg(feature = "templates")]
46 #[error("cannot render: the server was built without `.templates(..)`")]
47 TemplatesNotConfigured,
48
49 #[cfg(feature = "webserver")]
51 #[error(transparent)]
52 CacheBuster(#[from] crate::assets::CacheBusterError),
53
54 #[cfg(feature = "sitemap")]
56 #[error(transparent)]
57 Sitemap(#[from] crate::sitemap::SitemapError),
58
59 #[cfg(feature = "observability")]
61 #[error(transparent)]
62 Observability(#[from] crate::observability::ObservabilityError),
63
64 #[cfg(feature = "pages")]
67 #[error("`.pages(..)` requires `.templates(..)`: the sitemap needs the site's base url")]
68 PagesRequireTemplates,
69
70 #[cfg(feature = "pages")]
73 #[error(
74 "page path `{path}` contains a route parameter; \
75 use `dynamic_page_group` with concrete urls, or mark it unlisted"
76 )]
77 DynamicPagePathHasParameters { path: String },
78}
79
80impl IntoResponse for WebServerError {
81 fn into_response(self) -> Response {
83 error!("request failed: {self}");
84 (StatusCode::INTERNAL_SERVER_ERROR, "internal server error").into_response()
85 }
86}
87
88impl std::fmt::Debug for WebServerError {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 writeln!(f, "{self}")?;
98
99 let mut source: Option<&(dyn std::error::Error + 'static)> =
100 std::error::Error::source(self);
101 while let Some(error) = source {
102 writeln!(f, " caused by: {error}")?;
103 source = error.source();
104 }
105 Ok(())
106 }
107}