diff --git a/Cargo.lock b/Cargo.lock index 4acc510..a0c4b44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3583,20 +3583,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "tower-http" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" -dependencies = [ - "bitflags 2.10.0", - "bytes", - "http", - "pin-project-lite", - "tower-layer", - "tower-service", -] - [[package]] name = "tower-layer" version = "0.3.3" @@ -4293,7 +4279,6 @@ dependencies = [ "serde_json", "tokio", "tower", - "tower-http", "tracing", "tracing-subscriber", ] diff --git a/apps/api/Cargo.toml b/apps/api/Cargo.toml index e57bfb0..55b3f06 100644 --- a/apps/api/Cargo.toml +++ b/apps/api/Cargo.toml @@ -11,8 +11,7 @@ axum = { version = "0.8.7", features = ["form", "http1", "json", "matched-path", chrono = { version = "0.4.42", features = ["clock", "std", "oldtime", "wasmbind", "serde"] } config = { version = "0.15.19", features = ["toml", "json", "yaml", "ini", "ron", "json5", "convert-case", "async"] } tokio = { version = "1", features = ["fs", "io-util", "io-std", "macros", "net", "parking_lot", "process", "rt", "rt-multi-thread", "signal", "sync", "time", "tracing"] } -tower = { version = "0.5.2", features = ["tokio", "tracing"] } -tower-http = { version = "0.6.6" } +tower = { version = "0.5.2", features = ["tokio", "tracing", "timeout"] } tracing = { version = "0.1.41", features = ["std", "attributes"] } tracing-subscriber = { version = "0.3.20", features = ["smallvec", "fmt", "ansi", "tracing-log", "std", "chrono", "json", "serde", "serde_json", "time", "tracing"] } serde_json = { version = "1.0.145", features = ["std"] } diff --git a/apps/api/src/main.rs b/apps/api/src/main.rs index 6bcbb78..cb1256d 100644 --- a/apps/api/src/main.rs +++ b/apps/api/src/main.rs @@ -1,4 +1,5 @@ mod configs; +mod middlewares; mod routes; mod tasks; diff --git a/apps/api/src/middlewares.rs b/apps/api/src/middlewares.rs new file mode 100644 index 0000000..f47e3de --- /dev/null +++ b/apps/api/src/middlewares.rs @@ -0,0 +1,34 @@ +use axum::{ + BoxError, Router, + error_handling::HandleErrorLayer, + http::{Method, StatusCode, Uri}, +}; +use std::time::Duration; +use tower::{ServiceBuilder, timeout::TimeoutLayer}; + +use tracing::warn; + +pub const TIMEOUT_DURATION_SECS: u64 = 30; + +pub fn apply_root_middleware(router: Router) -> Router { + let timeout_layer = TimeoutLayer::new(Duration::from_secs(TIMEOUT_DURATION_SECS)); + + let service_builder = ServiceBuilder::new() + .layer(HandleErrorLayer::new(handle_timeout_error)) + .layer(timeout_layer); + + router.layer(service_builder) +} + +pub async fn handle_timeout_error( + method: Method, + uri: Uri, + // + err: BoxError, +) -> (StatusCode, String) { + warn!("`{method} {uri}` failed with {err}"); + ( + StatusCode::INTERNAL_SERVER_ERROR, + "Internal server error".to_string(), + ) +} diff --git a/apps/api/src/routes.rs b/apps/api/src/routes.rs index d202ce2..89328a2 100644 --- a/apps/api/src/routes.rs +++ b/apps/api/src/routes.rs @@ -1,8 +1,11 @@ use std::sync::Arc; -use axum::Router; +use axum::{Extension, Router}; use migration::sea_orm::DatabaseConnection; +use crate::middlewares; + +#[derive(Clone)] pub struct AppState { // TODO: remove dead_code allowances when fields are used #[allow(dead_code)] @@ -17,11 +20,12 @@ pub struct AppService { } pub fn get_root_router(state: impl Into>) -> Router { - let router = Router::new() - // TODO: Add routes - .with_state(state.into()); + let mut router = Router::new(); + + router = middlewares::apply_root_middleware(router); + + router = router.layer(Extension(state.into())); - #[allow(clippy::let_and_return)] router }