Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Split configs in server and service #671

Merged
merged 12 commits into from
Jan 4, 2023
2 changes: 0 additions & 2 deletions iroh-api/benches/add.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use futures::TryStreamExt;
use iroh_metrics::config::Config as MetricsConfig;
use iroh_resolver::resolver::Resolver;
use iroh_rpc_client::{Client, Config as RpcClientConfig};
use iroh_rpc_types::Addr;
Expand Down Expand Up @@ -44,7 +43,6 @@ fn add_benchmark(c: &mut Criterion) {
let config = StoreConfig {
path: dir.path().join("db"),
rpc_client: rpc_client.clone(),
metrics: MetricsConfig::default(),
};
let (_task, client, resolver) = executor.block_on(async {
let store = Store::create(config).await.unwrap();
Expand Down
1 change: 0 additions & 1 deletion iroh-embed/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ impl RocksStoreService {
store_addr: Some(addr.clone()),
channels: Some(1),
},
metrics: Default::default(),
};
let task = mem_store::start(addr.clone(), config).await?;
Ok(Self { task, addr })
Expand Down
129 changes: 122 additions & 7 deletions iroh-gateway/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@ pub const CONFIG_FILE_NAME: &str = "gateway.config.toml";
pub const ENV_PREFIX: &str = "IROH_GATEWAY";
pub const DEFAULT_PORT: u16 = 9050;

/// Configuration for [`iroh-gateway`].
/// The configuration for the gateway server.
///
/// This is the configuration which the gateway server binary needs to run. This is a
/// superset from the configuration needed by the gateway service, which can also run
/// integrated into another binary like iroh-one, iroh-share or iroh-embed.
// TODO: I'd prefer to include [`Config`] under the `gateway` field liek iroh-one does. But
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be done before merging, to avoid the duplication, don’t be afraid to break apis

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, feel free to break this, there's nobody really depending on it yet.

// that's a backwards incompatible change.
// TODO: If this was moved into main.rs it would not need to be public. Our binary is build
// as being outside of the lib crate, hence here it needs to be public.
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct Config {
pub struct ServerConfig {
/// Pretty URL to redirect to
#[serde(default = "String::new")]
pub public_url_base: String,
Expand Down Expand Up @@ -55,7 +63,7 @@ pub struct Config {
pub redirect_to_subdomain: bool,
}

impl Config {
impl ServerConfig {
pub fn new(port: u16, rpc_client: RpcClientConfig) -> Self {
Self {
public_url_base: String::new(),
Expand All @@ -70,6 +78,100 @@ impl Config {
redirect_to_subdomain: false,
}
}
}

impl Default for ServerConfig {
fn default() -> Self {
let inner = Config::default();
Self {
public_url_base: inner.public_url_base,
port: inner.port,
use_denylist: inner.use_denylist,
http_resolvers: inner.http_resolvers,
dns_resolver: inner.dns_resolver,
indexer_endpoint: inner.indexer_endpoint,
rpc_client: inner.rpc_client,
metrics: Default::default(),
headers: inner.headers,
redirect_to_subdomain: inner.redirect_to_subdomain,
}
}
}

impl Source for ServerConfig {
fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
Box::new(self.clone())
}

fn collect(&self) -> Result<Map<String, Value>, ConfigError> {
let rpc_client = self.rpc_client.collect()?;
let mut map: Map<String, Value> = Map::new();
insert_into_config_map(&mut map, "public_url_base", self.public_url_base.clone());
insert_into_config_map(&mut map, "use_denylist", self.use_denylist);
// Some issue between deserializing u64 & u16, converting this to
// an signed int fixes the issue
insert_into_config_map(&mut map, "port", self.port as i32);
insert_into_config_map(&mut map, "headers", collect_headers(&self.headers)?);
insert_into_config_map(&mut map, "rpc_client", rpc_client);
let metrics = self.metrics.collect()?;
insert_into_config_map(&mut map, "metrics", metrics);

if let Some(http_resolvers) = &self.http_resolvers {
insert_into_config_map(&mut map, "http_resolvers", http_resolvers.clone());
}
if let Some(indexer_endpoint) = &self.indexer_endpoint {
insert_into_config_map(&mut map, "indexer_endpoint", indexer_endpoint.clone());
}
Ok(map)
}
}

/// Configuration for [`iroh-gateway`].
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct Config {
/// Pretty URL to redirect to
#[serde(default = "String::new")]
pub public_url_base: String,
/// default port to listen on
pub port: u16,
/// flag to toggle whether the gateway should use denylist on requests
pub use_denylist: bool,
/// URL of gateways to be used by the racing resolver.
/// Strings can either be urls or subdomain gateway roots
/// values without https:// prefix are treated as subdomain gateways (eg: dweb.link)
/// values with are treated as IPFS path gateways (eg: <https://ipfs.io>)
pub http_resolvers: Option<Vec<String>>,
/// Separate resolvers for particular TLDs
#[serde(default = "DnsResolverConfig::default")]
pub dns_resolver: DnsResolverConfig,
/// Indexer node to use.
pub indexer_endpoint: Option<String>,
/// rpc addresses for the gateway & addresses for the rpc client to dial
pub rpc_client: RpcClientConfig,
// NOTE: for toml to serialize properly, the "table" values must be serialized at the end, and
// so much come at the end of the `Config` struct
/// set of user provided headers to attach to all responses
#[serde(with = "http_serde::header_map")]
pub headers: HeaderMap,
/// Redirects to subdomains for path requests
#[serde(default)]
pub redirect_to_subdomain: bool,
}

impl Config {
pub fn new(port: u16, rpc_client: RpcClientConfig) -> Self {
Self {
public_url_base: String::new(),
headers: HeaderMap::new(),
port,
rpc_client,
http_resolvers: None,
dns_resolver: DnsResolverConfig::default(),
indexer_endpoint: None,
use_denylist: false,
redirect_to_subdomain: false,
}
}

pub fn set_default_headers(&mut self) {
self.headers = default_headers();
Expand All @@ -80,6 +182,22 @@ impl Config {
}
}

impl From<ServerConfig> for Config {
fn from(source: ServerConfig) -> Self {
Self {
public_url_base: source.public_url_base,
port: source.port,
use_denylist: source.use_denylist,
http_resolvers: source.http_resolvers,
dns_resolver: source.dns_resolver,
indexer_endpoint: source.indexer_endpoint,
rpc_client: source.rpc_client,
headers: source.headers,
redirect_to_subdomain: source.redirect_to_subdomain,
}
}
}

fn default_headers() -> HeaderMap {
let mut headers = HeaderMap::new();
headers.typed_insert(AccessControlAllowOrigin::ANY);
Expand Down Expand Up @@ -136,7 +254,6 @@ impl Default for Config {
http_resolvers: None,
dns_resolver: DnsResolverConfig::default(),
indexer_endpoint: None,
metrics: MetricsConfig::default(),
use_denylist: false,
redirect_to_subdomain: false,
};
Expand All @@ -160,8 +277,6 @@ impl Source for Config {
insert_into_config_map(&mut map, "port", self.port as i32);
insert_into_config_map(&mut map, "headers", collect_headers(&self.headers)?);
insert_into_config_map(&mut map, "rpc_client", rpc_client);
let metrics = self.metrics.collect()?;
insert_into_config_map(&mut map, "metrics", metrics);

if let Some(http_resolvers) = &self.http_resolvers {
insert_into_config_map(&mut map, "http_resolvers", http_resolvers.clone());
Expand Down Expand Up @@ -228,7 +343,7 @@ mod tests {

#[test]
fn test_collect() {
let default = Config::default();
let default = ServerConfig::default();
let mut expect: Map<String, Value> = Map::new();
expect.insert(
"public_url_base".to_string(),
Expand Down
1 change: 0 additions & 1 deletion iroh-gateway/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ mod tests {
let config = iroh_store::Config {
path: store_dir.path().join("db"),
rpc_client: RpcClientConfig::default(),
metrics: iroh_metrics::config::Config::default(),
};
let store = iroh_store::Store::create(config).await.unwrap();
let task =
Expand Down
5 changes: 3 additions & 2 deletions iroh-gateway/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use clap::Parser;
use iroh_gateway::{
bad_bits::{self, BadBits},
cli::Args,
config::{Config, CONFIG_FILE_NAME, ENV_PREFIX},
config::{Config, ServerConfig, CONFIG_FILE_NAME, ENV_PREFIX},
core::Core,
metrics,
};
Expand All @@ -26,7 +26,7 @@ async fn main() -> Result<()> {
let sources = [Some(cfg_path.as_path()), args.cfg.as_deref()];
let mut config = make_config(
// default
Config::default(),
ServerConfig::default(),
// potential config files
&sources,
// env var prefix for this config
Expand All @@ -44,6 +44,7 @@ async fn main() -> Result<()> {
true => Arc::new(Some(RwLock::new(BadBits::new()))),
false => Arc::new(None),
};
let config = Config::from(config);
let rpc_addr = config
.rpc_addr()
.ok_or_else(|| anyhow!("missing gateway rpc addr"))?;
Expand Down
19 changes: 4 additions & 15 deletions iroh-one/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ impl Config {
self.gateway.rpc_client = self.rpc_client.clone();
self.p2p.rpc_client = self.rpc_client.clone();
self.store.rpc_client = self.rpc_client.clone();
self.gateway.metrics = self.metrics.clone();
self.p2p.metrics = self.metrics.clone();
self.store.metrics = self.metrics.clone();
}
}

Expand All @@ -93,15 +90,14 @@ impl Default for Config {
.join("ipfsd.http");
let rpc_client = Self::default_rpc_config();
let metrics_config = MetricsConfig::default();
let store_config =
default_store_config(None, rpc_client.clone(), metrics_config.clone()).unwrap();
let store_config = default_store_config(None, rpc_client.clone()).unwrap();
let key_store_path = iroh_util::iroh_data_root().unwrap();
Self {
rpc_client: rpc_client.clone(),
metrics: metrics_config.clone(),
metrics: metrics_config,
gateway: iroh_gateway::config::Config::default(),
store: store_config,
p2p: default_p2p_config(rpc_client, metrics_config, key_store_path),
p2p: default_p2p_config(rpc_client, key_store_path),
#[cfg(all(feature = "http-uds-gateway", unix))]
gateway_uds_path: Some(gateway_uds_path),
}
Expand All @@ -111,25 +107,18 @@ impl Default for Config {
fn default_store_config(
store_path: Option<PathBuf>,
ipfsd: RpcClientConfig,
metrics: iroh_metrics::config::Config,
) -> Result<iroh_store::config::Config> {
let path = config_data_path(store_path)?;
Ok(iroh_store::config::Config {
path,
rpc_client: ipfsd,
metrics,
})
}

fn default_p2p_config(
ipfsd: RpcClientConfig,
metrics: iroh_metrics::config::Config,
key_store_path: PathBuf,
) -> iroh_p2p::config::Config {
fn default_p2p_config(ipfsd: RpcClientConfig, key_store_path: PathBuf) -> iroh_p2p::config::Config {
iroh_p2p::config::Config {
libp2p: Libp2pConfig::default(),
rpc_client: ipfsd,
metrics,
key_store_path,
}
}
Expand Down
Loading