Compare commits

...

2 Commits

Author SHA1 Message Date
neri b9849153f0 fix url decoding in /uploaded endpoint 2022-11-22 21:15:15 +01:00
neri dc2f7ecab0 move multipart error handling into its module 2022-11-22 21:11:35 +01:00
2 changed files with 33 additions and 24 deletions

View File

@ -5,10 +5,14 @@ use futures_util::{StreamExt, TryStreamExt};
use mime::{Mime, APPLICATION_OCTET_STREAM, TEXT_PLAIN}; use mime::{Mime, APPLICATION_OCTET_STREAM, TEXT_PLAIN};
use std::{ use std::{
cmp::{max, min}, cmp::{max, min},
io::ErrorKind,
path::Path, path::Path,
}; };
use time::{Duration, OffsetDateTime}; use time::{Duration, OffsetDateTime};
use tokio::{fs::File, io::AsyncWriteExt}; use tokio::{
fs::{self, File},
io::AsyncWriteExt,
};
const MAX_UPLOAD_DURATION: Duration = Duration::days(31); const MAX_UPLOAD_DURATION: Duration = Duration::days(31);
const DEFAULT_UPLOAD_DURATION: Duration = Duration::minutes(30); const DEFAULT_UPLOAD_DURATION: Duration = Duration::minutes(30);
@ -21,6 +25,25 @@ pub(crate) struct UploadConfig {
} }
pub(crate) async fn parse_multipart( pub(crate) async fn parse_multipart(
payload: Multipart,
file_path: &Path,
config: &config::Config,
) -> Result<UploadConfig, error::Error> {
match parse_multipart_inner(payload, file_path, config).await {
Ok(data) => Ok(data),
Err(err) => {
match fs::remove_file(file_path).await {
Err(err) if err.kind() != ErrorKind::NotFound => {
log::error!("could not remove file {:?}", err);
}
_ => {}
}
Err(err)
}
}
}
pub(crate) async fn parse_multipart_inner(
mut payload: Multipart, mut payload: Multipart,
file_path: &Path, file_path: &Path,
config: &config::Config, config: &config::Config,

View File

@ -41,28 +41,12 @@ pub async fn upload(
error::ErrorInternalServerError("could not create file") error::ErrorInternalServerError("could not create file")
})?; })?;
let parsed_multipart = multipart::parse_multipart(payload, &file_name, &config).await;
let UploadConfig { let UploadConfig {
original_name, original_name,
content_type, content_type,
valid_till, valid_till,
delete_on_download, delete_on_download,
} = match parsed_multipart { } = multipart::parse_multipart(payload, &file_name, &config).await?;
Ok(data) => data,
Err(err) => {
match fs::remove_file(file_name).await {
Ok(()) => {}
Err(err) if err.kind() == ErrorKind::NotFound => {}
Err(err) => {
log::error!("could not remove file {:?}", err);
return Err(error::ErrorInternalServerError(
"could not parse multipart; could not remove file",
));
}
}
return Err(err);
}
};
let file_name = original_name.clone().unwrap_or_else(|| { let file_name = original_name.clone().unwrap_or_else(|| {
format!( format!(
@ -156,15 +140,17 @@ fn get_file_url(req: &HttpRequest, id: &str, name: Option<&str>) -> String {
} }
} }
pub async fn uploaded(req: HttpRequest) -> Result<HttpResponse, Error> { pub async fn uploaded(
let id = req.match_info().query("id"); req: HttpRequest,
let name = req.match_info().get("name"); path: web::Path<(String, Option<String>)>,
) -> Result<HttpResponse, Error> {
let (id, name) = path.into_inner();
let upload_html = if name.is_some() { let upload_html = if name.is_some() {
UPLOAD_SHORT_HTML UPLOAD_SHORT_HTML
.replace("{link}", &get_file_url(&req, id, name)) .replace("{link}", &get_file_url(&req, &id, name.as_deref()))
.replace("{shortlink}", &get_file_url(&req, id, None)) .replace("{shortlink}", &get_file_url(&req, &id, None))
} else { } else {
UPLOAD_HTML.replace("{link}", &get_file_url(&req, id, name)) UPLOAD_HTML.replace("{link}", &get_file_url(&req, &id, name.as_deref()))
}; };
Ok(HttpResponse::Ok() Ok(HttpResponse::Ok()
.content_type("text/html") .content_type("text/html")