cratestack_axum/rpc/
error_encode.rs1use axum::http::HeaderMap;
5use cratestack_core::CratestackError;
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: &CratestackError,
25) -> axum::response::Response
26where
27 C: HttpTransport,
28{
29 let body = RpcErrorBody::from_cratestack(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(
56 response.into_body(),
57 cratestack_core::MAX_RESPONSE_REBUFFER_BYTES,
58 )
59 .await
60 {
61 Ok(bytes) => bytes.to_vec(),
62 Err(error) => {
63 let cool = CratestackError::Internal(format!("buffer handler error body: {error}"));
65 return encode_rpc_error(codec, headers, &cool);
66 }
67 };
68
69 let rpc_body = match decode_rpc_body::<_, cratestack_core::CratestackErrorResponse>(
70 codec,
71 headers,
72 &body_bytes,
73 ) {
74 Ok(parsed) => RpcErrorBody::from_cratestack_response(parsed),
75 Err(_) => {
76 let cool = synthesize_error_for_status(status);
81 RpcErrorBody::from_cratestack(&cool)
82 }
83 };
84
85 encode_rpc_value_response(codec, headers, status, rpc_body)
86}
87
88fn encode_rpc_value_response<C, T>(
89 codec: &C,
90 headers: &HeaderMap,
91 status: axum::http::StatusCode,
92 value: T,
93) -> axum::response::Response
94where
95 C: HttpTransport,
96 T: Serialize,
97{
98 crate::encode_transport_result_with_status_for::<_, T>(
101 codec,
102 headers,
103 &RPC_BINDING_CAPABILITIES,
104 status,
105 Ok(value),
106 )
107}