Skip to main content

api_tools/server/axum/layers/
mod.rs

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