@@ -22,6 +22,8 @@ use axum::{
2222use prometheus:: { Encoder , Registry , TextEncoder } ;
2323use std:: net:: SocketAddr ;
2424use tracing:: { info, info_span, Instrument } ;
25+ use utoipa:: OpenApi ;
26+ use utoipa_swagger_ui:: SwaggerUi ;
2527
2628use crate :: auth:: AuthConfig ;
2729use crate :: logging:: new_request_id;
@@ -47,6 +49,7 @@ pub async fn serve(listen: String, registry: Registry, limiter: RateLimiter) ->
4749 let nonce_cache = NonceCache :: new ( replay_config) ;
4850
4951 let app = Router :: new ( )
52+ . merge ( SwaggerUi :: new ( "/swagger-ui" ) . url ( "/api-docs/openapi.json" , ApiDoc :: openapi ( ) ) )
5053 . route ( "/metrics" , get ( metrics_handler) )
5154 . route ( "/health" , get ( health_handler) )
5255 . route ( "/ready" , get ( ready_handler) )
@@ -209,6 +212,7 @@ mod tests {
209212
210213 let state = AppState { registry } ;
211214 Router :: new ( )
215+ . merge ( SwaggerUi :: new ( "/swagger-ui" ) . url ( "/api-docs/openapi.json" , ApiDoc :: openapi ( ) ) )
212216 . route ( "/metrics" , get ( metrics_handler) )
213217 . route ( "/health" , get ( health_handler) )
214218 . with_state ( state)
@@ -360,4 +364,19 @@ mod tests {
360364 . unwrap ( ) ;
361365 assert_eq ! ( response. status( ) , StatusCode :: OK ) ;
362366 }
367+
368+ #[ tokio:: test]
369+ async fn test_swagger_ui_returns_non_404 ( ) {
370+ let app = make_app ( ) ;
371+ let response = app
372+ . oneshot (
373+ Request :: builder ( )
374+ . uri ( "/swagger-ui/" )
375+ . body ( Body :: empty ( ) )
376+ . unwrap ( ) ,
377+ )
378+ . await
379+ . unwrap ( ) ;
380+ assert_ne ! ( response. status( ) , StatusCode :: NOT_FOUND ) ;
381+ }
363382}
0 commit comments