forked from neri/datatrash
update dependencies, urlencode filename
This commit is contained in:
parent
f100450796
commit
9e38960f00
File diff suppressed because it is too large
Load Diff
24
Cargo.toml
24
Cargo.toml
|
@ -7,19 +7,19 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-web = { version = "2.0.0", default-features = false, features = [] }
|
actix-web = "3.3.2"
|
||||||
sqlx = { version = "0.3.5", default-features = false, features = [ "runtime-async-std", "postgres", "chrono" ] }
|
sqlx = { version = "0.5.1", default-features = false, features = [ "runtime-async-std-rustls", "postgres", "chrono" ] }
|
||||||
actix-rt = "1.1.1"
|
env_logger = "0.8.3"
|
||||||
env_logger = "0.7.1"
|
log = "0.4.14"
|
||||||
log = "0.4.8"
|
actix-files = "0.5.0"
|
||||||
actix-files = "0.2.2"
|
async-std = "1.9.0"
|
||||||
async-std = "1.6.2"
|
actix-multipart = "0.3.0"
|
||||||
actix-multipart = "0.2.0"
|
futures = "0.3.13"
|
||||||
futures = "0.3.5"
|
rand = "0.8.3"
|
||||||
rand = "0.7.3"
|
chrono = "0.4.19"
|
||||||
chrono = "0.4.13"
|
openssl-sys = "0.9.60"
|
||||||
openssl-sys = "*"
|
|
||||||
htmlescape = "0.3.1"
|
htmlescape = "0.3.1"
|
||||||
|
urlencoding = "1.1.1"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
vendored = ["openssl-sys/vendored"]
|
vendored = ["openssl-sys/vendored"]
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
use async_std::{fs, path::PathBuf, sync::Receiver, task};
|
use async_std::{channel::Receiver, fs, path::PathBuf, task};
|
||||||
use chrono::{prelude::*, Duration};
|
use chrono::{prelude::*, Duration};
|
||||||
use futures::future::FutureExt;
|
use futures::{TryStreamExt, future::FutureExt};
|
||||||
use sqlx::{postgres::PgPool, Cursor, Row};
|
use sqlx::{postgres::PgPool, Row};
|
||||||
|
|
||||||
pub(crate) async fn delete_old_files(receiver: Receiver<()>, db: PgPool, files_dir: PathBuf) {
|
pub(crate) async fn delete_old_files(receiver: Receiver<()>, db: PgPool, files_dir: PathBuf) {
|
||||||
loop {
|
loop {
|
||||||
wait_for_file_expiry(&receiver, &db).await;
|
wait_for_file_expiry(&receiver, &db).await;
|
||||||
|
|
||||||
let now = Local::now().naive_local();
|
let now = Local::now().naive_local();
|
||||||
let mut cursor = sqlx::query("SELECT file_id FROM files WHERE files.valid_till < $1")
|
let mut rows = sqlx::query("SELECT file_id FROM files WHERE files.valid_till < $1")
|
||||||
.bind(now)
|
.bind(now)
|
||||||
.fetch(&db);
|
.fetch(&db);
|
||||||
while let Some(row) = cursor.next().await.expect("could not load expired files") {
|
while let Some(row) = rows.try_next().await.expect("could not load expired files") {
|
||||||
let file_id: String = row.get("file_id");
|
let file_id: String = row.try_get("file_id").expect("we selected this column");
|
||||||
let mut path = files_dir.clone();
|
let mut path = files_dir.clone();
|
||||||
path.push(&file_id);
|
path.push(&file_id);
|
||||||
if path.exists().await {
|
if path.exists().await {
|
||||||
|
@ -30,9 +30,9 @@ pub(crate) async fn delete_old_files(receiver: Receiver<()>, db: PgPool, files_d
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn wait_for_file_expiry(receiver: &Receiver<()>, db: &PgPool) {
|
async fn wait_for_file_expiry(receiver: &Receiver<()>, db: &PgPool) {
|
||||||
let mut cursor = sqlx::query("SELECT MIN(valid_till) as min from files").fetch(db);
|
let mut rows = sqlx::query("SELECT MIN(valid_till) as min from files").fetch(db);
|
||||||
let row = cursor
|
let row = rows
|
||||||
.next()
|
.try_next()
|
||||||
.await
|
.await
|
||||||
.expect("could not fetch expiring files from database")
|
.expect("could not fetch expiring files from database")
|
||||||
.expect("postgres min did not return any row");
|
.expect("postgres min did not return any row");
|
||||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -12,15 +12,16 @@ use actix_web::{
|
||||||
App, Error, FromRequest, HttpRequest, HttpResponse, HttpServer,
|
App, Error, FromRequest, HttpRequest, HttpResponse, HttpServer,
|
||||||
};
|
};
|
||||||
use async_std::{
|
use async_std::{
|
||||||
|
channel::{self, Sender},
|
||||||
fs,
|
fs,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{channel, Sender},
|
|
||||||
task,
|
task,
|
||||||
};
|
};
|
||||||
use file_kind::FileKind;
|
use file_kind::FileKind;
|
||||||
|
use futures::TryStreamExt;
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
postgres::{PgPool, PgRow},
|
postgres::{PgPool, PgPoolOptions, PgRow},
|
||||||
Cursor, Row,
|
Row,
|
||||||
};
|
};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
@ -92,10 +93,11 @@ async fn upload(
|
||||||
kind
|
kind
|
||||||
);
|
);
|
||||||
|
|
||||||
expiry_watch_sender.send(()).await;
|
expiry_watch_sender.send(()).await.unwrap();
|
||||||
|
|
||||||
let redirect = if kind == FileKind::BINARY && original_name.is_some() {
|
let redirect = if kind == FileKind::BINARY && original_name.is_some() {
|
||||||
format!("/upload/{}/{}", file_id, original_name.as_ref().unwrap())
|
let encoded_name = urlencoding::encode(original_name.as_ref().unwrap());
|
||||||
|
format!("/upload/{}/{}", file_id, encoded_name)
|
||||||
} else {
|
} else {
|
||||||
format!("/upload/{}", file_id)
|
format!("/upload/{}", file_id)
|
||||||
};
|
};
|
||||||
|
@ -113,7 +115,8 @@ fn get_host_url(req: &web::HttpRequest) -> String {
|
||||||
|
|
||||||
fn get_file_url(req: &web::HttpRequest, id: &str, name: Option<&str>) -> String {
|
fn get_file_url(req: &web::HttpRequest, id: &str, name: Option<&str>) -> String {
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
format!("{}/file/{}/{}", get_host_url(req), id, name)
|
let encoded_name = urlencoding::encode(name);
|
||||||
|
format!("{}/file/{}/{}", get_host_url(req), id, encoded_name)
|
||||||
} else {
|
} else {
|
||||||
format!("{}/file/{}", get_host_url(req), id)
|
format!("{}/file/{}", get_host_url(req), id)
|
||||||
}
|
}
|
||||||
|
@ -135,11 +138,11 @@ async fn download(
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let id = req.match_info().query("id");
|
let id = req.match_info().query("id");
|
||||||
let mut cursor = sqlx::query("SELECT file_id, file_name, kind from files WHERE file_id = $1")
|
let mut rows = sqlx::query("SELECT file_id, file_name, kind from files WHERE file_id = $1")
|
||||||
.bind(id)
|
.bind(id)
|
||||||
.fetch(db.as_ref());
|
.fetch(db.as_ref());
|
||||||
let row: PgRow = cursor
|
let row: PgRow = rows
|
||||||
.next()
|
.try_next()
|
||||||
.await
|
.await
|
||||||
.map_err(|_| error::ErrorInternalServerError("could not run select statement"))?
|
.map_err(|_| error::ErrorInternalServerError("could not run select statement"))?
|
||||||
.ok_or_else(|| error::ErrorNotFound("file does not exist or has expired"))?;
|
.ok_or_else(|| error::ErrorNotFound("file does not exist or has expired"))?;
|
||||||
|
@ -204,10 +207,10 @@ async fn setup_db() -> PgPool {
|
||||||
let conn_url = &get_db_url();
|
let conn_url = &get_db_url();
|
||||||
log::info!("Using Connection string {}", conn_url);
|
log::info!("Using Connection string {}", conn_url);
|
||||||
|
|
||||||
let pool = PgPool::builder()
|
let pool = PgPoolOptions::new()
|
||||||
.max_size(5)
|
.max_connections(5)
|
||||||
.connect_timeout(std::time::Duration::from_secs(5))
|
.connect_timeout(std::time::Duration::from_secs(5))
|
||||||
.build(conn_url)
|
.connect(conn_url)
|
||||||
.await
|
.await
|
||||||
.expect("could not create db pool");
|
.expect("could not create db pool");
|
||||||
|
|
||||||
|
@ -224,7 +227,7 @@ struct Config {
|
||||||
files_dir: PathBuf,
|
files_dir: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
if env::var("RUST_LOG").is_err() {
|
if env::var("RUST_LOG").is_err() {
|
||||||
env::set_var("RUST_LOG", "info");
|
env::set_var("RUST_LOG", "info");
|
||||||
|
@ -238,7 +241,7 @@ async fn main() -> std::io::Result<()> {
|
||||||
fs::create_dir_all(&config.files_dir)
|
fs::create_dir_all(&config.files_dir)
|
||||||
.await
|
.await
|
||||||
.expect("could not create directory for storing files");
|
.expect("could not create directory for storing files");
|
||||||
let (sender, receiver) = channel(8);
|
let (sender, receiver) = channel::bounded(8);
|
||||||
|
|
||||||
log::info!("omnomnom");
|
log::info!("omnomnom");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue