zino_axum/response/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use axum::{
    body::Body,
    http::{
        header::{self, HeaderName, HeaderValue},
        StatusCode,
    },
    response::IntoResponse,
};
use zino_http::response::{Rejection, Response, ResponseCode};

/// An HTTP response for `axum`.
pub struct AxumResponse<S: ResponseCode = StatusCode>(Response<S>);

impl<S: ResponseCode> From<Response<S>> for AxumResponse<S> {
    #[inline]
    fn from(response: Response<S>) -> Self {
        Self(response)
    }
}

impl<S: ResponseCode> IntoResponse for AxumResponse<S> {
    #[inline]
    fn into_response(self) -> axum::response::Response {
        build_http_response(self.0)
    }
}

/// An HTTP rejection response for `axum`.
pub struct AxumRejection(Response<StatusCode>);

impl From<Rejection> for AxumRejection {
    #[inline]
    fn from(rejection: Rejection) -> Self {
        Self(rejection.into())
    }
}

impl IntoResponse for AxumRejection {
    #[inline]
    fn into_response(self) -> axum::response::Response {
        build_http_response(self.0)
    }
}

/// Build http response from `zino_core::response::Response`.
pub(crate) fn build_http_response<S: ResponseCode>(
    mut response: Response<S>,
) -> axum::response::Response {
    let mut res = match response.read_bytes() {
        Ok(data) => axum::response::Response::builder()
            .status(response.status_code())
            .header(header::CONTENT_TYPE, response.content_type())
            .body(Body::from(data))
            .unwrap_or_default(),
        Err(err) => axum::response::Response::builder()
            .status(S::INTERNAL_SERVER_ERROR.status_code())
            .header(header::CONTENT_TYPE, "text/plain; charset=utf-8")
            .body(Body::from(err.to_string()))
            .unwrap_or_default(),
    };

    for (key, value) in response.finalize() {
        if let Ok(header_name) = HeaderName::try_from(key.as_ref()) {
            if let Ok(header_value) = HeaderValue::try_from(value) {
                res.headers_mut().insert(header_name, header_value);
            }
        }
    }

    res
}