tamasfe/aide

Broken URLs with trailing `/` due to `.nest()`

Opened this issue · 1 comments

This is a small reproducer of a problem we are facing in our code, where the use of .nest() leads to routes with a trailing / in the documentation but the URLs are only working without them.

Example

Apply the following patch/diff to the main.rs file in the axum example in the aide Github repository:

[nix-shell:~/code/other/aide]$ git diff
diff --git a/examples/example-axum/src/main.rs b/examples/example-axum/src/main.rs
index ac4f621..84ec2a7 100644
--- a/examples/example-axum/src/main.rs
+++ b/examples/example-axum/src/main.rs
@@ -33,11 +33,11 @@ async fn main() {
     let mut api = OpenApi::default();
 
     let app = ApiRouter::new()
-        .nest_api_service("/todo", todo_routes(state.clone()))
-        .nest_api_service("/docs", docs_routes(state.clone()))
+        .nest("/todo", todo_routes(state.clone()))
+        .nest("/docs", docs_routes(state.clone()))
         .finish_api_with(&mut api, api_docs)
-        .layer(Extension(Arc::new(api))) // Arc is very important here or you will face massive memory and performance issues
-        .with_state(state);
+        .layer(Extension(Arc::new(api))); // Arc is very important here or you will face massive memory and performance issues
+        //.with_state(state);
 
     println!("Example docs are accessible at http://127.0.0.1:3000/docs");

Resulting Documentation

After applying the diff above the app produces the following documentation:
documentation
Note that the --url parameters in the curl examples all end with a trailing /.

Broken POST example execution

The screenshot below illustrates that the POST method only works if we remove the trailing /, but if we copy the snippet from the documentation without modification we get a 404 NOT FOUND response.
post_request

Issue report

Above you can see that .nest() leads to misleading documentation and broken URLs.

We are currently using a workaround with .merge(), but it makes the code less readable, since we then need to include the base URL in the sub-router. We also figured that using .nest_api_service() like in the original example code enables URLs to work with and without the trailing /, but we don’t want that.

Is this known behavior or as we suspect a bug?

I too am seeing this issue. I'm not even sure it's an aide issue to be honest, as I believe it would happen with axum proper as well. Instantiating separate ApiRouter<()> with their own state (even if all the nested ones would ultimately have the same state) is a fine workaround, but it is more verbose than necessary in many cases.