Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utoipa swagger bug on axum: the url option points to two different locations #964

Closed
Mek101 opened this issue Jun 27, 2024 · 2 comments
Closed
Labels
wontfix This will not be worked on

Comments

@Mek101
Copy link

Mek101 commented Jun 27, 2024

I build my swagger UI router like so

fn swagger_ui() -> axum::Router {
        utoipa_swagger_ui::SwaggerUi::new("/swagger-ui")
                .url("/openapi.json", ApiDoc::openapi())
                .into()
}

And then nest it in another router like this

axum::Router::new()
        .route("/v1/enabled_services", routing::get(other_stuff))
        .with_state(some_app_state)
        .nest("/v1/doc", swagger_ui())        // <----- HERE

Then when I try to access the url at /v1/doc/swagger-ui, the UI loads but it can't find the the json data.

swagger 404

This is because the json endpoint is actually in /v1/doc/openapi.json, while the UI is trying to load it from /openapi.json.

Is there a way to make the UI point to a user-configurable URL, which can be picked separately from .url("/openapi.json", ApiDoc::openapi())?

@juhaku
Copy link
Owner

juhaku commented Aug 19, 2024

It is possible if you provide a custom config for the Swagger UI. The Swagger UI must be let known of the location where the openapi.json is located at.

fn swagger_ui() -> axum::Router {
        let config = Config::from("/v1/doc/openapi.json"); // <-- let the Swagger UI know the openapi json location
        utoipa_swagger_ui::SwaggerUi::new("/swagger-ui")
                .url("/openapi.json", ApiDoc::openapi())
                .config(config)
                .into()
}
// and then the rest normally
axum::Router::new()
        .route("/v1/enabled_services", routing::get(other_stuff))
        .with_state(some_app_state)
        .nest("/v1/doc", swagger_ui())    

@juhaku
Copy link
Owner

juhaku commented Sep 15, 2024

To further elaborate why this is happening. When nest(...) is called with Swagger UI it will nest the Swagger UI router under the path provided with the nest() call. For convenience Swagger UI url(...) call will create handler to serve the openapi.json from the provided url and it will use the same url to configure the path the Swagger UI should look for openapi.json.

Now what it doesn't know is that if the Swagger UI is nested under axum Router it does not know that it is actually nested. Thus Swagger UI cannot know that the actual path for openapi.json is not just /openapi.json but actually /some/nested/path/not/known/by/swagger/openapi.json.

To fix this, one needs to override the url the Swagger UI will look for openapi.json file as shown above by the Config::from("/path/swagger-ui/should/look/for/openapi.json").

axum::Router::new()
       .route("/v1/enabled_services", routing::get(other_stuff))
       .with_state(some_app_state)
       .nest("/v1/doc", swagger_ui())        // <----- HERE

In order to support nesting Swagger UI directly without the Config::from would need some fundamental changes to how Swagger UI is setup which might complicate the basic usage of Swagger UI which is unwanted. As of now such changes are not planned but not excluded from future updates. Nevertheless at the moment the Config::from is sufficient enough and no further actions will be taken.

@juhaku juhaku closed this as completed Sep 15, 2024
@juhaku juhaku added the wontfix This will not be worked on label Sep 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants