servers/http/result/
error_result.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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}