使用ライブラリ
| ライブラリ | 説明 |
|---|---|
| envsubst | 文字列テンプレートにおける変数の置換に使用 |
| env_logger | log crateによって公開されるロギングファサードで使用するために、環境変数によって設定できるシンプルなロガー |
| log | ログ出力に使用(ログの設定は割愛) |
| once_cell | 「一度しか初期化できない」型を提供 正規表現のパフォーマンス改善に使用 |
| regex | 正規表現 |
| serde | Rustデータ構造を効率的かつ汎用的にシリアライズおよびデシリアライズするためのフレームワーク |
| confy | 環境変数、設定ファイル、コマンドライン引数など、複数の設定ソースを統合して管理できるクレート |
[package]
name = "web"
version = "0.1.0"
edition = "2021"
[dependencies]
envsubst = "0.2.1"
env_logger = "0.11.3"
log = "0.4.21"
once_cell = "1.19.0"
regex = "1.10.5"
serde = { version = "1.0", features = ["derive"] }
[dependencies.confy]
version = "0.6.1"
features = ["yaml_conf"]
default-features = false
設定ファイル
- 環境変数を埋め込みたい部分は
${環境変数名}で記述
config.yml
cors:
allowed_origin: ${ALLOWED_ORIGIN}
実装
環境変数を置換するようのコード
env.rs
use envsubst;
use log::error;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Deserializer};
use std::env;
use std::process;
/// ${val}を環境変数の値に置換
pub fn deserialize_with_env<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: Deserializer<'de>,
{
let s: String = Deserialize::deserialize(deserializer)?;
Ok(substitute_env_variables(&s))
}
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"\$\{(\w+)\}").unwrap());
fn substitute_env_variables(input: &str) -> String {
if envsubst::is_templated(input) {
let mut context = std::collections::HashMap::new();
for (_, [cap]) in RE.captures_iter(input).map(|c| c.extract()) {
match env::var(cap) {
Ok(val) => context.insert(cap.to_string(), val),
Err(e) => {
error!("{}", e);
process::exit(1);
}
};
}
envsubst::substitute(input, &context).unwrap()
} else {
input.to_string()
}
}
main処理
-
#[serde(deserialize_with = "deserialize_with_env")]を環境変数を設定する可能性がある箇所に付与
main.rs
use common::config::env::deserialize_with_env;
use confy::{self, ConfyError};
use log::{info, error};
use serde::{Deserialize, Serialize};
use std::process;
use env_logger::Env;
mod env;
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct CorsConfig {
#[serde(deserialize_with = "deserialize_with_env")]
pub allowed_origin: String,
}
#[derive(Default, Debug, Serialize, Deserialize)]
pub struct Config {
pub cors: CorsConfig,
}
/// YAMLからコンフィグの値を取得
pub fn get_config() -> Config {
let cfg: Result<Config, ConfyError> = confy::load_path("config.yml");
match cfg {
Ok(cfg) => cfg,
Err(e) => {
error!("{}", e);
process::exit(1);
}
}
}
fn main() {
env_logger::init_from_env(Env::default().default_filter_or("info"));
let config = env::get_config();
info!("{:?}", config);
}