servers/http/result/
error_result.rs1use axum::response::{IntoResponse, Response};
16use axum::Json;
17use common_error::ext::ErrorExt;
18use common_error::from_err_code_msg_to_header;
19use common_error::status_code::StatusCode;
20use common_telemetry::{debug, error};
21use serde::{Deserialize, Serialize};
22
23use crate::error::status_code_to_http_status;
24
25#[derive(Serialize, Deserialize, Debug)]
26pub struct ErrorResponse {
27 code: u32,
28 error: String,
29 execution_time_ms: u64,
30}
31
32impl ErrorResponse {
33 pub fn from_error(error: impl ErrorExt) -> Self {
34 let code = error.status_code();
35
36 if code.should_log_error() {
37 error!(error; "Failed to handle HTTP request");
38 } else {
39 debug!("Failed to handle HTTP request, err: {:?}", error);
40 }
41
42 Self::from_error_message(code, error.output_msg())
43 }
44
45 pub fn from_error_message(code: StatusCode, msg: String) -> Self {
46 ErrorResponse {
47 code: code as u32,
48 error: msg,
49 execution_time_ms: 0,
50 }
51 }
52
53 pub fn with_execution_time(mut self, execution_time: u64) -> Self {
54 self.execution_time_ms = execution_time;
55 self
56 }
57
58 pub fn execution_time_ms(&self) -> u64 {
59 self.execution_time_ms
60 }
61
62 pub fn code(&self) -> u32 {
63 self.code
64 }
65
66 pub fn error(&self) -> &str {
67 &self.error
68 }
69}
70
71impl IntoResponse for ErrorResponse {
72 fn into_response(self) -> Response {
73 let code = self.code;
74 let execution_time = self.execution_time_ms;
75 let new_header = from_err_code_msg_to_header(
76 code,
77 &format!(
78 "error: {}, execution_time_ms: {}",
79 self.error, execution_time
80 ),
81 );
82 let mut resp = Json(self).into_response();
83 resp.headers_mut().extend(new_header);
84
85 let status = StatusCode::from_u32(code).unwrap_or(StatusCode::Unknown);
86 let status_code = status_code_to_http_status(&status);
87
88 (status_code, resp).into_response()
89 }
90}