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
use http::{Request, Response};
use hyper::Body;
use std::convert::TryFrom;
use std::sync::Arc;
use tokio::sync::Mutex;

use crate::addon::cors::Cors;
use crate::config::cors::CorsConfig;

use super::MiddlewareAfter;

/// Creates a CORS middleware with the configuration provided and returns it.
/// The configured headers will be appended to every HTTP Response before
/// sending such response back to the client (After Middleware)
///
/// CORS headers for every response are built on server initialization and
/// then are "appended" to Response headers on every response.
///
/// # Panics
///
/// Panics if a CORS config is not defined for the `Config` instance provided.
/// (`Config.cors` is `None`).
/// `make_cors_middlware` should only be called when a `CorsConfig` is defined.
///
/// Also panics if any CORS header value is not a valid UTF-8 string
pub fn make_cors_middleware(cors_config: CorsConfig) -> MiddlewareAfter {
    let cors = Cors::try_from(cors_config).unwrap();
    let cors_headers = cors.make_http_headers();

    Box::new(
        move |_: Arc<Mutex<Request<Body>>>, response: Arc<Mutex<Response<Body>>>| {
            let cors_headers = cors_headers.clone();
            let response = Arc::clone(&response);

            Box::pin(async move {
                let mut response = response.lock().await;

                let headers = response.headers_mut();

                cors_headers.iter().for_each(|(header, value)| {
                    headers.append(header, value.to_owned());
                });

                Ok(())
            })
        },
    )
}