Rust
Using environment variables with rust works - at least - two different ways:
- embedding at compile time with macro
std::env env!() - reading at runtime with
std::env::var(key)
The below code uses both methods of accessing environment variables:
use std::env;
fn main() {
println!(
"The value of COMPILE_TIME_VARIABLE is: {}",
env!("COMPILE_TIME_VARIABLE","$COMPILE_TIME_VARIABLE should be set")
);
println!(
"The value of RUNTIME_VARIABLE is: {}",
env::var("RUNTIME_VARIABLE").expect("$RUNTIME_VARIABLE should be set")
);
}
Building with no variables set
Building the code without setting any environment variables will fail because the COMPILE_TIME_VARIABLE is not set:
user $ cargo build --bin env-ingestion-test --release
Compiling env-rocket-example v0.1.0 (/Users/ds/env-rocket-example)
error: $COMPILE_TIME_VARIABLE should be set
--> src/bin/env-ingestion-test.rs:6:9
|
6 | env!("COMPILE_TIME_VARIABLE","$COMPILE_TIME_VARIABLE should be set")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
error: could not compile `env-rocket-example` due to previous error
Building with only COMPILE_TIME_VARIABLE set
When building with set COMPILE_TIME_VARIABLE the code will compile successfully:
user $ COMPILE_TIME_VARIABLE="Ye old compile time content"\
cargo build --bin env-ingestion-test --release
Compiling env-rocket-example v0.1.0 (/Users/ds/env-rocket-example)
Finished release [optimized] target(s) in 0.31s
Executing the binary without any variables set
When executing the binary without any variable set, the program will show the value that COMPILE_TIME_VARIABLE had while building the binary and the execution will fail due to the RUNTIME_VARIABLE missing:
user $ ./target/release/env-ingestion-test
The value of COMPILE_TIME_VARIABLE is: Ye old compile time content
thread 'main' panicked at '$RUNTIME_VARIABLE should be set: NotPresent', src/bin/env-ingestion-test.rs:10:38
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Executing the binary with the RUNTIME_VARIABLE set
When executing the compiled binary with RUNTIME_VARIABLE set, the program will complete and print:
- the value of
COMPILE_TIME_VARIABLEset when building the code - the value of the
RUNTIME_VARIABLEset when executing the program
user $ RUNTIME_VARIABLE="New runtime content"\
./target/release/env-ingestion-test
The value of COMPILE_TIME_VARIABLE is: Ye old compile time content
The value of RUNTIME_VARIABLE is: New runtime content
Executing the binary with the RUNTIME_VARIABLE and COMPILE_TIME_VARIABLE set
When executing the compiled binary with RUNTIME_VARIABLE and a new COMPILE_TIME_VARIABLE set, the program will complete and print:
- the old value of
COMPILE_TIME_VARIABLEset when building the code - the value of the
RUNTIME_VARIABLEset when executing the program
user $ COMPILE_TIME_VARIABLE="New compile time content"\
RUNTIME_VARIABLE="New runtime content"\
./target/release/env-ingestion-test
The value of COMPILE_TIME_VARIABLE is: Ye old compile time content
The value of RUNTIME_VARIABLE is: New runtime content
Rocket
The documentation on rocket config and rocket::fairing was confusing and it took some time to figure it out. Here is a working example of using an environment variable in a rocket function:
#[macro_use]
extern crate rocket;
use rocket::fairing::AdHoc;
use rocket::serde::Deserialize;
use rocket::State;
#[derive(Deserialize)]
#[serde(crate = "rocket::serde")]
struct Config {
my_api_key: String,
}
#[get("/testenv")]
fn testenv(config: &State<Config>) -> &str {
&config.my_api_key
}
#[launch]
fn rocket() -> _ {
rocket::build()
.attach(AdHoc::config::<Config>())
.mount("/", routes![testenv])
}
Run the rocket instance like this
ROCKET_PORT=8080 ROCKET_my_api_key=supersecretkey cargo run
OR like this:
ROCKET_PORT=8080 ROCKET_MY_API_KEY=supersecretkey cargo run
Harvest the result with:
% curl http://127.0.0.1:8080/testenv
supersecretkey