arcly_http/http.rs
1//! Zero-axum public HTTP types.
2//!
3//! User code says `arcly_http::Response`, `arcly_http::Json`, etc. — no
4//! `axum::…` paths in the public surface. Internally these are thin
5//! delegations to axum, so we keep its battle-tested implementation without
6//! welding it into the public API.
7//!
8//! Why a private `axum::response::Response` re-export rather than a full
9//! newtype: pinning `axum::response::Response` is the *one* type the
10//! framework's boundary code constructs; making it a newtype would force
11//! every adapter / interceptor to unwrap repeatedly with zero behavioural
12//! benefit. A `pub use` rename achieves the same "no axum in user paths"
13//! outcome at zero runtime cost.
14
15use serde::Serialize;
16
17/// The framework's response type. Same memory shape as axum's; the alias
18/// keeps the user-visible path `arcly_http::Response`.
19pub use axum::response::Response;
20
21/// Convert a value into a `Response`.
22///
23/// `arcly_http::IntoResponse` is a thin re-trait over axum's so user code
24/// never types `axum`. A blanket impl makes every axum-compatible type
25/// automatically satisfy ours.
26pub trait IntoResponse: Sized {
27 fn into_response(self) -> Response;
28}
29
30impl<T: axum::response::IntoResponse> IntoResponse for T {
31 #[inline]
32 fn into_response(self) -> Response {
33 axum::response::IntoResponse::into_response(self)
34 }
35}
36
37/// JSON response wrapper. `Json(body)` writes `Content-Type: application/json`
38/// and serialises `body` with `serde_json`. Same surface as axum's `Json` so
39/// the route macro's return-type walker (`Json<T> | Result<Json<T>, _>`)
40/// keeps working without changes.
41pub struct Json<T>(pub T);
42
43impl<T: Serialize> axum::response::IntoResponse for Json<T> {
44 #[inline]
45 fn into_response(self) -> axum::response::Response {
46 axum::response::IntoResponse::into_response(axum::Json(self.0))
47 }
48}
49
50impl<T> From<T> for Json<T> {
51 #[inline]
52 fn from(v: T) -> Self {
53 Json(v)
54 }
55}