feat(server): support server-side default expiry time

This commit is contained in:
Orhun Parmaksız 2023-05-14 01:30:35 +03:00
parent 9ea7d5de8a
commit 607f07b6e1
No known key found for this signature in database
GPG key ID: F83424824B3E4B90
4 changed files with 21 additions and 8 deletions

View file

@ -43,4 +43,5 @@ mime_blacklist = [
"application/java-vm", "application/java-vm",
] ]
duplicate_files = true duplicate_files = true
# default_expiry = "1h"
delete_expired_files = { enabled = true, interval = "1h" } delete_expired_files = { enabled = true, interval = "1h" }

View file

@ -62,8 +62,11 @@ pub struct PasteConfig {
/// Media type blacklist. /// Media type blacklist.
#[serde(default)] #[serde(default)]
pub mime_blacklist: Vec<String>, pub mime_blacklist: Vec<String>,
/// Allow duplicate uploads /// Allow duplicate uploads.
pub duplicate_files: Option<bool>, pub duplicate_files: Option<bool>,
/// Default expiry time.
#[serde(default, with = "humantime_serde")]
pub default_expiry: Option<Duration>,
/// Delete expired files. /// Delete expired files.
pub delete_expired_files: Option<CleanupConfig>, pub delete_expired_files: Option<CleanupConfig>,
} }

View file

@ -1,19 +1,18 @@
use crate::util;
use actix_web::http::header::{ use actix_web::http::header::{
ContentDisposition as ActixContentDisposition, DispositionParam, DispositionType, HeaderMap, ContentDisposition as ActixContentDisposition, DispositionParam, DispositionType, HeaderMap,
}; };
use actix_web::{error, Error as ActixError}; use actix_web::{error, Error as ActixError};
use std::time::Duration;
/// Custom HTTP header for expiry dates. /// Custom HTTP header for expiry dates.
pub const EXPIRE: &str = "expire"; pub const EXPIRE: &str = "expire";
/// Parses the expiry date from the [`custom HTTP header`](EXPIRE). /// Parses the expiry date from the [`custom HTTP header`](EXPIRE).
pub fn parse_expiry_date(headers: &HeaderMap) -> Result<Option<u128>, ActixError> { pub fn parse_expiry_date(headers: &HeaderMap, time: Duration) -> Result<Option<u128>, ActixError> {
if let Some(expire_time) = headers.get(EXPIRE).and_then(|v| v.to_str().ok()) { if let Some(expire_time) = headers.get(EXPIRE).and_then(|v| v.to_str().ok()) {
let timestamp = util::get_system_time()?;
let expire_time = let expire_time =
humantime::parse_duration(expire_time).map_err(error::ErrorInternalServerError)?; humantime::parse_duration(expire_time).map_err(error::ErrorInternalServerError)?;
Ok(timestamp.checked_add(expire_time).map(|t| t.as_millis())) Ok(time.checked_add(expire_time).map(|t| t.as_millis()))
} else { } else {
Ok(None) Ok(None)
} }
@ -62,9 +61,9 @@ impl ContentDisposition {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::util;
use actix_web::http::header::{HeaderName, HeaderValue}; use actix_web::http::header::{HeaderName, HeaderValue};
use std::thread; use std::thread;
use std::time::Duration;
#[test] #[test]
fn test_content_disposition() -> Result<(), ActixError> { fn test_content_disposition() -> Result<(), ActixError> {
@ -97,7 +96,8 @@ mod tests {
HeaderName::from_static(EXPIRE), HeaderName::from_static(EXPIRE),
HeaderValue::from_static("5ms"), HeaderValue::from_static("5ms"),
); );
let expiry_time = parse_expiry_date(&headers)?.unwrap_or_default(); let time = util::get_system_time()?;
let expiry_time = parse_expiry_date(&headers, time)?.unwrap_or_default();
assert!(expiry_time > util::get_system_time()?.as_millis()); assert!(expiry_time > util::get_system_time()?.as_millis());
thread::sleep(Duration::from_millis(10)); thread::sleep(Duration::from_millis(10));
assert!(expiry_time < util::get_system_time()?.as_millis()); assert!(expiry_time < util::get_system_time()?.as_millis());

View file

@ -160,7 +160,16 @@ async fn upload(
.as_ref() .as_ref()
.cloned()), .cloned()),
)?; )?;
let expiry_date = header::parse_expiry_date(request.headers())?; let time = util::get_system_time()?;
let mut expiry_date = header::parse_expiry_date(request.headers(), time)?;
if expiry_date.is_none() {
expiry_date = config
.read()
.map_err(|_| error::ErrorInternalServerError("cannot acquire config"))?
.paste
.default_expiry
.and_then(|v| time.checked_add(v).map(|t| t.as_millis()));
}
let mut urls: Vec<String> = Vec::new(); let mut urls: Vec<String> = Vec::new();
while let Some(item) = payload.next().await { while let Some(item) = payload.next().await {
let mut field = item?; let mut field = item?;