diff --git a/Cargo.lock b/Cargo.lock index 2b5e8fd..1bd44ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,6 +76,12 @@ dependencies = [ "libc", ] +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "async-trait" version = "0.1.74" @@ -243,6 +249,7 @@ dependencies = [ "bytes", "chacha20", "dotenvy", + "duration-str", "env_logger", "futures-util", "hex", @@ -529,6 +536,20 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "duration-str" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e172e85f305d6a442b250bf40667ffcb91a24f52c9a1ca59e2fa991ac9b7790" +dependencies = [ + "chrono", + "nom", + "rust_decimal", + "serde", + "thiserror", + "time", +] + [[package]] name = "dyn-clone" version = "1.0.14" @@ -1154,6 +1175,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1192,6 +1219,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-bigint" version = "0.4.4" @@ -1728,6 +1765,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rust_decimal" +version = "1.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c4216490d5a413bc6d10fa4742bd7d4955941d062c0ef873141d6b0e7b30fd" +dependencies = [ + "arrayvec", + "num-traits", +] + [[package]] name = "rustc-demangle" version = "0.1.23" diff --git a/Cargo.toml b/Cargo.toml index f26cc6c..fa02fc0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ futures-util = "0.3" axum = {version="0.6", features=["macros", "headers", "multipart"]} serde = "1.0" toml = "0.8" +duration-str = "0.7.0" render = { git="https://github.com/render-rs/render.rs" } thiserror = "1.0" rand = "0.8" diff --git a/src/main.rs b/src/main.rs index c50653c..6de1def 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,10 @@ #![deny(clippy::unwrap_used)] +use duration_str::{deserialize_option_duration, parse_std}; use std::{ borrow::Borrow, env, str::FromStr, - time::{SystemTime, UNIX_EPOCH}, + time::{Duration, SystemTime, UNIX_EPOCH}, }; use axum::{ @@ -196,7 +197,8 @@ async fn get_index( #[derive(Deserialize)] pub struct PostQuery { - ttl: Option, + #[serde(deserialize_with = "deserialize_option_duration")] + ttl: Option, } async fn post_item( @@ -226,7 +228,7 @@ async fn post_item( let mut etag_hasher = Sha3_256::new(); let mut size: u64 = 0; - let mut ttl = params.ttl.unwrap_or(24 * 3600); + let mut ttl = params.ttl.unwrap_or(Duration::from_secs(24 * 3600)); match data { MultipartOrStream::Stream(mut stream) => { @@ -267,7 +269,7 @@ async fn post_item( } if field.name().unwrap_or_default() == "ttl" { if let Some(mp_ttl) = - field.text().await.ok().and_then(|x| x.parse::().ok()) + field.text().await.ok().and_then(|x| parse_std(x).ok()) { ttl = mp_ttl; } @@ -277,16 +279,17 @@ async fn post_item( } writer.flush().await?; - let now = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(); - let expires_at = match u64::MAX - ttl > now { - true => now + ttl, - false => u64::MAX, - }; + if let Some(expires_at) = SystemTime::now() + .duration_since(UNIX_EPOCH)? + .checked_add(ttl) + .map(|x| x.as_secs()) + { + metadata.expires_at = expires_at; + } metadata.etag = Some(hex::encode(etag_hasher.finalize())); metadata.size = Some(size); - metadata.expires_at = expires_at; metadata.to_file(&metadata_path).await?; app_state