commit 1cb08214cf3a82ad3acb8fec023e7fb2a404f6bd from: msi date: Fri Nov 14 13:31:30 2025 UTC Add config files for project commit - 7583df586ed40b9202e7585fa5fd795ab2e3315b commit + 1cb08214cf3a82ad3acb8fec023e7fb2a404f6bd blob - 21363f3dede514363d423a5be1011fbf372824a2 blob + 556952c4198c548f93bd7667434b18fda7be9c84 --- web/README.md +++ web/README.md @@ -7,7 +7,7 @@ * [ ] Middleware Ip * [x] Request Id Header * [x] Static files -* [ ] Config +* [x] Config * [x] Tracing * [x] Messages (like flask) * [x] Sessions blob - 2f7896d1d1365eafb0da03d9fe456fac81408487 blob + ce8c5ca8cfa7766e7cf52af12119b6ed76a18e38 --- web/template/.gitignore +++ web/template/.gitignore @@ -1 +1,2 @@ target/ +config/production.toml blob - bfb4153d79077a8e152f7d143adf4d4002ed7a39 blob + 207eafbd53830c5193ccc5ea5502abca1654ccd8 --- web/template/Cargo.toml +++ web/template/Cargo.toml @@ -9,8 +9,9 @@ edition = "2024" [dependencies] anyhow = "=1.0.100" axum = { version = "=0.8.6", features = ["macros"] } -axum-messages = "0.8.0" -axum_csrf = { version = "0.11.0", features = ["layer"] } +axum-messages = "=0.8.0" +axum_csrf = { version = "=0.11.0", features = ["layer"] } +config = { version = "=0.15.19", default-features = false, features = ["toml"] } metrics = { version = "=0.24.2", default-features = false } metrics-exporter-prometheus = { version = "=0.17.2", default-features = false } minijinja = "=2.12.0" @@ -21,4 +22,3 @@ tower-http = { version = "=0.6.6", features = ["timeou tower-sessions = "=0.14.0" tracing = "=0.1.41" tracing-subscriber = { version = "=0.3.20", features = ["env-filter"] } - blob - /dev/null blob + dbb2f3020990f9cb884e02408ce2471f3e481bbb (mode 644) --- /dev/null +++ web/template/config/default.toml @@ -0,0 +1,17 @@ +[database] +url = "postgres://postgres@localhost" + +[sparkpost] +key = "sparkpost-dev-key" +token = "sparkpost-dev-token" +url = "https://api.sparkpost.com" +version = 1 + +[twitter] +consumer_token = "twitter-dev-consumer-key" +consumer_secret = "twitter-dev-consumer-secret" + +[braintree] +merchant_id = "braintree-merchant-id" +public_key = "braintree-dev-public-key" +private_key = "braintree-dev-private-key" blob - /dev/null blob + f07dcc2b400cf54b26e71ab75acb270f891f79c5 (mode 644) --- /dev/null +++ web/template/config/development.toml @@ -0,0 +1,4 @@ +debug = true + +[database] +echo = true blob - 315a365408046be29f9ce0bf5eac5637a77bb219 blob + f9c63402ebb48560a26b3ab2a1b4286a335395f8 --- web/template/src/main.rs +++ web/template/src/main.rs @@ -24,11 +24,14 @@ mod helpers; mod metric; mod router; mod state; +mod settings; #[tokio::main] async fn main() -> anyhow::Result<()> { helpers::init_tracing(); + let _settings = settings::Settings::new(); + let (_main_server, _metrics_server) = tokio::join!(start_main_server(), metric::start_metrics_server()); Ok(()) blob - /dev/null blob + 897cbf4288d8cc11fc05ceb140d88314764f74bd (mode 644) --- /dev/null +++ web/template/src/settings.rs @@ -0,0 +1,80 @@ +use std::env; + +use tracing::{debug, info}; + +use config::{Config, ConfigError, Environment, File}; +use serde::Deserialize; + +#[derive(Debug, Deserialize)] +#[allow(unused)] +struct Database { + url: String, +} + +#[derive(Debug, Deserialize)] +#[allow(unused)] +struct Sparkpost { + key: String, + token: String, + url: String, + version: u8, +} + +#[derive(Debug, Deserialize)] +#[allow(unused)] +struct Twitter { + consumer_token: String, + consumer_secret: String, +} + +#[derive(Debug, Deserialize)] +#[allow(unused)] +struct Braintree { + merchant_id: String, + public_key: String, + private_key: String, +} + +#[derive(Debug, Deserialize)] +#[allow(unused)] +pub(crate) struct Settings { + debug: bool, + database: Database, + sparkpost: Sparkpost, + twitter: Twitter, + braintree: Braintree, +} + +impl Settings { + pub(crate) fn new() -> Result { + info!("loading settings"); + let run_mode = env::var("RUN_MODE").unwrap_or_else(|_| "development".into()); + + let s = Config::builder() + // Start off by merging in the "default" configuration file + .add_source(File::with_name("config/default")) + // Add in the current environment file + // Default to 'development' env + // Note that this file is _optional_ + .add_source( + File::with_name(&format!("config/{run_mode}")) + .required(false), + ) + // Add in a local configuration file + // This file shouldn't be checked in to git + .add_source(File::with_name("config/local").required(false)) + // Add in settings from the environment (with a prefix of APP) + // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key + .add_source(Environment::with_prefix("app")) + // You may also programmatically change settings + .set_override("database.url", "postgres://")? + .build()?; + + // Now that we're done, let's access our configuration + debug!("debug: {:?}", s.get_bool("debug")); + debug!("database: {:?}", s.get::("database.url")); + + // You can deserialize (and thus freeze) the entire configuration as + s.try_deserialize() + } +}