reth_rpc_builder/
cors.rs

1use http::{HeaderValue, Method};
2use tower_http::cors::{AllowOrigin, Any, CorsLayer};
3
4/// Error thrown when parsing cors domains went wrong
5#[derive(Debug, thiserror::Error)]
6pub enum CorsDomainError {
7    /// Represents an invalid header value for a domain
8    #[error("{domain} is an invalid header value")]
9    InvalidHeader {
10        /// The domain that caused the invalid header
11        domain: String,
12    },
13
14    /// Indicates that a wildcard origin was used incorrectly in a list
15    #[error("wildcard origin (`*`) cannot be passed as part of a list: {input}")]
16    WildCardNotAllowed {
17        /// The input string containing the incorrectly used wildcard
18        input: String,
19    },
20}
21
22/// Creates a [`CorsLayer`] from the given domains
23pub(crate) fn create_cors_layer(http_cors_domains: &str) -> Result<CorsLayer, CorsDomainError> {
24    let cors = match http_cors_domains.trim() {
25        "*" => CorsLayer::new()
26            .allow_methods([Method::GET, Method::POST])
27            .allow_origin(Any)
28            .allow_headers(Any),
29        _ => {
30            let iter = http_cors_domains.split(',');
31            if iter.clone().any(|o| o == "*") {
32                return Err(CorsDomainError::WildCardNotAllowed {
33                    input: http_cors_domains.to_string(),
34                })
35            }
36
37            let origins = iter
38                .map(|domain| {
39                    domain
40                        .parse::<HeaderValue>()
41                        .map_err(|_| CorsDomainError::InvalidHeader { domain: domain.to_string() })
42                })
43                .collect::<Result<Vec<HeaderValue>, _>>()?;
44
45            let origin = AllowOrigin::list(origins);
46            CorsLayer::new()
47                .allow_methods([Method::GET, Method::POST])
48                .allow_origin(origin)
49                .allow_headers(Any)
50        }
51    };
52    Ok(cors)
53}