The goal of this package is to provide an easy way to build a "configuration struct" for your rust program, where you can combine data from multiple sources (cli arguments, environment, configuration file, defaults) to build a typed configuration object.
This is done by providing a trait your struct can derive
. When you add #[derive(AppConfig)]
to your struct, it will implement the AppConfig
trait, creating a Builder
type, and providing the fn builder() -> Self::Builder
function. This Builder
type can be used to specify fields with the "builder pattern", load available fields from the environment, load fields from a file, and combine the fields of multiple builders. The builder can be turned into your struct with the function try_build()
, which fails if there are missing fields.
#[derive(AppConfig)]
struct MyConfig {
field_a: String,
field_b: usize,
#[config_field(default = true)]
field_c: bool,
}
fn get_config() -> MyConfig {
MyConfig::builder()
.from_env()
.unwrap()
.field_a("foo".into())
.combine(MyConfig::builder().default())
.try_build()
.unwrap()
}
If we set the environment variable CONFIG_FIELD_B=123
, and call get_config
defined above, we should get an object that looks like this:
MyConfig {
field_a: "foo",
field_b: 123,
field_c: true,
}
You can also use it in more complex cases, like below, with nested structs, deserialization, and combining multiple builders/sources. Earlier sources take precedent, so in this case the priority of the fields are:
port
is always set toPORT_NUMBER_FROM_CLI
- Then environment variables (like
COOL_APP_POSTGRES_PASSWORD=secret
) - Then values from the yaml file/string
CONFIG_YML
- Then default values
#[derive(AppConfig)]
#[builder_derive(Deserialize)]
struct PostgresConfig {
username: String,
password: String,
}
#[derive(AppConfig)]
#[builder_derive(Deserialize)]
struct CoolAppConfig {
#[config_field(default = 8080_u16)]
port: u16,
#[config_field(default = [127, 0, 0, 1])]
addr: std::net::IpAddr,
#[nested_field]
postgres: PostgresConfig,
#[config_field(default = "example.com")]
public_url: String,
}
static CONFIG_YML: &'static str = r#"
addr: 0.0.0.0
postgres:
username: postgres
password: changeme
"#;
static PORT_NUMBER_FROM_CLI: u16 = 80;
fn get_cool_app_config() -> CoolAppConfig {
CoolAppConfig::builder()
.port(PORT_NUMBER_FROM_CLI)
.combine(
CoolAppConfig::builder()
.from_env_prefixed("COOL_APP")
.unwrap(),
)
.combine(serde_yaml::from_str(CONFIG_YML).unwrap())
.combine(CoolAppConfig::builder().default())
.try_build()
.unwrap()
}
If we call get_cool_app_config
with the environment variable COOL_APP_POSTGRES_PASSWORD=secret
set, we should get something that looks like this:
CoolAppConfig {
port: 80,
addr: std::net::IpAddr::from([0, 0, 0, 0]),
postgres: PostgresConfig {
username: "postgres",
password: "secret",
},
public_url: "example.com",
}