Skip to main content

postcrate_core/http/
error.rs

1//! `IntoResponse` for our crate `Error`. The wire shape is the
2//! `{error, message}` object used elsewhere in the API.
3
4use axum::http::StatusCode;
5use axum::response::{IntoResponse, Response};
6use axum::Json;
7use serde::Serialize;
8
9use crate::error::Error;
10
11#[derive(Serialize)]
12struct ErrorBody<'a> {
13    error: &'a str,
14    message: String,
15}
16
17impl IntoResponse for Error {
18    fn into_response(self) -> Response {
19        // Log internal-class errors at warn level so they show up in
20        // CI logs without spamming production output for 4xx cases.
21        if self.http_status().as_u16() >= 500 {
22            tracing::warn!(target: "postcrate::http", error = %self, code = self.code());
23        }
24        let status = self.http_status();
25        let body = ErrorBody {
26            error: self.code(),
27            message: self.to_string(),
28        };
29        // We can't safely map every error variant to a non-500 — if a
30        // DB error somehow leaks, give the client a 500 not a panic.
31        let status = if matches!(status, StatusCode::OK) {
32            StatusCode::INTERNAL_SERVER_ERROR
33        } else {
34            status
35        };
36        (status, Json(body)).into_response()
37    }
38}