nixfleet_control_plane/server/
route_error.rs

1//! Shared route-handler error helpers. Each returns a `FnOnce(E) -> StatusCode`
2//! that logs and converts - paired with `?` to drop the 4-line map_err blocks.
3
4use axum::http::StatusCode;
5use std::fmt::Display;
6
7/// `.map_err(internal("label: detail"))` -> log at error + 500.
8pub(crate) fn internal<E: Display>(label: &'static str) -> impl FnOnce(E) -> StatusCode {
9    move |err| {
10        tracing::error!(error = %err, "{label}");
11        StatusCode::INTERNAL_SERVER_ERROR
12    }
13}
14
15/// `.map_err(bad_request("label: detail"))` -> log at warn + 400.
16pub(crate) fn bad_request<E: Display>(label: &'static str) -> impl FnOnce(E) -> StatusCode {
17    move |err| {
18        tracing::warn!(error = %err, "{label}");
19        StatusCode::BAD_REQUEST
20    }
21}
22
23/// `.map_err(bad_request_error("label: detail"))` - log level escalated to
24/// error (handler-side reasons indicate a CP bug, not a malformed request).
25pub(crate) fn bad_request_error<E: Display>(label: &'static str) -> impl FnOnce(E) -> StatusCode {
26    move |err| {
27        tracing::error!(error = %err, "{label}");
28        StatusCode::BAD_REQUEST
29    }
30}
31
32/// `.map_err(internal_warn("label: detail"))` - same as `internal` but at
33/// warn level. For DB-side queries where a transient miss isn't a CP bug.
34pub(crate) fn internal_warn<E: Display>(label: &'static str) -> impl FnOnce(E) -> StatusCode {
35    move |err| {
36        tracing::warn!(error = %err, "{label}");
37        StatusCode::INTERNAL_SERVER_ERROR
38    }
39}