api_tools/server/axum/layers/
mod.rs

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