Skip to content

Commit

Permalink
enable cors (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc authored Nov 16, 2023
1 parent 06047b7 commit b908466
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ chrono = "0.4.24"
clap = { version = "4.1.1", features = ["derive"] }
enumflags2 = "0.7.7"
futures = "0.3.25"
http = "0.2.8"
hyper = "0.14.23"
log = "0.4.17"
moka = { version = "0.11.0", features = ["future"] }
Expand Down
1 change: 1 addition & 0 deletions benches/bench/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ fn config() -> Config {
max_connections: 1024 * 1024,
request_timeout_seconds: 120,
http_methods: Vec::new(),
cors: None,
}),
substrate_api: Some(SubstrateApiConfig {
stale_timeout_seconds: 5_000,
Expand Down
1 change: 1 addition & 0 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extensions:
method: system_health
- path: /liveness
method: chain_getBlockHash
cors: all

middlewares:
methods:
Expand Down
1 change: 1 addition & 0 deletions eth_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extensions:
port: 8545
listen_address: '0.0.0.0'
max_connections: 2000
cors: all

middlewares:
methods:
Expand Down
64 changes: 51 additions & 13 deletions src/extensions/server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::{future::Future, net::SocketAddr};

use async_trait::async_trait;
use http::header::HeaderValue;
use jsonrpsee::server::{RandomStringIdProvider, RpcModule, ServerBuilder, ServerHandle};
use serde::Deserialize;
use tower_http::cors::{AllowOrigin, CorsLayer};

use super::{Extension, ExtensionRegistry};
use proxy_get_request::ProxyGetRequestLayer;
Expand All @@ -21,6 +23,22 @@ pub struct HttpMethodsConfig {
pub method: String,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum ItemOrList<T> {
Item(T),
List(Vec<T>),
}

impl<T> ItemOrList<T> {
fn into_list(self) -> Vec<T> {
match self {
ItemOrList::Item(item) => vec![item],
ItemOrList::List(list) => list,
}
}
}

#[derive(Deserialize, Debug, Clone)]
pub struct ServerConfig {
pub port: u16,
Expand All @@ -30,6 +48,8 @@ pub struct ServerConfig {
pub http_methods: Vec<HttpMethodsConfig>,
#[serde(default = "default_request_timeout_seconds")]
pub request_timeout_seconds: u64,
#[serde(default)]
pub cors: Option<ItemOrList<String>>,
}

fn default_request_timeout_seconds() -> u64 {
Expand All @@ -45,6 +65,22 @@ impl Extension for SubwayServerBuilder {
}
}

fn cors_layer(cors: Option<ItemOrList<String>>) -> anyhow::Result<CorsLayer> {
let origins = cors.map(|c| c.into_list()).unwrap_or_default();

match origins.as_slice() {
[] => Ok(CorsLayer::new()),
[origin] if origin == "*" || origin == "all" => Ok(CorsLayer::permissive()),
origins => {
let list = origins
.iter()
.map(|o| HeaderValue::from_str(o))
.collect::<Result<Vec<_>, _>>()?;
Ok(CorsLayer::new().allow_origin(AllowOrigin::list(list)))
}
}
}

impl SubwayServerBuilder {
pub fn new(config: ServerConfig) -> Self {
Self { config }
Expand All @@ -54,19 +90,21 @@ impl SubwayServerBuilder {
&self,
builder: impl FnOnce() -> Fut,
) -> anyhow::Result<(SocketAddr, ServerHandle)> {
let service_builder = tower::ServiceBuilder::new().layer(
ProxyGetRequestLayer::new(
self.config
.http_methods
.iter()
.map(|m| ProxyGetRequestMethod {
path: m.path.clone(),
method: m.method.clone(),
})
.collect(),
)
.expect("Invalid health config"),
);
let service_builder = tower::ServiceBuilder::new()
.layer(cors_layer(self.config.cors.clone()).expect("Invalid CORS config"))
.layer(
ProxyGetRequestLayer::new(
self.config
.http_methods
.iter()
.map(|m| ProxyGetRequestMethod {
path: m.path.clone(),
method: m.method.clone(),
})
.collect(),
)
.expect("Invalid health config"),
);

let server = ServerBuilder::default()
.set_middleware(service_builder)
Expand Down
1 change: 1 addition & 0 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ mod tests {
max_connections: 1024,
request_timeout_seconds: request_timeout_seconds.unwrap_or(10),
http_methods: Vec::new(),
cors: None,
}),
..Default::default()
},
Expand Down
1 change: 1 addition & 0 deletions src/tests/merge_subscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ async fn merge_subscription_works() {
max_connections: 10,
request_timeout_seconds: 120,
http_methods: Vec::new(),
cors: None,
}),
merge_subscription: Some(MergeSubscriptionConfig {
keep_alive_seconds: Some(1),
Expand Down
1 change: 1 addition & 0 deletions src/tests/upstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ async fn upstream_error_propagate() {
max_connections: 10,
request_timeout_seconds: 120,
http_methods: Vec::new(),
cors: None,
}),
merge_subscription: Some(MergeSubscriptionConfig {
keep_alive_seconds: Some(1),
Expand Down

0 comments on commit b908466

Please sign in to comment.