#[derive(ServiceConf)]
{
// Attributes available to this derive:
#[conf]
}
Expand description
ServiceConf derive macro
Automatically implements the from_env() method on structs for loading configuration
from environment variables.
§Supported Attributes
§Struct-level Attributes
§#[conf(prefix = "PREFIX_")]
Add a prefix to all environment variable names in the struct.
use serviceconf::ServiceConf;
#[derive(ServiceConf)]
#[conf(prefix = "MYAPP_")]
struct Config {
pub api_key: String, // Reads from MYAPP_API_KEY
pub port: u16, // Reads from MYAPP_PORT
}§Field-level Attributes
§#[conf(name = "CUSTOM_NAME")]
Override the default environment variable name for a specific field.
use serviceconf::ServiceConf;
#[derive(ServiceConf)]
struct Config {
#[conf(name = "DATABASE_URL")]
pub db_connection: String, // Reads from DATABASE_URL
}§#[conf(default)]
Use Default::default() when the environment variable is not set.
use serviceconf::ServiceConf;
#[derive(ServiceConf)]
struct Config {
#[conf(default)]
pub port: u16, // Uses 0 if PORT not set
}§#[conf(default = value)]
Use an explicit default value when the environment variable is not set.
use serviceconf::ServiceConf;
#[derive(ServiceConf)]
struct Config {
#[conf(default = 8080)]
pub port: u16, // Uses 8080 if PORT not set
}§#[conf(from_file)]
Support loading from file-based secrets (Kubernetes/Docker Secrets).
Reads from both VAR_NAME and VAR_NAME_FILE environment variables.
use serviceconf::ServiceConf;
#[derive(ServiceConf)]
struct Config {
#[conf(from_file)]
pub api_key: String, // Reads from API_KEY or API_KEY_FILE
}§#[conf(deserializer = "function")]
Use a custom deserializer function for complex types.
The function signature must be: fn(&str) -> Result<T, impl std::fmt::Display>
Can be combined with default to provide a fallback value, or used with Option<T>
to make the field optional:
use serviceconf::ServiceConf;
use std::time::Duration;
fn parse_duration_secs(s: &str) -> Result<Duration, String> {
s.parse::<u64>()
.map(Duration::from_secs)
.map_err(|e| format!("Failed to parse: {}", e))
}
#[derive(ServiceConf)]
struct Config {
// Required field with custom deserializer
#[conf(deserializer = "parse_duration_secs")]
pub timeout: Duration,
// With default value (uses default when env var is not set)
#[conf(deserializer = "parse_duration_secs", default = Duration::from_secs(60))]
pub retry_interval: Duration,
// With Option<T> (None when env var is not set)
#[conf(deserializer = "parse_duration_secs")]
pub max_timeout: Option<Duration>,
}§Examples
Basic usage:
use serviceconf::ServiceConf;
#[derive(ServiceConf)]
struct Config {
pub api_key: String,
#[conf(default = 8080)]
pub port: u16,
}
fn main() -> anyhow::Result<()> {
let config = Config::from_env()?;
Ok(())
}With prefix and file-based secrets:
use serviceconf::ServiceConf;
#[derive(ServiceConf)]
#[conf(prefix = "APP_")]
struct Config {
#[conf(from_file)]
pub database_password: String, // Reads from APP_DATABASE_PASSWORD or APP_DATABASE_PASSWORD_FILE
#[conf(default = 3000)]
pub port: u16, // Reads from APP_PORT, defaults to 3000
}With custom deserializer and default:
use serviceconf::ServiceConf;
use std::time::Duration;
fn parse_duration_secs(s: &str) -> Result<Duration, String> {
s.parse::<u64>()
.map(Duration::from_secs)
.map_err(|e| e.to_string())
}
fn parse_comma_list(s: &str) -> Result<Vec<String>, String> {
Ok(s.split(',').map(|s| s.trim().to_string()).collect())
}
#[derive(ServiceConf)]
struct Config {
// Custom deserializer with explicit default value
#[conf(deserializer = "parse_duration_secs", default = Duration::from_secs(30))]
pub timeout: Duration,
// Custom deserializer with Default::default()
#[conf(deserializer = "parse_comma_list", default)]
pub allowed_hosts: Vec<String>,
}
// Uses default values when environment variables are not set
std::env::remove_var("TIMEOUT");
std::env::remove_var("ALLOWED_HOSTS");
let config = Config::from_env().unwrap();
assert_eq!(config.timeout, Duration::from_secs(30));
assert_eq!(config.allowed_hosts, Vec::<String>::new());
// Override with environment variables
std::env::set_var("TIMEOUT", "60");
std::env::set_var("ALLOWED_HOSTS", "localhost, example.com");
let config = Config::from_env().unwrap();
assert_eq!(config.timeout, Duration::from_secs(60));
assert_eq!(config.allowed_hosts, vec!["localhost", "example.com"]);For complete documentation and more examples, see the serviceconf crate.