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 = "feed")]
61 #[error(transparent)]
62 Feed(#[from] crate::feed::FeedError),
63
64 #[cfg(feature = "feed")]
70 #[error("cannot serve a feed: the server was built without `.frontend(..)`")]
71 FeedWithoutFrontend,
72
73 #[cfg(feature = "observability")]
75 #[error(transparent)]
76 Observability(#[from] crate::observability::ObservabilityError),
77
78 #[cfg(feature = "pages")]
81 #[error("`.pages(..)` requires `.templates(..)`: the sitemap needs the site's base url")]
82 PagesRequireTemplates,
83
84 #[cfg(feature = "pages")]
87 #[error(
88 "page path `{path}` contains a route parameter; \
89 use `dynamic_page_group` with concrete urls, or mark it unlisted"
90 )]
91 DynamicPagePathHasParameters { path: String },
92}
93
94impl IntoResponse for WebServerError {
95 fn into_response(self) -> Response {
97 error!("request failed: {self}");
98 (StatusCode::INTERNAL_SERVER_ERROR, "internal server error").into_response()
99 }
100}
101
102impl std::fmt::Debug for WebServerError {
110 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111 writeln!(f, "{self}")?;
112
113 let mut source: Option<&(dyn std::error::Error + 'static)> =
114 std::error::Error::source(self);
115 while let Some(error) = source {
116 writeln!(f, " caused by: {error}")?;
117 source = error.source();
118 }
119 Ok(())
120 }
121}