mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 19:31:35 +00:00
Update to actix-web 4.0.0-beta.3
This commit is contained in:
parent
d51a73cee9
commit
79b26a1dda
8 changed files with 376 additions and 748 deletions
927
Cargo.lock
generated
927
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
19
Cargo.toml
19
Cargo.toml
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "pict-rs"
|
name = "pict-rs"
|
||||||
description = "A simple image hosting service"
|
description = "A simple image hosting service"
|
||||||
version = "0.3.0-alpha.6"
|
version = "0.3.0-alpha.7"
|
||||||
authors = ["asonix <asonix@asonix.dog>"]
|
authors = ["asonix <asonix@asonix.dog>"]
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -11,24 +11,23 @@ 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-form-data = "0.5.0"
|
actix-form-data = "0.6.0-beta.1"
|
||||||
actix-fs = { git = "https://git.asonix.dog/asonix/actix-fs", branch = "main" }
|
actix-fs = { git = "https://git.asonix.dog/asonix/actix-fs", branch = "asonix/actix-rt-2" }
|
||||||
actix-rt = "1.1.1"
|
actix-rt = "2.0.2"
|
||||||
actix-web = { version = "3.0.1", default-features = false, features = ["rustls"] }
|
actix-web = { version = "4.0.0-beta.3", default-features = false, features = ["rustls", "compress"] }
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
async-stream = "0.3.0"
|
async-stream = "0.3.0"
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
bytes = "0.5"
|
|
||||||
futures = "0.3.4"
|
futures = "0.3.4"
|
||||||
magick_rust = { version = "0.14.0", git = "https://github.com/nlfiedler/magick-rust" }
|
magick_rust = { version = "0.14.0", git = "https://github.com/nlfiedler/magick-rust" }
|
||||||
mime = "0.3.1"
|
mime = "0.3.1"
|
||||||
once_cell = "1.4.0"
|
once_cell = "1.4.0"
|
||||||
rand = "0.7.3"
|
rand = "0.8.0"
|
||||||
rexiv2 = "0.9.1"
|
rexiv2 = "0.9.1"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
sha2 = "0.9.0"
|
sha2 = "0.9.0"
|
||||||
sled = { version = "0.34.4" }
|
sled = { version = "0.34.6" }
|
||||||
structopt = "0.3.14"
|
structopt = "0.3.14"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
time = { version = "0.2.23", features = ["serde"] }
|
time = { version = "0.2.23", features = ["serde"] }
|
||||||
|
@ -44,3 +43,7 @@ features = ["codec", "filter", "device", "format", "resampling", "postprocessing
|
||||||
|
|
||||||
[dependencies.ffmpeg-sys-next]
|
[dependencies.ffmpeg-sys-next]
|
||||||
version = "4.3.5"
|
version = "4.3.5"
|
||||||
|
git = "https://github.com/baadc0de/rust-ffmpeg-sys"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
ffmpeg-sys-next = { git = "https://github.com/baadc0de/rust-ffmpeg-sys", branch = "master" }
|
||||||
|
|
15
src/error.rs
15
src/error.rs
|
@ -100,15 +100,9 @@ impl From<actix_form_data::Error> for UploadError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<actix_web::error::BlockingError<T>> for UploadError
|
impl From<actix_web::error::BlockingError> for UploadError {
|
||||||
where
|
fn from(_: actix_web::error::BlockingError) -> Self {
|
||||||
T: Into<UploadError> + std::fmt::Debug,
|
UploadError::Canceled
|
||||||
{
|
|
||||||
fn from(e: actix_web::error::BlockingError<T>) -> Self {
|
|
||||||
match e {
|
|
||||||
actix_web::error::BlockingError::Error(e) => e.into(),
|
|
||||||
_ => UploadError::Canceled,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +122,7 @@ impl ResponseError for UploadError {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_response(&self) -> HttpResponse {
|
fn error_response(&self) -> HttpResponse {
|
||||||
HttpResponse::build(self.status_code()).json(serde_json::json!({ "msg": self.to_string() }))
|
HttpResponse::build(self.status_code())
|
||||||
|
.json(&serde_json::json!({ "msg": self.to_string() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
39
src/main.rs
39
src/main.rs
|
@ -7,7 +7,6 @@ use actix_web::{
|
||||||
middleware::{Compress, Logger},
|
middleware::{Compress, Logger},
|
||||||
web, App, HttpResponse, HttpServer,
|
web, App, HttpResponse, HttpServer,
|
||||||
};
|
};
|
||||||
use bytes::Bytes;
|
|
||||||
use futures::stream::{once, Stream, TryStreamExt};
|
use futures::stream::{once, Stream, TryStreamExt};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -50,6 +49,7 @@ static TMP_DIR: Lazy<PathBuf> = Lazy::new(|| {
|
||||||
let tmp_nonce = Alphanumeric
|
let tmp_nonce = Alphanumeric
|
||||||
.sample_iter(&mut rng)
|
.sample_iter(&mut rng)
|
||||||
.take(7)
|
.take(7)
|
||||||
|
.map(char::from)
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
let mut path = std::env::temp_dir();
|
let mut path = std::env::temp_dir();
|
||||||
|
@ -93,7 +93,7 @@ async fn safe_create_parent(path: PathBuf) -> Result<(), UploadError> {
|
||||||
|
|
||||||
// Try writing to a file
|
// Try writing to a file
|
||||||
#[instrument(skip(bytes))]
|
#[instrument(skip(bytes))]
|
||||||
async fn safe_save_file(path: PathBuf, bytes: bytes::Bytes) -> Result<(), UploadError> {
|
async fn safe_save_file(path: PathBuf, bytes: web::Bytes) -> Result<(), UploadError> {
|
||||||
if let Some(path) = path.parent() {
|
if let Some(path) = path.parent() {
|
||||||
// create the directory for the file
|
// create the directory for the file
|
||||||
debug!("Creating directory {:?}", path);
|
debug!("Creating directory {:?}", path);
|
||||||
|
@ -132,7 +132,11 @@ pub(crate) fn tmp_file() -> PathBuf {
|
||||||
let limit: usize = 10;
|
let limit: usize = 10;
|
||||||
let rng = rand::thread_rng();
|
let rng = rand::thread_rng();
|
||||||
|
|
||||||
let s: String = Alphanumeric.sample_iter(rng).take(limit).collect();
|
let s: String = Alphanumeric
|
||||||
|
.sample_iter(rng)
|
||||||
|
.take(limit)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let name = format!("{}.tmp", s);
|
let name = format!("{}.tmp", s);
|
||||||
|
|
||||||
|
@ -203,7 +207,7 @@ async fn upload(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(HttpResponse::Created().json(serde_json::json!({
|
Ok(HttpResponse::Created().json(&serde_json::json!({
|
||||||
"msg": "ok",
|
"msg": "ok",
|
||||||
"files": files
|
"files": files
|
||||||
})))
|
})))
|
||||||
|
@ -250,7 +254,7 @@ async fn download(
|
||||||
new_details
|
new_details
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(HttpResponse::Created().json(serde_json::json!({
|
Ok(HttpResponse::Created().json(&serde_json::json!({
|
||||||
"msg": "ok",
|
"msg": "ok",
|
||||||
"files": [{
|
"files": [{
|
||||||
"file": alias,
|
"file": alias,
|
||||||
|
@ -334,7 +338,7 @@ async fn process_details(
|
||||||
|
|
||||||
let details = details.ok_or(UploadError::NoFiles)?;
|
let details = details.ok_or(UploadError::NoFiles)?;
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(details))
|
Ok(HttpResponse::Ok().json(&details))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process files
|
/// Process files
|
||||||
|
@ -447,7 +451,7 @@ async fn process(
|
||||||
let range = range_header.ranges().next().unwrap();
|
let range = range_header.ranges().next().unwrap();
|
||||||
|
|
||||||
let mut builder = HttpResponse::PartialContent();
|
let mut builder = HttpResponse::PartialContent();
|
||||||
builder.set(range.to_content_range(img_bytes.len() as u64));
|
builder.insert_header(range.to_content_range(img_bytes.len() as u64));
|
||||||
(builder, range.chop_bytes(img_bytes))
|
(builder, range.chop_bytes(img_bytes))
|
||||||
} else {
|
} else {
|
||||||
return Err(UploadError::Range);
|
return Err(UploadError::Range);
|
||||||
|
@ -499,7 +503,7 @@ async fn details(
|
||||||
new_details
|
new_details
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(details))
|
Ok(HttpResponse::Ok().json(&details))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serve files
|
/// Serve files
|
||||||
|
@ -550,7 +554,7 @@ async fn ranged_file_resp(
|
||||||
let range = range_header.ranges().next().unwrap();
|
let range = range_header.ranges().next().unwrap();
|
||||||
|
|
||||||
let mut builder = HttpResponse::PartialContent();
|
let mut builder = HttpResponse::PartialContent();
|
||||||
builder.set(range.to_content_range(meta.len()));
|
builder.insert_header(range.to_content_range(meta.len()));
|
||||||
|
|
||||||
(builder, range.chop_file(file).await?)
|
(builder, range.chop_file(file).await?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -562,7 +566,8 @@ async fn ranged_file_resp(
|
||||||
let stream = actix_fs::read_to_stream(path)
|
let stream = actix_fs::read_to_stream(path)
|
||||||
.await?
|
.await?
|
||||||
.map_err(UploadError::from);
|
.map_err(UploadError::from);
|
||||||
let stream: Pin<Box<dyn Stream<Item = Result<Bytes, UploadError>>>> = Box::pin(stream);
|
let stream: Pin<Box<dyn Stream<Item = Result<web::Bytes, UploadError>>>> =
|
||||||
|
Box::pin(stream);
|
||||||
(HttpResponse::Ok(), stream)
|
(HttpResponse::Ok(), stream)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -585,18 +590,18 @@ fn srv_response<S, E>(
|
||||||
modified: SystemTime,
|
modified: SystemTime,
|
||||||
) -> HttpResponse
|
) -> HttpResponse
|
||||||
where
|
where
|
||||||
S: Stream<Item = Result<bytes::Bytes, E>> + Unpin + 'static,
|
S: Stream<Item = Result<web::Bytes, E>> + Unpin + 'static,
|
||||||
E: 'static,
|
E: 'static,
|
||||||
actix_web::Error: From<E>,
|
actix_web::Error: From<E>,
|
||||||
{
|
{
|
||||||
builder
|
builder
|
||||||
.set(LastModified(modified.into()))
|
.insert_header(LastModified(modified.into()))
|
||||||
.set(CacheControl(vec![
|
.insert_header(CacheControl(vec![
|
||||||
CacheDirective::Public,
|
CacheDirective::Public,
|
||||||
CacheDirective::MaxAge(expires),
|
CacheDirective::MaxAge(expires),
|
||||||
CacheDirective::Extension("immutable".to_owned(), None),
|
CacheDirective::Extension("immutable".to_owned(), None),
|
||||||
]))
|
]))
|
||||||
.set_header(ACCEPT_RANGES, "bytes")
|
.insert_header((ACCEPT_RANGES, "bytes"))
|
||||||
.content_type(ext.to_string())
|
.content_type(ext.to_string())
|
||||||
.streaming(stream)
|
.streaming(stream)
|
||||||
}
|
}
|
||||||
|
@ -623,7 +628,7 @@ async fn purge(
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
Ok(HttpResponse::Ok().json(&serde_json::json!({
|
||||||
"msg": "ok",
|
"msg": "ok",
|
||||||
"aliases": aliases
|
"aliases": aliases
|
||||||
})))
|
})))
|
||||||
|
@ -638,7 +643,7 @@ async fn aliases(
|
||||||
FileOrAlias::Alias { alias } => upload_manager.aliases_by_alias(alias).await?,
|
FileOrAlias::Alias { alias } => upload_manager.aliases_by_alias(alias).await?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
Ok(HttpResponse::Ok().json(&serde_json::json!({
|
||||||
"msg": "ok",
|
"msg": "ok",
|
||||||
"aliases": aliases,
|
"aliases": aliases,
|
||||||
})))
|
})))
|
||||||
|
@ -655,7 +660,7 @@ async fn filename_by_alias(
|
||||||
) -> Result<HttpResponse, UploadError> {
|
) -> Result<HttpResponse, UploadError> {
|
||||||
let filename = upload_manager.from_alias(query.into_inner().alias).await?;
|
let filename = upload_manager.from_alias(query.into_inner().alias).await?;
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(serde_json::json!({
|
Ok(HttpResponse::Ok().json(&serde_json::json!({
|
||||||
"msg": "ok",
|
"msg": "ok",
|
||||||
"filename": filename,
|
"filename": filename,
|
||||||
})))
|
})))
|
||||||
|
|
|
@ -26,16 +26,16 @@ impl ResponseError for ApiError {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_response(&self) -> HttpResponse {
|
fn error_response(&self) -> HttpResponse {
|
||||||
HttpResponse::build(self.status_code()).json(serde_json::json!({ "msg": self.to_string() }))
|
HttpResponse::build(self.status_code())
|
||||||
|
.json(&serde_json::json!({ "msg": self.to_string() }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Transform<S> for Tracing
|
impl<S, Request> Transform<S, Request> for Tracing
|
||||||
where
|
where
|
||||||
S: Service,
|
S: Service<Request>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
{
|
{
|
||||||
type Request = S::Request;
|
|
||||||
type Response = S::Response;
|
type Response = S::Response;
|
||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
|
@ -47,21 +47,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Service for TracingMiddleware<S>
|
impl<S, Request> Service<Request> for TracingMiddleware<S>
|
||||||
where
|
where
|
||||||
S: Service,
|
S: Service<Request>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
{
|
{
|
||||||
type Request = S::Request;
|
|
||||||
type Response = S::Response;
|
type Response = S::Response;
|
||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type Future = Instrumented<S::Future>;
|
type Future = Instrumented<S::Future>;
|
||||||
|
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
self.inner.poll_ready(cx)
|
self.inner.poll_ready(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: S::Request) -> Self::Future {
|
fn call(&self, req: Request) -> Self::Future {
|
||||||
let uuid = Uuid::new_v4();
|
let uuid = Uuid::new_v4();
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
|
@ -70,12 +69,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Transform<S> for Internal
|
impl<S> Transform<S, ServiceRequest> for Internal
|
||||||
where
|
where
|
||||||
S: Service<Request = ServiceRequest, Error = actix_web::Error>,
|
S: Service<ServiceRequest, Error = actix_web::Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
{
|
{
|
||||||
type Request = S::Request;
|
|
||||||
type Response = S::Response;
|
type Response = S::Response;
|
||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type InitError = ();
|
type InitError = ();
|
||||||
|
@ -87,21 +85,20 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Service for InternalMiddleware<S>
|
impl<S> Service<ServiceRequest> for InternalMiddleware<S>
|
||||||
where
|
where
|
||||||
S: Service<Request = ServiceRequest, Error = actix_web::Error>,
|
S: Service<ServiceRequest, Error = actix_web::Error>,
|
||||||
S::Future: 'static,
|
S::Future: 'static,
|
||||||
{
|
{
|
||||||
type Request = S::Request;
|
|
||||||
type Response = S::Response;
|
type Response = S::Response;
|
||||||
type Error = S::Error;
|
type Error = S::Error;
|
||||||
type Future = LocalBoxFuture<'static, Result<S::Response, S::Error>>;
|
type Future = LocalBoxFuture<'static, Result<S::Response, S::Error>>;
|
||||||
|
|
||||||
fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
|
||||||
self.1.poll_ready(cx)
|
self.1.poll_ready(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: S::Request) -> Self::Future {
|
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||||
if let Some(value) = req.headers().get("x-api-token") {
|
if let Some(value) = req.headers().get("x-api-token") {
|
||||||
if value.to_str().is_ok() && value.to_str().ok() == self.0.as_deref() {
|
if value.to_str().is_ok() && value.to_str().ok() == self.0.as_deref() {
|
||||||
let fut = self.1.call(req);
|
let fut = self.1.call(req);
|
||||||
|
|
|
@ -4,7 +4,6 @@ use crate::{
|
||||||
validate::{ptos, Op},
|
validate::{ptos, Op},
|
||||||
};
|
};
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use bytes::Bytes;
|
|
||||||
use magick_rust::MagickWand;
|
use magick_rust::MagickWand;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tracing::{debug, error, instrument, Span};
|
use tracing::{debug, error, instrument, Span};
|
||||||
|
@ -372,7 +371,7 @@ pub(crate) async fn prepare_image(
|
||||||
|
|
||||||
transcode(orig_path, tmpfile, Target::Jpeg).map_err(UploadError::Transcode)
|
transcode(orig_path, tmpfile, Target::Jpeg).map_err(UploadError::Transcode)
|
||||||
})
|
})
|
||||||
.await;
|
.await?;
|
||||||
|
|
||||||
if let Err(e) = res {
|
if let Err(e) = res {
|
||||||
error!("transcode error: {:?}", e);
|
error!("transcode error: {:?}", e);
|
||||||
|
@ -395,7 +394,7 @@ pub(crate) async fn process_image(
|
||||||
original_file: PathBuf,
|
original_file: PathBuf,
|
||||||
chain: ProcessChain,
|
chain: ProcessChain,
|
||||||
format: Format,
|
format: Format,
|
||||||
) -> Result<Bytes, UploadError> {
|
) -> Result<web::Bytes, UploadError> {
|
||||||
let original_path_str = ptos(&original_file)?;
|
let original_path_str = ptos(&original_file)?;
|
||||||
|
|
||||||
let span = Span::current();
|
let span = Span::current();
|
||||||
|
@ -414,9 +413,9 @@ pub(crate) async fn process_image(
|
||||||
|
|
||||||
let vec = wand.op(|w| w.write_image_blob(format.to_magick_format()))?;
|
let vec = wand.op(|w| w.write_image_blob(format.to_magick_format()))?;
|
||||||
drop(entered);
|
drop(entered);
|
||||||
Ok(Bytes::from(vec)) as Result<Bytes, UploadError>
|
Ok(web::Bytes::from(vec)) as Result<web::Bytes, UploadError>
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ impl std::fmt::Debug for UploadManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type UploadStream<E> = Pin<Box<dyn Stream<Item = Result<bytes::Bytes, E>>>>;
|
type UploadStream<E> = Pin<Box<dyn Stream<Item = Result<web::Bytes, E>>>>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct Serde<T> {
|
pub(crate) struct Serde<T> {
|
||||||
|
@ -134,7 +134,7 @@ impl Details {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
Ok(Details::now(width as usize, height as usize, mime_type))
|
Ok(Details::now(width as usize, height as usize, mime_type))
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ impl UploadManager {
|
||||||
) -> Result<Self, UploadError> {
|
) -> Result<Self, UploadError> {
|
||||||
let root_clone = root_dir.clone();
|
let root_clone = root_dir.clone();
|
||||||
// sled automatically creates it's own directories
|
// sled automatically creates it's own directories
|
||||||
let db = web::block(move || LatestDb::exists(root_clone).migrate()).await?;
|
let db = web::block(move || LatestDb::exists(root_clone).migrate()).await??;
|
||||||
|
|
||||||
root_dir.push("files");
|
root_dir.push("files");
|
||||||
|
|
||||||
|
@ -245,13 +245,13 @@ impl UploadManager {
|
||||||
let fname_tree = self.inner.filename_tree.clone();
|
let fname_tree = self.inner.filename_tree.clone();
|
||||||
debug!("Getting hash");
|
debug!("Getting hash");
|
||||||
let hash: sled::IVec = web::block(move || fname_tree.get(filename.as_bytes()))
|
let hash: sled::IVec = web::block(move || fname_tree.get(filename.as_bytes()))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingFilename)?;
|
.ok_or(UploadError::MissingFilename)?;
|
||||||
|
|
||||||
let key = variant_key(&hash, &path_string);
|
let key = variant_key(&hash, &path_string);
|
||||||
let main_tree = self.inner.main_tree.clone();
|
let main_tree = self.inner.main_tree.clone();
|
||||||
debug!("Storing variant");
|
debug!("Storing variant");
|
||||||
web::block(move || main_tree.insert(key, path_string.as_bytes())).await?;
|
web::block(move || main_tree.insert(key, path_string.as_bytes())).await??;
|
||||||
debug!("Stored variant");
|
debug!("Stored variant");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -268,13 +268,13 @@ impl UploadManager {
|
||||||
let fname_tree = self.inner.filename_tree.clone();
|
let fname_tree = self.inner.filename_tree.clone();
|
||||||
debug!("Getting hash");
|
debug!("Getting hash");
|
||||||
let hash: sled::IVec = web::block(move || fname_tree.get(filename.as_bytes()))
|
let hash: sled::IVec = web::block(move || fname_tree.get(filename.as_bytes()))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingFilename)?;
|
.ok_or(UploadError::MissingFilename)?;
|
||||||
|
|
||||||
let key = variant_details_key(&hash, &path_string);
|
let key = variant_details_key(&hash, &path_string);
|
||||||
let main_tree = self.inner.main_tree.clone();
|
let main_tree = self.inner.main_tree.clone();
|
||||||
debug!("Getting details");
|
debug!("Getting details");
|
||||||
let opt = match web::block(move || main_tree.get(key)).await? {
|
let opt = match web::block(move || main_tree.get(key)).await?? {
|
||||||
Some(ivec) => match serde_json::from_slice(&ivec) {
|
Some(ivec) => match serde_json::from_slice(&ivec) {
|
||||||
Ok(details) => Some(details),
|
Ok(details) => Some(details),
|
||||||
Err(_) => None,
|
Err(_) => None,
|
||||||
|
@ -297,14 +297,14 @@ impl UploadManager {
|
||||||
let fname_tree = self.inner.filename_tree.clone();
|
let fname_tree = self.inner.filename_tree.clone();
|
||||||
debug!("Getting hash");
|
debug!("Getting hash");
|
||||||
let hash: sled::IVec = web::block(move || fname_tree.get(filename.as_bytes()))
|
let hash: sled::IVec = web::block(move || fname_tree.get(filename.as_bytes()))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingFilename)?;
|
.ok_or(UploadError::MissingFilename)?;
|
||||||
|
|
||||||
let key = variant_details_key(&hash, &path_string);
|
let key = variant_details_key(&hash, &path_string);
|
||||||
let main_tree = self.inner.main_tree.clone();
|
let main_tree = self.inner.main_tree.clone();
|
||||||
let details_value = serde_json::to_string(details)?;
|
let details_value = serde_json::to_string(details)?;
|
||||||
debug!("Storing details");
|
debug!("Storing details");
|
||||||
web::block(move || main_tree.insert(key, details_value.as_bytes())).await?;
|
web::block(move || main_tree.insert(key, details_value.as_bytes())).await??;
|
||||||
debug!("Stored details");
|
debug!("Stored details");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -317,7 +317,7 @@ impl UploadManager {
|
||||||
) -> Result<Vec<String>, UploadError> {
|
) -> Result<Vec<String>, UploadError> {
|
||||||
let fname_tree = self.inner.filename_tree.clone();
|
let fname_tree = self.inner.filename_tree.clone();
|
||||||
let hash = web::block(move || fname_tree.get(filename.as_bytes()))
|
let hash = web::block(move || fname_tree.get(filename.as_bytes()))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingAlias)?;
|
.ok_or(UploadError::MissingAlias)?;
|
||||||
|
|
||||||
self.aliases_by_hash(&hash).await
|
self.aliases_by_hash(&hash).await
|
||||||
|
@ -327,7 +327,7 @@ impl UploadManager {
|
||||||
pub(crate) async fn aliases_by_alias(&self, alias: String) -> Result<Vec<String>, UploadError> {
|
pub(crate) async fn aliases_by_alias(&self, alias: String) -> Result<Vec<String>, UploadError> {
|
||||||
let alias_tree = self.inner.alias_tree.clone();
|
let alias_tree = self.inner.alias_tree.clone();
|
||||||
let hash = web::block(move || alias_tree.get(alias.as_bytes()))
|
let hash = web::block(move || alias_tree.get(alias.as_bytes()))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingFilename)?;
|
.ok_or(UploadError::MissingFilename)?;
|
||||||
|
|
||||||
self.aliases_by_hash(&hash).await
|
self.aliases_by_hash(&hash).await
|
||||||
|
@ -342,7 +342,7 @@ impl UploadManager {
|
||||||
.values()
|
.values()
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
debug!("Got {} aliases for hash", aliases.len());
|
debug!("Got {} aliases for hash", aliases.len());
|
||||||
let aliases = aliases
|
let aliases = aliases
|
||||||
|
@ -362,7 +362,7 @@ impl UploadManager {
|
||||||
let token_key = delete_key(&alias);
|
let token_key = delete_key(&alias);
|
||||||
let alias_tree = self.inner.alias_tree.clone();
|
let alias_tree = self.inner.alias_tree.clone();
|
||||||
let token = web::block(move || alias_tree.get(token_key.as_bytes()))
|
let token = web::block(move || alias_tree.get(token_key.as_bytes()))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingAlias)?;
|
.ok_or(UploadError::MissingAlias)?;
|
||||||
|
|
||||||
self.delete(alias, String::from_utf8(token.to_vec())?).await
|
self.delete(alias, String::from_utf8(token.to_vec())?).await
|
||||||
|
@ -415,7 +415,7 @@ impl UploadManager {
|
||||||
Ok(hash)
|
Ok(hash)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
// -- CHECK IF ANY OTHER ALIASES EXIST --
|
// -- CHECK IF ANY OTHER ALIASES EXIST --
|
||||||
let main_tree = self.inner.main_tree.clone();
|
let main_tree = self.inner.main_tree.clone();
|
||||||
|
@ -424,7 +424,7 @@ impl UploadManager {
|
||||||
let any_aliases = web::block(move || {
|
let any_aliases = web::block(move || {
|
||||||
Ok(main_tree.range(start..end).next().is_some()) as Result<bool, UploadError>
|
Ok(main_tree.range(start..end).next().is_some()) as Result<bool, UploadError>
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
// Bail if there are existing aliases
|
// Bail if there are existing aliases
|
||||||
if any_aliases {
|
if any_aliases {
|
||||||
|
@ -437,7 +437,7 @@ impl UploadManager {
|
||||||
let hash2 = hash.clone();
|
let hash2 = hash.clone();
|
||||||
debug!("Deleting hash -> filename mapping");
|
debug!("Deleting hash -> filename mapping");
|
||||||
let filename = web::block(move || main_tree.remove(&hash2))
|
let filename = web::block(move || main_tree.remove(&hash2))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingFile)?;
|
.ok_or(UploadError::MissingFile)?;
|
||||||
|
|
||||||
// -- DELETE FILES --
|
// -- DELETE FILES --
|
||||||
|
@ -468,7 +468,11 @@ impl UploadManager {
|
||||||
debug!("Generating delete token");
|
debug!("Generating delete token");
|
||||||
use rand::distributions::{Alphanumeric, Distribution};
|
use rand::distributions::{Alphanumeric, Distribution};
|
||||||
let rng = rand::thread_rng();
|
let rng = rand::thread_rng();
|
||||||
let s: String = Alphanumeric.sample_iter(rng).take(10).collect();
|
let s: String = Alphanumeric
|
||||||
|
.sample_iter(rng)
|
||||||
|
.take(10)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
let delete_token = s.clone();
|
let delete_token = s.clone();
|
||||||
|
|
||||||
debug!("Saving delete token");
|
debug!("Saving delete token");
|
||||||
|
@ -481,7 +485,7 @@ impl UploadManager {
|
||||||
Some(s.as_bytes()),
|
Some(s.as_bytes()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
if let Err(sled::CompareAndSwapError {
|
if let Err(sled::CompareAndSwapError {
|
||||||
current: Some(ivec),
|
current: Some(ivec),
|
||||||
|
@ -579,13 +583,13 @@ impl UploadManager {
|
||||||
let tree = self.inner.alias_tree.clone();
|
let tree = self.inner.alias_tree.clone();
|
||||||
debug!("Getting hash from alias");
|
debug!("Getting hash from alias");
|
||||||
let hash = web::block(move || tree.get(alias.as_bytes()))
|
let hash = web::block(move || tree.get(alias.as_bytes()))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingAlias)?;
|
.ok_or(UploadError::MissingAlias)?;
|
||||||
|
|
||||||
let main_tree = self.inner.main_tree.clone();
|
let main_tree = self.inner.main_tree.clone();
|
||||||
debug!("Getting filename from hash");
|
debug!("Getting filename from hash");
|
||||||
let filename = web::block(move || main_tree.get(hash))
|
let filename = web::block(move || main_tree.get(hash))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingFile)?;
|
.ok_or(UploadError::MissingFile)?;
|
||||||
|
|
||||||
let filename = String::from_utf8(filename.to_vec())?;
|
let filename = String::from_utf8(filename.to_vec())?;
|
||||||
|
@ -610,7 +614,7 @@ impl UploadManager {
|
||||||
let fname_tree = self.inner.filename_tree.clone();
|
let fname_tree = self.inner.filename_tree.clone();
|
||||||
debug!("Deleting filename -> hash mapping");
|
debug!("Deleting filename -> hash mapping");
|
||||||
let hash = web::block(move || fname_tree.remove(filename))
|
let hash = web::block(move || fname_tree.remove(filename))
|
||||||
.await?
|
.await??
|
||||||
.ok_or(UploadError::MissingFile)?;
|
.ok_or(UploadError::MissingFile)?;
|
||||||
|
|
||||||
let (start, end) = variant_key_bounds(&hash);
|
let (start, end) = variant_key_bounds(&hash);
|
||||||
|
@ -624,13 +628,13 @@ impl UploadManager {
|
||||||
|
|
||||||
Ok(keys) as Result<Vec<sled::IVec>, UploadError>
|
Ok(keys) as Result<Vec<sled::IVec>, UploadError>
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
debug!("{} files prepared for deletion", keys.len());
|
debug!("{} files prepared for deletion", keys.len());
|
||||||
|
|
||||||
for key in keys {
|
for key in keys {
|
||||||
let main_tree = self.inner.main_tree.clone();
|
let main_tree = self.inner.main_tree.clone();
|
||||||
if let Some(path) = web::block(move || main_tree.remove(key)).await? {
|
if let Some(path) = web::block(move || main_tree.remove(key)).await?? {
|
||||||
let s = String::from_utf8_lossy(&path);
|
let s = String::from_utf8_lossy(&path);
|
||||||
debug!("Deleting {}", s);
|
debug!("Deleting {}", s);
|
||||||
// ignore json objects
|
// ignore json objects
|
||||||
|
@ -685,12 +689,12 @@ impl UploadManager {
|
||||||
hasher.update(&bytes);
|
hasher.update(&bytes);
|
||||||
Ok(hasher) as Result<_, UploadError>
|
Ok(hasher) as Result<_, UploadError>
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
}
|
}
|
||||||
|
|
||||||
let hash =
|
let hash =
|
||||||
web::block(move || Ok(hasher.finalize_reset().to_vec()) as Result<_, UploadError>)
|
web::block(move || Ok(hasher.finalize_reset().to_vec()) as Result<_, UploadError>)
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
Ok(Hash::new(hash))
|
Ok(Hash::new(hash))
|
||||||
}
|
}
|
||||||
|
@ -715,7 +719,7 @@ impl UploadManager {
|
||||||
Some(filename2.as_bytes()),
|
Some(filename2.as_bytes()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
if let Err(sled::CompareAndSwapError {
|
if let Err(sled::CompareAndSwapError {
|
||||||
current: Some(ivec),
|
current: Some(ivec),
|
||||||
|
@ -730,7 +734,7 @@ impl UploadManager {
|
||||||
let fname_tree = self.inner.filename_tree.clone();
|
let fname_tree = self.inner.filename_tree.clone();
|
||||||
let filename2 = filename.clone();
|
let filename2 = filename.clone();
|
||||||
debug!("Saving filename -> hash relation");
|
debug!("Saving filename -> hash relation");
|
||||||
web::block(move || fname_tree.insert(filename2, hash.inner)).await?;
|
web::block(move || fname_tree.insert(filename2, hash.inner)).await??;
|
||||||
|
|
||||||
Ok((Dup::New, filename))
|
Ok((Dup::New, filename))
|
||||||
}
|
}
|
||||||
|
@ -741,11 +745,15 @@ impl UploadManager {
|
||||||
let image_dir = self.image_dir();
|
let image_dir = self.image_dir();
|
||||||
use rand::distributions::{Alphanumeric, Distribution};
|
use rand::distributions::{Alphanumeric, Distribution};
|
||||||
let mut limit: usize = 10;
|
let mut limit: usize = 10;
|
||||||
let rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
loop {
|
loop {
|
||||||
debug!("Filename generation loop");
|
debug!("Filename generation loop");
|
||||||
let mut path = image_dir.clone();
|
let mut path = image_dir.clone();
|
||||||
let s: String = Alphanumeric.sample_iter(rng).take(limit).collect();
|
let s: String = Alphanumeric
|
||||||
|
.sample_iter(&mut rng)
|
||||||
|
.take(limit)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let filename = file_name(s, content_type.clone())?;
|
let filename = file_name(s, content_type.clone())?;
|
||||||
|
|
||||||
|
@ -799,7 +807,7 @@ impl UploadManager {
|
||||||
loop {
|
loop {
|
||||||
debug!("hash -> alias save loop");
|
debug!("hash -> alias save loop");
|
||||||
let db = self.inner.db.clone();
|
let db = self.inner.db.clone();
|
||||||
let id = web::block(move || db.generate_id()).await?.to_string();
|
let id = web::block(move || db.generate_id()).await??.to_string();
|
||||||
|
|
||||||
let key = alias_key(&hash.inner, &id);
|
let key = alias_key(&hash.inner, &id);
|
||||||
let main_tree = self.inner.main_tree.clone();
|
let main_tree = self.inner.main_tree.clone();
|
||||||
|
@ -808,13 +816,13 @@ impl UploadManager {
|
||||||
let res = web::block(move || {
|
let res = web::block(move || {
|
||||||
main_tree.compare_and_swap(key, None as Option<sled::IVec>, Some(alias2.as_bytes()))
|
main_tree.compare_and_swap(key, None as Option<sled::IVec>, Some(alias2.as_bytes()))
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
if res.is_ok() {
|
if res.is_ok() {
|
||||||
let alias_tree = self.inner.alias_tree.clone();
|
let alias_tree = self.inner.alias_tree.clone();
|
||||||
let key = alias_id_key(&alias);
|
let key = alias_id_key(&alias);
|
||||||
debug!("Saving alias -> id mapping");
|
debug!("Saving alias -> id mapping");
|
||||||
web::block(move || alias_tree.insert(key.as_bytes(), id.as_bytes())).await?;
|
web::block(move || alias_tree.insert(key.as_bytes(), id.as_bytes())).await??;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -834,10 +842,14 @@ impl UploadManager {
|
||||||
) -> Result<String, UploadError> {
|
) -> Result<String, UploadError> {
|
||||||
use rand::distributions::{Alphanumeric, Distribution};
|
use rand::distributions::{Alphanumeric, Distribution};
|
||||||
let mut limit: usize = 10;
|
let mut limit: usize = 10;
|
||||||
let rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
loop {
|
loop {
|
||||||
debug!("Alias gen loop");
|
debug!("Alias gen loop");
|
||||||
let s: String = Alphanumeric.sample_iter(rng).take(limit).collect();
|
let s: String = Alphanumeric
|
||||||
|
.sample_iter(&mut rng)
|
||||||
|
.take(limit)
|
||||||
|
.map(char::from)
|
||||||
|
.collect();
|
||||||
let alias = file_name(s, content_type.clone())?;
|
let alias = file_name(s, content_type.clone())?;
|
||||||
|
|
||||||
let res = self.save_alias(hash, &alias).await?;
|
let res = self.save_alias(hash, &alias).await?;
|
||||||
|
@ -866,7 +878,7 @@ impl UploadManager {
|
||||||
let res = web::block(move || {
|
let res = web::block(move || {
|
||||||
tree.compare_and_swap(alias.as_bytes(), None as Option<sled::IVec>, Some(vec))
|
tree.compare_and_swap(alias.as_bytes(), None as Option<sled::IVec>, Some(vec))
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
if res.is_err() {
|
if res.is_err() {
|
||||||
warn!("Duplicate alias");
|
warn!("Duplicate alias");
|
||||||
|
|
|
@ -199,7 +199,7 @@ pub(crate) async fn validate_image(
|
||||||
drop(entered);
|
drop(entered);
|
||||||
Ok(content_type) as Result<mime::Mime, UploadError>
|
Ok(content_type) as Result<mime::Mime, UploadError>
|
||||||
})
|
})
|
||||||
.await?;
|
.await??;
|
||||||
|
|
||||||
Ok(content_type)
|
Ok(content_type)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue