summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2022-09-12 13:30:19 +0000
committerSanto Cariotti <santo@dcariotti.me>2022-09-12 13:30:19 +0000
commitaf3f5430a0b0f1834228b28fd89848959512e718 (patch)
tree27e843c147b92bf09893012f323ddaf54f5eb0a5
parent385102a5763f667d53a9d8ed2052ccb8c791bc91 (diff)
Use configuration for environment variables
-rw-r--r--Cargo.lock166
-rw-r--r--Cargo.toml3
-rw-r--r--src/config.rs38
-rw-r--r--src/db.rs3
-rw-r--r--src/files.rs8
-rw-r--r--src/logger.rs3
-rw-r--r--src/main.rs19
-rw-r--r--src/models/auth.rs2
-rw-r--r--src/models/model.rs6
-rw-r--r--src/models/user.rs6
-rw-r--r--src/routes/model.rs3
11 files changed, 216 insertions, 41 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c98ff4b..0900b7a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -56,6 +56,12 @@ dependencies = [
]
[[package]]
+name = "arrayvec"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
+
+[[package]]
name = "async-compression"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -85,7 +91,7 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e"
dependencies = [
- "num-traits",
+ "num-traits 0.2.15",
]
[[package]]
@@ -116,7 +122,7 @@ dependencies = [
"multer",
"percent-encoding",
"pin-project-lite",
- "serde",
+ "serde 1.0.144",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
@@ -231,14 +237,30 @@ dependencies = [
"iana-time-zone",
"js-sys",
"num-integer",
- "num-traits",
- "serde",
+ "num-traits 0.2.15",
+ "serde 1.0.144",
"time 0.1.44",
"wasm-bindgen",
"winapi",
]
[[package]]
+name = "config"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3"
+dependencies = [
+ "lazy_static",
+ "nom 5.1.2",
+ "rust-ini",
+ "serde 1.0.144",
+ "serde-hjson",
+ "serde_json",
+ "toml",
+ "yaml-rust",
+]
+
+[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -339,6 +361,12 @@ dependencies = [
]
[[package]]
+name = "dotenv"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
+
+[[package]]
name = "dotenvy"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -687,7 +715,7 @@ dependencies = [
"base64",
"pem",
"ring",
- "serde",
+ "serde 1.0.144",
"serde_json",
"simple_asn1",
]
@@ -699,12 +727,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
+name = "lexical-core"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
+dependencies = [
+ "arrayvec",
+ "bitflags",
+ "cfg-if",
+ "ryu",
+ "static_assertions",
+]
+
+[[package]]
name = "libc"
version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
+name = "linked-hash-map"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
+dependencies = [
+ "serde 0.8.23",
+ "serde_test",
+]
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
name = "lock_api"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -803,6 +860,17 @@ dependencies = [
[[package]]
name = "nom"
+version = "5.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
+dependencies = [
+ "lexical-core",
+ "memchr",
+ "version_check",
+]
+
+[[package]]
+name = "nom"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
@@ -819,7 +887,7 @@ checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
dependencies = [
"autocfg",
"num-integer",
- "num-traits",
+ "num-traits 0.2.15",
]
[[package]]
@@ -829,7 +897,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
dependencies = [
"autocfg",
- "num-traits",
+ "num-traits 0.2.15",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.1.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
+dependencies = [
+ "num-traits 0.2.15",
]
[[package]]
@@ -1113,6 +1190,12 @@ dependencies = [
]
[[package]]
+name = "rust-ini"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
+
+[[package]]
name = "rustls"
version = "0.20.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1157,6 +1240,12 @@ dependencies = [
[[package]]
name = "serde"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
+
+[[package]]
+name = "serde"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
@@ -1165,6 +1254,19 @@ dependencies = [
]
[[package]]
+name = "serde-hjson"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a3a4e0ea8a88553209f6cc6cfe8724ecad22e1acf372793c27d995290fe74f8"
+dependencies = [
+ "lazy_static",
+ "linked-hash-map 0.3.0",
+ "num-traits 0.1.43",
+ "regex",
+ "serde 0.8.23",
+]
+
+[[package]]
name = "serde_derive"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1183,7 +1285,16 @@ checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
dependencies = [
"itoa",
"ryu",
- "serde",
+ "serde 1.0.144",
+]
+
+[[package]]
+name = "serde_test"
+version = "0.8.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5"
+dependencies = [
+ "serde 0.8.23",
]
[[package]]
@@ -1195,7 +1306,7 @@ dependencies = [
"form_urlencoded",
"itoa",
"ryu",
- "serde",
+ "serde 1.0.144",
]
[[package]]
@@ -1268,7 +1379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
dependencies = [
"num-bigint",
- "num-traits",
+ "num-traits 0.2.15",
"thiserror",
"time 0.3.13",
]
@@ -1308,7 +1419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4"
dependencies = [
"itertools",
- "nom",
+ "nom 7.1.1",
"unicode_categories",
]
@@ -1361,7 +1472,7 @@ dependencies = [
"rand",
"rustls",
"rustls-pemfile",
- "serde",
+ "serde 1.0.144",
"serde_json",
"sha-1",
"sha2 0.10.2",
@@ -1408,6 +1519,12 @@ dependencies = [
]
[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
name = "stringprep"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1581,6 +1698,15 @@ dependencies = [
]
[[package]]
+name = "toml"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+dependencies = [
+ "serde 1.0.144",
+]
+
+[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1766,7 +1892,7 @@ dependencies = [
"idna",
"lazy_static",
"regex",
- "serde",
+ "serde 1.0.144",
"serde_derive",
"serde_json",
"url",
@@ -1812,11 +1938,14 @@ dependencies = [
"async-trait",
"axum",
"chrono",
+ "config",
+ "dotenv",
"http-body",
"jsonwebtoken",
+ "lazy_static",
"once_cell",
"rand",
- "serde",
+ "serde 1.0.144",
"serde_json",
"sha256",
"sqlx",
@@ -2012,3 +2141,12 @@ name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+
+[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map 0.5.6",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 736ec20..0cf6a32 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,3 +21,6 @@ sha256 = "1.0.3"
validator = { version = "0.16.0", features = ["derive"] }
chrono = { version = "0.4", features = ["serde"] }
rand = "0.8.5"
+dotenv = "0.15.0"
+config = "0.10"
+lazy_static = "1.4.0"
diff --git a/src/config.rs b/src/config.rs
index 02ae63d..7e67214 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,6 +1,34 @@
-// TODO: Everything here must be a std::env
+pub use config::ConfigError;
+use lazy_static::lazy_static;
+use serde::Deserialize;
-pub static PAGE_LIMIT: i64 = 20;
-pub const MAX_UPLOAD_FILE_SIZE: u64 = 1024 * 1024; // 1 MB
-pub const SAVE_FILE_BASE_PATH: &str = "./uploads";
-pub const UPLOADS_ENDPOINT: &str = "/uploads";
+// pub static PAGE_LIMIT: i64 = std::env::var("PAGE_LIMIT")
+// .unwrap_or_else(|_| "20".to_string())
+// .parse::<i64>()
+// .unwrap();
+// pub const MAX_UPLOAD_FILE_SIZE: u64 = 1024 * 1024; // 1 MB
+// pub const SAVE_FILE_BASE_PATH: &str = &std::env::var("SAVE_FILE_BASE_PATH").unwrap();
+// pub const UPLOADS_ENDPOINT: &str = &std::env::var("UPLOADS_ENDPOINT").unwrap();
+
+#[derive(Deserialize)]
+pub struct Configuration {
+ pub page_limit: i64,
+ pub save_file_base_path: String,
+ pub uploads_endpoint: String,
+ pub rust_log: String,
+ pub database_url: String,
+ pub jwt_secret: String,
+ pub allowed_host: String,
+}
+
+impl Configuration {
+ pub fn new() -> Result<Self, ConfigError> {
+ let mut cfg = config::Config::new();
+ cfg.merge(config::Environment::default())?;
+ cfg.try_into()
+ }
+}
+
+lazy_static! {
+ pub static ref CONFIG: Configuration = Configuration::new().expect("Config can be loaded");
+}
diff --git a/src/db.rs b/src/db.rs
index 43c3bd9..f157187 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -9,8 +9,7 @@ static mut CONNECTION: Option<PgPool> = None;
/// Setup database connection. Get variable `DATABASE_URL` from the environment. Sqlx crate already
/// defines an error for environments without DATABASE_URL.
pub async fn setup() -> Result<(), AppError> {
- let database_url =
- std::env::var("DATABASE_URL").expect("Define `DATABASE_URL` environment variable.");
+ let database_url = &crate::config::CONFIG.database_url;
unsafe {
CONNECTION = Some(PgPool::connect(&database_url).await?);
diff --git a/src/files.rs b/src/files.rs
index 616a75d..73e0497 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -1,4 +1,4 @@
-use crate::config::{SAVE_FILE_BASE_PATH, UPLOADS_ENDPOINT};
+use crate::config::CONFIG;
use crate::errors::AppError;
use axum::{
extract::{Multipart, Path},
@@ -30,8 +30,8 @@ pub async fn upload(
{
let rnd = (random::<f32>() * 1000000000 as f32) as i32;
- let save_filename = format!("{}/{}.{}", SAVE_FILE_BASE_PATH, rnd, ext_name);
- uploaded_file = format!("{}/{}.{}", UPLOADS_ENDPOINT, rnd, ext_name);
+ let save_filename = format!("{}/{}.{}", CONFIG.save_file_base_path, rnd, ext_name);
+ uploaded_file = format!("{}/{}.{}", CONFIG.uploads_endpoint, rnd, ext_name);
let data = file.bytes().await.unwrap();
@@ -70,6 +70,6 @@ pub async fn show_uploads(Path(id): Path<String>) -> (HeaderMap, Vec<u8>) {
HeaderValue::from_str(&content_type).unwrap(),
);
}
- let file_name = format!("{}/{}", SAVE_FILE_BASE_PATH, id);
+ let file_name = format!("{}/{}", CONFIG.save_file_base_path, id);
(headers, read(&file_name).unwrap())
}
diff --git a/src/logger.rs b/src/logger.rs
index 151803f..3f3ff0f 100644
--- a/src/logger.rs
+++ b/src/logger.rs
@@ -4,8 +4,7 @@ use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
pub fn setup() {
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::new(
- std::env::var("RUST_LOG")
- .unwrap_or_else(|_| "verden=debug,tower_http=debug".into()),
+ crate::config::CONFIG.rust_log.clone(),
))
.with(tracing_subscriber::fmt::layer())
.init();
diff --git a/src/main.rs b/src/main.rs
index c20f667..39c6738 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,13 +7,14 @@ mod models;
mod pagination;
mod routes;
-use crate::config::UPLOADS_ENDPOINT;
+use crate::config::CONFIG;
use axum::{
handler::Handler,
http::{header, Request},
routing::get,
Router,
};
+use std::net::{SocketAddr, ToSocketAddrs};
use std::time::Duration;
use tower_http::sensitive_headers::SetSensitiveHeadersLayer;
use tower_http::{classify::ServerErrorsFailureClass, trace::TraceLayer};
@@ -24,11 +25,19 @@ use tracing::Span;
async fn main() {
let app = create_app().await;
- // By default the server is bind at "127.0.0.1:3000"
- let addr = std::env::var("ALLOWED_HOST").unwrap_or_else(|_| "127.0.0.1:3000".to_string());
+ let host = &CONFIG.allowed_host;
+ let addr = match host.parse::<SocketAddr>() {
+ Ok(addr) => addr,
+ Err(_) => match host.to_socket_addrs() {
+ Ok(mut addr) => addr.next().unwrap(),
+ Err(e) => {
+ panic!("{}", e);
+ }
+ },
+ };
tracing::info!("Listening on {}", addr);
- axum::Server::bind(&addr.parse().unwrap())
+ axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
@@ -46,7 +55,7 @@ async fn create_app() -> Router {
Router::new()
.route(
- &format!("{}/:id", UPLOADS_ENDPOINT),
+ &format!("{}/:id", CONFIG.uploads_endpoint),
get(crate::files::show_uploads),
)
// Map all routes to `/v1/*` namespace
diff --git a/src/models/auth.rs b/src/models/auth.rs
index 36a0175..8a70244 100644
--- a/src/models/auth.rs
+++ b/src/models/auth.rs
@@ -40,7 +40,7 @@ pub struct LoginCredentials {
}
static KEYS: Lazy<Keys> = Lazy::new(|| {
- let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");
+ let secret = &crate::config::CONFIG.jwt_secret;
Keys::new(secret.as_bytes())
});
diff --git a/src/models/model.rs b/src/models/model.rs
index 5b47f5c..f686192 100644
--- a/src/models/model.rs
+++ b/src/models/model.rs
@@ -1,4 +1,4 @@
-use crate::config::PAGE_LIMIT;
+use crate::config::CONFIG;
use crate::db::get_client;
use crate::errors::AppError;
@@ -163,8 +163,8 @@ impl Model {
GROUP BY models.id, users.id
LIMIT $1 OFFSET $2
"#,
- PAGE_LIMIT,
- PAGE_LIMIT * page
+ CONFIG.page_limit,
+ CONFIG.page_limit * page
)
.fetch_all(pool)
.await?;
diff --git a/src/models/user.rs b/src/models/user.rs
index 22bd130..55abc97 100644
--- a/src/models/user.rs
+++ b/src/models/user.rs
@@ -1,4 +1,4 @@
-use crate::config::PAGE_LIMIT;
+use crate::config::CONFIG;
use crate::db::get_client;
use crate::errors::AppError;
@@ -121,8 +121,8 @@ impl User {
r#"SELECT id, email, username, is_staff FROM users
LIMIT $1 OFFSET $2
"#,
- PAGE_LIMIT,
- PAGE_LIMIT * page
+ CONFIG.page_limit,
+ CONFIG.page_limit * page
)
.fetch_all(pool)
.await?;
diff --git a/src/routes/model.rs b/src/routes/model.rs
index d1ac197..34e896d 100644
--- a/src/routes/model.rs
+++ b/src/routes/model.rs
@@ -1,4 +1,3 @@
-use crate::config::MAX_UPLOAD_FILE_SIZE;
use crate::errors::AppError;
use crate::files::upload;
use crate::models::{
@@ -69,7 +68,7 @@ async fn get_model(Path(model_id): Path<i32>) -> Result<Json<ModelUser>, AppErro
async fn upload_model_file(
claims: Claims,
Path(model_id): Path<i32>,
- ContentLengthLimit(multipart): ContentLengthLimit<Multipart, { MAX_UPLOAD_FILE_SIZE }>,
+ ContentLengthLimit(multipart): ContentLengthLimit<Multipart, { 1024 * 1024 }>,
) -> Result<Json<ModelUpload>, AppError> {
let model = match Model::find_by_id(model_id).await {
Ok(model) => model,