use std::sync::Arc; use axum::{ http::{StatusCode, Uri}, middleware::map_request_with_state, response::IntoResponse, }; use axum_extra::routing::RouterExt; use tower_http::cors::CorsLayer; use crate::state::AppState; use self::jwt::authenticate; mod healthcheck; mod jwt; mod login; mod register; mod user; #[tracing::instrument] pub fn init_router(state: Arc) -> axum::Router { axum::Router::new() .typed_get(user::User::get) .typed_get(login::Logout::get) .route_layer(map_request_with_state(state.clone(), authenticate)) .typed_get(healthcheck::HealthCheck::get) .typed_get(user::UserUuid::get) .typed_post(register::Register::post) .typed_post(login::Login::post) .layer(CorsLayer::permissive()) .fallback(fallback) .with_state(state) } pub async fn fallback(uri: Uri) -> impl IntoResponse { (StatusCode::NOT_FOUND, format!("Route not found: {uri}")) } #[cfg(test)] mod tests { use super::*; use axum::{ body::Body, http::{Request, StatusCode}, }; use sqlx::PgPool; use tower::ServiceExt; const JWT_SECRET: &str = "test-jwt-secret-token"; type TestResult> = std::result::Result; #[sqlx::test] async fn test_route_not_found(pool: PgPool) -> TestResult { let state = Arc::new(AppState { pool, jwt_secret: JWT_SECRET.to_string(), }); let router = init_router(state.clone()); let request = Request::builder() .uri("/does-not-exist") .body(Body::empty())?; let response = router.oneshot(request).await?; assert_eq!(StatusCode::NOT_FOUND, response.status()); Ok(()) } }