api_tools/server/axum/layers/
mod.rs

1//! Axum layers
2
3pub mod basic_auth;
4pub mod cors;
5pub mod logger;
6pub mod request_id;
7
8use crate::server::axum::response::ApiErrorResponse;
9use axum::http::header::CONTENT_TYPE;
10use axum::http::response::Parts;
11use axum::http::{HeaderName, HeaderValue, StatusCode};
12use bytes::Bytes;
13use std::str::from_utf8;
14
15/// Construct a response body from `Parts`, status code, message and headers
16pub fn body_from_parts(
17    parts: &mut Parts,
18    status_code: StatusCode,
19    message: &str,
20    headers: Option<Vec<(HeaderName, HeaderValue)>>,
21) -> Bytes {
22    // Status
23    parts.status = status_code;
24
25    // Headers
26    parts
27        .headers
28        .insert(CONTENT_TYPE, HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()));
29    if let Some(headers) = headers {
30        for header in headers {
31            parts.headers.insert(header.0, header.1);
32        }
33    }
34
35    // Body
36    let msg = serde_json::json!(ApiErrorResponse::new(status_code, message));
37
38    Bytes::from(msg.to_string())
39}
40
41/// Convert `HeaderValue` to `&str`
42pub fn header_value_to_str(value: Option<&HeaderValue>) -> &str {
43    match value {
44        Some(value) => from_utf8(value.as_bytes()).unwrap_or_default(),
45        None => "",
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_header_value_to_str() {
55        let header_value = HeaderValue::from_static("test_value");
56        let result = header_value_to_str(Some(&header_value));
57        assert_eq!(result, "test_value");
58
59        let none_result = header_value_to_str(None);
60        assert_eq!(none_result, "");
61    }
62}