Rust

Using environment variables with rust works - at least - two different ways:

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_VARIABLE set when building the code
  • the value of the RUNTIME_VARIABLE set 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_VARIABLE set when building the code
  • the value of the RUNTIME_VARIABLE set 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