Skip to main content

max / makenotwork

server: fix duplicate /api/openapi.json route panic The Swagger UI wiring (6e247eb) registered the OpenAPI spec at /api/openapi.json, which already had a hand-rolled route, so axum panicked "Overlapping method route" at build_app time — cascading every integration test. Point SwaggerUi at /api-docs/openapi.json (outside the /api/docs UI base, idiomatic) and leave the public /api/openapi.json endpoint intact. Adds a DB-free regression test mirroring the lib.rs merge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-09 02:34 UTC
Commit: 7b0637ebeff10c5070af3c325f96d89836c2b01b
Parent: 3a82fde
2 files changed, +17 insertions, -1 deletion
@@ -215,7 +215,7 @@ pub fn build_app(
215 215 .route("/api/openapi.json", axum::routing::get(openapi::openapi_json))
216 216 .merge(
217 217 utoipa_swagger_ui::SwaggerUi::new("/api/docs")
218 - .url("/api/openapi.json", <openapi::ApiDoc as utoipa::OpenApi>::openapi()),
218 + .url("/api-docs/openapi.json", <openapi::ApiDoc as utoipa::OpenApi>::openapi()),
219 219 )
220 220 .nest_service(
221 221 "/static",
@@ -153,4 +153,20 @@ mod tests {
153 153 assert!(paths.contains_key(p), "openapi spec is missing path {p}");
154 154 }
155 155 }
156 +
157 + /// Regression (v0.10.14): the hand-rolled `/api/openapi.json` route and the
158 + /// SwaggerUi mount must serve the spec at *distinct* paths. Reusing the same
159 + /// path makes axum panic ("Overlapping method route") at `build_app` time,
160 + /// which cascades every integration test that boots the app. This mirrors the
161 + /// wiring in `lib.rs`; building the router here is DB-free and fails fast if
162 + /// the two paths ever collide again.
163 + #[test]
164 + fn openapi_route_and_swagger_ui_do_not_collide() {
165 + let _app: axum::Router = axum::Router::new()
166 + .route("/api/openapi.json", axum::routing::get(openapi_json))
167 + .merge(
168 + utoipa_swagger_ui::SwaggerUi::new("/api/docs")
169 + .url("/api-docs/openapi.json", ApiDoc::openapi()),
170 + );
171 + }
156 172 }