cratestack_axum/rpc/
error_encode.rs1use axum::http::HeaderMap;
5use cratestack_core::CoolError;
6use cratestack_core::rpc::RpcErrorBody;
7use serde::Serialize;
8
9use crate::HttpTransport;
10
11use super::RPC_BINDING_CAPABILITIES;
12use super::codec_helpers::decode_rpc_body;
13use super::util::synthesize_error_for_status;
14
15pub fn encode_rpc_error<C>(
22 codec: &C,
23 headers: &HeaderMap,
24 error: &CoolError,
25) -> axum::response::Response
26where
27 C: HttpTransport,
28{
29 let body = RpcErrorBody::from_cool(error);
30 let status = error.status_code();
31 encode_rpc_value_response(codec, headers, status, body)
32}
33
34pub async fn convert_handler_error_response<C>(
43 response: axum::response::Response,
44 codec: &C,
45 headers: &HeaderMap,
46) -> axum::response::Response
47where
48 C: HttpTransport,
49{
50 if response.status().is_success() {
51 return response;
52 }
53
54 let status = response.status();
55 let body_bytes = match axum::body::to_bytes(response.into_body(), usize::MAX).await {
56 Ok(bytes) => bytes.to_vec(),
57 Err(error) => {
58 let cool = CoolError::Internal(format!("buffer handler error body: {error}"));
60 return encode_rpc_error(codec, headers, &cool);
61 }
62 };
63
64 let rpc_body =
65 match decode_rpc_body::<_, cratestack_core::CoolErrorResponse>(codec, headers, &body_bytes)
66 {
67 Ok(parsed) => RpcErrorBody::from_cool_response(parsed),
68 Err(_) => {
69 let cool = synthesize_error_for_status(status);
74 RpcErrorBody::from_cool(&cool)
75 }
76 };
77
78 encode_rpc_value_response(codec, headers, status, rpc_body)
79}
80
81fn encode_rpc_value_response<C, T>(
82 codec: &C,
83 headers: &HeaderMap,
84 status: axum::http::StatusCode,
85 value: T,
86) -> axum::response::Response
87where
88 C: HttpTransport,
89 T: Serialize,
90{
91 crate::encode_transport_result_with_status_for::<_, T>(
94 codec,
95 headers,
96 &RPC_BINDING_CAPABILITIES,
97 status,
98 Ok(value),
99 )
100}