confik
confik is a library for reading application configuration split across multiple sources.
Example
Assume that config.toml contains:
=google.com
=root
and the environment contains:
PASSWORD=hunter2
then:
# #[cfg(all(feature = "toml", feature = "env"))]
# {
use confik::{Configuration, EnvSource, FileSource, TomlSource};
#[derive(Debug, PartialEq, Configuration)]
struct Config {
host: String,
username: String,
#[confik(secret)]
password: String,
}
let config = Config::builder()
.override_with(FileSource::new("config.toml"))
.override_with(EnvSource::new().allow_secrets())
.try_build()
.unwrap();
assert_eq!(
config,
Config {
host: "google.com".to_string(),
username: "root".to_string(),
password: "hunter2".to_string(),
}
);
# }
Sources
A [Source] is any type that can create [ConfigurationBuilder]s.
This crate implements the following sources:
- [
EnvSource]: Loads configuration from environment variables using the [envious] crate. Requires theenvfeature. (Enabled by default.) - [
FileSource]: Loads configuration from a file, detectingjsonortomlfiles based on the file extension. Requires thejsonandtomlfeature respectively. (tomlis enabled by default.) - [
TomlSource]: Loads configuration from a TOML string literal. Requires thetomlfeature. (Enabled by default.) - [
JsonSource]: Loads configuration from a JSON string literal. Requires thejsonfeature.
Secrets
Fields annotated with #[confik(secret)] will only be read from secure sources.
This serves as a runtime check that no secrets have been stored in insecure places such as
world-readable files.
If a secret is found in an insecure source, an error will be returned. You can opt into loading secrets on a source-by-source basis.
Foreign Types
This crate provides implementations of [Configuration] for a number of std types and the
following third-party crates. Implementations for third-party crates are feature gated.
with-chrono-chrono0.4with-rust_decimal-1-rust_decimal1with-url-url1with-uuid-uuid1
Macro usage
The derive macro is called Configuration and is used as normal:
Forwarding Attributes To Deserialize
The serde attributes used for customizing a Deserialize derive typically are achieved by
adding #[confik(forward_serde(...)) attributes.
For example:
Defaults
Defaults are specified on a per-field basis.
- Defaults are used if the data cannot be fully read, even if it is partially read.
E.g., even if
datain the below example has one value read in, both will be overwritten by the default.
#
#
- Defaults can be given by any rust expression, and have [
Into::into] run over them. E.g.,
const DEFAULT_VALUE: u8 = 4;
- Alternatively, a default without a given value called [
Default::default]. E.g.,
use ;
let config = builder.try_build.unwrap;
assert_eq!;
Handling Foreign Types
If there's a foreign type used in your config, then you will not be able to implement
[Configuration] for it. Instead any type that implements [Into] can be used.
Macro Limitations
Option Defaulting
Options cannot default to anything other than None. I.e., the below example ignores the provided default.
# use Configuration;
const DEFAULT_DATA: = Some;
let config = builder.try_build.unwrap;
assert_eq!;
This behaviour occurs due to Options needing to have a default value of None, as Optional
configuration shouldn't be required. This defaulting occurs inside the [ConfigurationBuilder]
implementation of [Option] and so happens before the macro can try to default the value.
This is in principle fixable by special casing any value with an Option<...> type, but this
has not been implemented due to the fragility that trying to exact match on the string value of
a type in a macro would bring. E.g., a custom type such as type MyOption = Option<usize> would
then behave differently to using Option<usize> directly.
Custom Deserialize Implementations
If you're using a custom Deserialize implementation, then you cannot use the Configuration
derive macro. Instead, define the necessary config implementation manually like so:
;
Note that the Option<Self> builder type only works for simple types. For more info, see the
docs on [Configuration] and [ConfigurationBuilder].