Mini Post: Parsing Environment Variables Safely in Rust
bloom
⋄ posted almost 2 years ago ⋄ last updated almost 2 years ago ⋄
2 min read
Almost every app I write nowadays uses an environment file, and therefore I always have to read things from the environment and parse them into different forms. Doing this safely with defaults in Rust was a bit tricky for me at first, but I’ve landed on a solution I like.
Optional Numbers#
The reason I was looking for code like this was to try and get a port for a database from the environment with a reasonable fallback. Here’s what I landed on:
use std::env;use dotenv::dotenv;
fn main() { dotenv().ok(); let count = env::var("COUNT") // convert to Option<String> .ok() // convert to Option<u64> via parse .and_then(|value| value.parse::<u64>().ok()) // Use 5 as a default if either the value was not found or it could // not be converted. .unwrap_or(5)
println!("{}", count * 5);}
Default Strings#
Of course, you can always just get a required value like this:
std::env;use dotenv::dotenv;
fn main() { dotenv().ok(); let test = env::var("TEST") .unwrap_or(String::from("Test"));
println!("{}", test);}
Required Environment Variables#
And of course, you can make them required by just unwrap
ing them, but that
will crash your program:
std::env;use dotenv::dotenv;
fn main() { dotenv().ok(); let test = env::var("TEST").unwrap();
println!("{}", test);}
thread 'main' panicked at src\main.rs:6:35:called `Result::unwrap()` on an `Err` value: NotPresent
You can instead print a helpful message:
std::env;use dotenv::dotenv;
fn main() { dotenv().ok(); let test = env::var("TEST");
match test { Ok(test) => { println!("{}", test) } Err(_) => { eprintln!("Missing required environment variable 'TEST'"); return; } }}
Missing required environment variable 'TEST'