main
Zynh0722 2023-08-02 01:39:50 -07:00
parent 6d939efbbf
commit 290041e367
3 changed files with 36 additions and 35 deletions

View File

@ -6,7 +6,7 @@ use axum::{
http::{Request, Response, StatusCode}, http::{Request, Response, StatusCode},
middleware::{self, Next}, middleware::{self, Next},
response::{Html, IntoResponse, Redirect}, response::{Html, IntoResponse, Redirect},
routing::{delete, get, post}, routing::{get, post},
Json, Router, TypedHeader, Json, Router, TypedHeader,
}; };
@ -91,8 +91,7 @@ async fn main() -> io::Result<()> {
.route("/records", get(records)) .route("/records", get(records))
.route("/records/links", get(records_links)) .route("/records/links", get(records_links))
.route("/download/:id", get(download)) .route("/download/:id", get(download))
.route("/link/:id", get(link)) .route("/link/:id", get(link).delete(link_delete))
.route("/link/:id", delete(link_delete))
.route("/link/:id/remaining", get(remaining)) .route("/link/:id/remaining", get(remaining))
.layer(DefaultBodyLimit::disable()) .layer(DefaultBodyLimit::disable())
.layer(RequestBodyLimitLayer::new( .layer(RequestBodyLimitLayer::new(
@ -178,7 +177,10 @@ async fn link(
{ {
let mut records = state.records.lock().await; let mut records = state.records.lock().await;
if let Some(record) = records.get_mut(&id) { if let Some(record) = records
.get_mut(&id)
.filter(|record| record.can_be_downloaded())
{
if record.can_be_downloaded() { if record.can_be_downloaded() {
return Ok(Html(leptos::ssr::render_to_string({ return Ok(Html(leptos::ssr::render_to_string({
let record = record.clone(); let record = record.clone();
@ -292,11 +294,10 @@ async fn upload_to_zip(
async fn download( async fn download(
axum::extract::Path(id): axum::extract::Path<String>, axum::extract::Path(id): axum::extract::Path<String>,
headers: HeaderMap, headers: HeaderMap,
State(mut state): State<AppState>, State(state): State<AppState>,
) -> Result<axum::response::Response, (StatusCode, String)> { ) -> Result<axum::response::Response, (StatusCode, String)> {
{ {
let mut records = state.records.lock().await; let mut records = state.records.lock().await;
tracing::info!("{headers:?}");
if headers.get("hx-request").is_some() { if headers.get("hx-request").is_some() {
return Ok(axum::http::Response::builder() return Ok(axum::http::Response::builder()
.header("HX-Redirect", format!("/download/{id}")) .header("HX-Redirect", format!("/download/{id}"))
@ -306,23 +307,23 @@ async fn download(
.into_response()); .into_response());
} }
if let Some(record) = records.get_mut(&id) { if let Some(record) = records
if record.can_be_downloaded() { .get_mut(&id)
record.downloads += 1; .filter(|record| record.can_be_downloaded())
{
record.downloads += 1;
let file = tokio::fs::File::open(&record.file).await.unwrap(); let file = tokio::fs::File::open(&record.file).await.unwrap();
return Ok(axum::response::Response::builder() return Ok(axum::response::Response::builder()
.header("Content-Type", "application/zip") .header("Content-Type", "application/zip")
.body(StreamBody::new(ReaderStream::new(file))) .body(StreamBody::new(ReaderStream::new(file)))
.unwrap() .unwrap()
.into_response()); .into_response());
} } else {
records.remove_record(&id).await.unwrap()
} }
} }
// TODO: This....
state.remove_record(&id).await.unwrap();
Ok(Redirect::to("/404.html").into_response()) Ok(Redirect::to("/404.html").into_response())
} }

View File

@ -1,5 +1,6 @@
use std::{ use std::{
collections::HashMap, collections::{hash_map::Entry, HashMap},
io::ErrorKind,
path::{Path, PathBuf}, path::{Path, PathBuf},
sync::Arc, sync::Arc,
}; };
@ -72,26 +73,25 @@ pub trait AsyncRemoveRecord {
impl AsyncRemoveRecord for AppState { impl AsyncRemoveRecord for AppState {
async fn remove_record(&mut self, id: &String) -> Result<(), std::io::Error> { async fn remove_record(&mut self, id: &String) -> Result<(), std::io::Error> {
let mut records = self.records.lock().await; let mut records = self.records.lock().await;
records.remove_record(id).await
if let Some(record) = records.get_mut(id) {
tokio::fs::remove_file(&record.file).await?;
records.remove(id);
cache::write_to_cache(&records).await?;
}
Ok(())
} }
} }
#[async_trait] #[async_trait]
impl AsyncRemoveRecord for HashMap<String, UploadRecord> { impl AsyncRemoveRecord for HashMap<String, UploadRecord> {
async fn remove_record(&mut self, id: &String) -> Result<(), std::io::Error> { async fn remove_record(&mut self, id: &String) -> Result<(), std::io::Error> {
if let Some(record) = self.get_mut(id) { match self.entry(id.clone()) {
tokio::fs::remove_file(&record.file).await?; Entry::Occupied(entry) => {
self.remove(id); tokio::fs::remove_file(&entry.get().file).await?;
cache::write_to_cache(&self).await?; entry.remove_entry();
} cache::write_to_cache(&self).await?;
Ok(()) Ok(())
}
Entry::Vacant(_) => Err(std::io::Error::new(
ErrorKind::Other,
"No UploadRecord Found",
)),
}
} }
} }

View File

@ -91,7 +91,7 @@ pub fn LinkView(cx: Scope, id: String, record: UploadRecord) -> impl IntoView {
cx, cx,
<div class="column-container"> <div class="column-container">
<div class="link-wrapper"> <div class="link-wrapper">
<a id="link" hx-get="/download/{id}" href="/download/{id}">Download Now!</a> <a id="link" href="/download/{id}">Download Now!</a>
</div> </div>
<div class="link-wrapper" hx-get="/link/{id}/remaining" hx-trigger="click from:#link delay:0.2s, every 10s" > <div class="link-wrapper" hx-get="/link/{id}/remaining" hx-trigger="click from:#link delay:0.2s, every 10s" >