Added timeouts and a struct for empty response
This commit is contained in:
		
							
								
								
									
										8
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -321,9 +321,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "cc" | name = "cc" | ||||||
| version = "1.1.12" | version = "1.1.13" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "68064e60dbf1f17005c2fde4d07c16d8baa506fd7ffed8ccab702d93617975c7" | checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "jobserver", |  "jobserver", | ||||||
|  "libc", |  "libc", | ||||||
| @@ -1051,9 +1051,9 @@ dependencies = [ | |||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "libc" | name = "libc" | ||||||
| version = "0.2.155" | version = "0.2.156" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" | checksum = "a5f43f184355eefb8d17fc948dbecf6c13be3c141f20d834ae842193a448c72a" | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "libm" | name = "libm" | ||||||
|   | |||||||
| @@ -48,6 +48,7 @@ tower = { version = "0.4" } | |||||||
| tower-http = { version = "0.5", features = [ | tower-http = { version = "0.5", features = [ | ||||||
|     "compression-full", |     "compression-full", | ||||||
|     "sensitive-headers", |     "sensitive-headers", | ||||||
|  |     "timeout", | ||||||
|     "trace", |     "trace", | ||||||
|     "util", |     "util", | ||||||
| ] } | ] } | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ pub async fn delete( | |||||||
|     Query(params): Query<Params>, |     Query(params): Query<Params>, | ||||||
|     State(state): State<AppState>, |     State(state): State<AppState>, | ||||||
|     claims: Claims, |     claims: Claims, | ||||||
| ) -> GeneralResult<StatusCode> { | ) -> GeneralResult<EmptyResponse> { | ||||||
|     db::file::get_permissions(params.file_id, claims.user_id, &state.pool) |     db::file::get_permissions(params.file_id, claims.user_id, &state.pool) | ||||||
|         .await |         .await | ||||||
|         .can_write_guard()?; |         .can_write_guard()?; | ||||||
| @@ -24,5 +24,5 @@ pub async fn delete( | |||||||
|         .await |         .await | ||||||
|         .handle_internal("Error deleting the file")?; |         .handle_internal("Error deleting the file")?; | ||||||
|  |  | ||||||
|     Ok(StatusCode::NO_CONTENT) |     Ok(EmptyResponse) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ pub async fn modify( | |||||||
|     State(state): State<AppState>, |     State(state): State<AppState>, | ||||||
|     claims: Claims, |     claims: Claims, | ||||||
|     mut multipart: Multipart, |     mut multipart: Multipart, | ||||||
| ) -> GeneralResult<StatusCode> { | ) -> GeneralResult<EmptyResponse> { | ||||||
|     db::file::get_permissions(params.file_id, claims.user_id, &state.pool) |     db::file::get_permissions(params.file_id, claims.user_id, &state.pool) | ||||||
|         .await |         .await | ||||||
|         .can_write_guard()?; |         .can_write_guard()?; | ||||||
| @@ -52,5 +52,5 @@ pub async fn modify( | |||||||
|         .await |         .await | ||||||
|         .handle_internal("Error updating the file")?; |         .handle_internal("Error updating the file")?; | ||||||
|  |  | ||||||
|     Ok(StatusCode::NO_CONTENT) |     Ok(EmptyResponse) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,9 +36,19 @@ async fn create_file( | |||||||
|     pool: &Pool, |     pool: &Pool, | ||||||
| ) -> anyhow::Result<Uuid> { | ) -> anyhow::Result<Uuid> { | ||||||
|     let (file_id, file) = storage.create().await?; |     let (file_id, file) = storage.create().await?; | ||||||
|     let (hash, size) = crate::FileStorage::write_to_file(file, field).await?; |     let result = async { | ||||||
|     db::file::insert(file_id, parent_folder, file_name, size, hash, pool).await?; |         let (hash, size) = crate::FileStorage::write_to_file(file, field).await?; | ||||||
|     Ok(file_id) |         db::file::insert(file_id, parent_folder, file_name, size, hash, pool).await?; | ||||||
|  |         anyhow::Result::Ok(()) | ||||||
|  |     } | ||||||
|  |     .await; | ||||||
|  |     match result { | ||||||
|  |         Ok(()) => Ok(file_id), | ||||||
|  |         Err(err) => { | ||||||
|  |             let _ = storage.delete(file_id).await; | ||||||
|  |             Err(err) | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| async fn parse_field( | async fn parse_field( | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ pub async fn delete( | |||||||
|     State(state): State<AppState>, |     State(state): State<AppState>, | ||||||
|     claims: Claims, |     claims: Claims, | ||||||
|     Query(params): Query<Params>, |     Query(params): Query<Params>, | ||||||
| ) -> GeneralResult<()> { | ) -> GeneralResult<EmptyResponse> { | ||||||
|     let root = db::folder::get_root(claims.user_id, &state.pool) |     let root = db::folder::get_root(claims.user_id, &state.pool) | ||||||
|         .await |         .await | ||||||
|         .handle_internal("Error getting the root folder")?; |         .handle_internal("Error getting the root folder")?; | ||||||
| @@ -31,5 +31,7 @@ pub async fn delete( | |||||||
|             Ok(()) |             Ok(()) | ||||||
|         }) |         }) | ||||||
|         .await |         .await | ||||||
|         .handle_internal("Error deleting the fodler") |         .handle_internal("Error deleting the fodler")?; | ||||||
|  |  | ||||||
|  |     Ok(EmptyResponse) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ pub async fn delete( | |||||||
|     State(pool): State<Pool>, |     State(pool): State<Pool>, | ||||||
|     claims: Claims, |     claims: Claims, | ||||||
|     Query(params): Query<Params>, |     Query(params): Query<Params>, | ||||||
| ) -> GeneralResult<StatusCode> { | ) -> GeneralResult<EmptyResponse> { | ||||||
|     if params.user_id != claims.user_id { |     if params.user_id != claims.user_id { | ||||||
|         db::folder::get_permissions(params.folder_id, claims.user_id, &pool) |         db::folder::get_permissions(params.folder_id, claims.user_id, &pool) | ||||||
|             .await |             .await | ||||||
| @@ -21,5 +21,5 @@ pub async fn delete( | |||||||
|         .await |         .await | ||||||
|         .handle_internal("Error deleting the permissions")?; |         .handle_internal("Error deleting the permissions")?; | ||||||
|  |  | ||||||
|     Ok(StatusCode::NO_CONTENT) |     Ok(EmptyResponse) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ pub async fn set( | |||||||
|     claims: Claims, |     claims: Claims, | ||||||
|     State(pool): State<Pool>, |     State(pool): State<Pool>, | ||||||
|     Json(params): Json<Params>, |     Json(params): Json<Params>, | ||||||
| ) -> GeneralResult<StatusCode> { | ) -> GeneralResult<EmptyResponse> { | ||||||
|     let root = db::folder::get_root(claims.user_id, &pool) |     let root = db::folder::get_root(claims.user_id, &pool) | ||||||
|         .await |         .await | ||||||
|         .handle_internal("Error getting the root folder")?; |         .handle_internal("Error getting the root folder")?; | ||||||
| @@ -53,5 +53,5 @@ pub async fn set( | |||||||
|     .await |     .await | ||||||
|     .handle_internal("Error writing to the database")?; |     .handle_internal("Error writing to the database")?; | ||||||
|  |  | ||||||
|     Ok(StatusCode::NO_CONTENT) |     Ok(EmptyResponse) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,14 +1,19 @@ | |||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
| use crate::prelude::*; | use crate::prelude::*; | ||||||
|  |  | ||||||
| pub async fn delete( | pub async fn delete( | ||||||
|     State(AppState { pool, ref storage }): State<AppState>, |     State(AppState { pool, ref storage }): State<AppState>, | ||||||
|     claims: Claims, |     claims: Claims, | ||||||
| ) -> GeneralResult<()> { | ) -> GeneralResult<EmptyResponse> { | ||||||
|  |     tokio::time::sleep(Duration::from_secs(100)).await; | ||||||
|     db::users::delete_user(claims.user_id, &pool) |     db::users::delete_user(claims.user_id, &pool) | ||||||
|         .try_for_each_concurrent(5, |file_id| async move { |         .try_for_each_concurrent(5, |file_id| async move { | ||||||
|             let _ = storage.delete(file_id).await; |             let _ = storage.delete(file_id).await; | ||||||
|             Ok(()) |             Ok(()) | ||||||
|         }) |         }) | ||||||
|         .await |         .await | ||||||
|         .handle_internal("Error deleting the user") |         .handle_internal("Error deleting the user")?; | ||||||
|  |  | ||||||
|  |     Ok(EmptyResponse) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -4,10 +4,8 @@ mod endpoints; | |||||||
| mod errors; | mod errors; | ||||||
| mod file_storage; | mod file_storage; | ||||||
| mod prelude; | mod prelude; | ||||||
|  | mod util; | ||||||
|  |  | ||||||
| use std::{env, net::Ipv4Addr}; |  | ||||||
|  |  | ||||||
| use axum::Router; |  | ||||||
| use file_storage::FileStorage; | use file_storage::FileStorage; | ||||||
|  |  | ||||||
| type Pool = sqlx::postgres::PgPool; | type Pool = sqlx::postgres::PgPool; | ||||||
| @@ -63,6 +61,8 @@ fn init_tracing() { | |||||||
|  |  | ||||||
| #[tokio::main] | #[tokio::main] | ||||||
| async fn main() -> anyhow::Result<()> { | async fn main() -> anyhow::Result<()> { | ||||||
|  |     use std::{env, net::Ipv4Addr}; | ||||||
|  |  | ||||||
|     if env::var("RUST_BACKTRACE").is_err() { |     if env::var("RUST_BACKTRACE").is_err() { | ||||||
|         env::set_var("RUST_BACKTRACE", "1"); |         env::set_var("RUST_BACKTRACE", "1"); | ||||||
|     } |     } | ||||||
| @@ -124,7 +124,7 @@ async fn shutdown_signal() { | |||||||
|     ctrl_c.await; |     ctrl_c.await; | ||||||
| } | } | ||||||
|  |  | ||||||
| fn app(state: AppState) -> Router { | fn app(state: AppState) -> axum::Router { | ||||||
|     use axum::{ |     use axum::{ | ||||||
|         extract::DefaultBodyLimit, |         extract::DefaultBodyLimit, | ||||||
|         handler::Handler as _, |         handler::Handler as _, | ||||||
| @@ -137,6 +137,7 @@ fn app(state: AppState) -> Router { | |||||||
|         users, |         users, | ||||||
|     }; |     }; | ||||||
|     use tower_http::{ |     use tower_http::{ | ||||||
|  |         timeout::TimeoutLayer, | ||||||
|         trace::{MakeSpan, TraceLayer}, |         trace::{MakeSpan, TraceLayer}, | ||||||
|         ServiceBuilderExt as _, |         ServiceBuilderExt as _, | ||||||
|     }; |     }; | ||||||
| @@ -160,19 +161,22 @@ fn app(state: AppState) -> Router { | |||||||
|     const TEN_GIBIBYTES: usize = 10 * 1024 * 1024 * 1024; |     const TEN_GIBIBYTES: usize = 10 * 1024 * 1024 * 1024; | ||||||
|     let body_limit = DefaultBodyLimit::max(TEN_GIBIBYTES); |     let body_limit = DefaultBodyLimit::max(TEN_GIBIBYTES); | ||||||
|  |  | ||||||
|     let middleware = tower::ServiceBuilder::new() |     let timeout = TimeoutLayer::new(std::time::Duration::from_secs(10)); | ||||||
|  |  | ||||||
|  |     let common_middleware = tower::ServiceBuilder::new() | ||||||
|         .sensitive_headers([header::AUTHORIZATION, header::COOKIE]) |         .sensitive_headers([header::AUTHORIZATION, header::COOKIE]) | ||||||
|         .layer(TraceLayer::new_for_http().make_span_with(SpanMaker)) |         .layer(TraceLayer::new_for_http().make_span_with(SpanMaker)) | ||||||
|         .compression(); |         .compression(); | ||||||
|  |  | ||||||
|     Router::new() |     let file_router = axum::Router::new().route( | ||||||
|         .route( |         "/", | ||||||
|             "/files", |         get(file::download::download) | ||||||
|             get(file::download::download) |             .post(file::upload::upload.layer(body_limit.clone())) | ||||||
|                 .post(file::upload::upload.layer(body_limit.clone())) |             .delete(file::delete::delete.layer(timeout)) | ||||||
|                 .delete(file::delete::delete) |             .patch(file::modify::modify.layer(body_limit.clone())), | ||||||
|                 .patch(file::modify::modify.layer(body_limit)), |     ); | ||||||
|         ) |  | ||||||
|  |     let general_router = axum::Router::new() | ||||||
|         .route( |         .route( | ||||||
|             "/folders", |             "/folders", | ||||||
|             get(folder::list::list) |             get(folder::list::list) | ||||||
| @@ -200,6 +204,11 @@ fn app(state: AppState) -> Router { | |||||||
|         .route("/users/search", get(users::search::search)) |         .route("/users/search", get(users::search::search)) | ||||||
|         .route("/users/register", post(users::register::register)) |         .route("/users/register", post(users::register::register)) | ||||||
|         .route("/users/authorize", post(users::login::login)) |         .route("/users/authorize", post(users::login::login)) | ||||||
|         .layer(middleware) |         .layer(timeout); | ||||||
|  |  | ||||||
|  |     axum::Router::new() | ||||||
|  |         .nest("/files", file_router) | ||||||
|  |         .nest("/", general_router) | ||||||
|  |         .layer(common_middleware) | ||||||
|         .with_state(state) |         .with_state(state) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ pub(crate) use crate::{ | |||||||
|     auth::Claims, |     auth::Claims, | ||||||
|     db::{self, permissions::PermissionExt as _}, |     db::{self, permissions::PermissionExt as _}, | ||||||
|     errors::{ErrorHandlingExt as _, GeneralError, GeneralResult, ItemNotFoundExt as _}, |     errors::{ErrorHandlingExt as _, GeneralError, GeneralResult, ItemNotFoundExt as _}, | ||||||
|  |     util::EmptyResponse, | ||||||
|     AppState, Pool, |     AppState, Pool, | ||||||
| }; | }; | ||||||
| pub use axum::{ | pub use axum::{ | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								src/util.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/util.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | use axum::response::IntoResponse; | ||||||
|  |  | ||||||
|  | use crate::prelude::*; | ||||||
|  |  | ||||||
|  | pub struct EmptyResponse; | ||||||
|  |  | ||||||
|  | impl IntoResponse for EmptyResponse { | ||||||
|  |     fn into_response(self) -> axum::response::Response { | ||||||
|  |         StatusCode::NO_CONTENT.into_response() | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user