Open Sh1nku opened 1 year ago
Minimal working example:
// src/main.rs
use axum::{routing::get, Router};
use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi;
#[utoipa::path(get, path = "/hello-world")]
pub async fn hello_world() -> &'static str {
"Hello, World!"
}
#[tokio::main]
async fn main() {
#[derive(OpenApi)]
#[openapi(paths(hello_world))]
struct ApiDoc;
let app = Router::new()
.merge(SwaggerUi::new("/").url("/openapi.json", ApiDoc::openapi()))
.route("/hello-world", get(hello_world));
axum::Server::bind(&"127.0.0.1:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
and
# Cargo.toml
[package]
name = "a"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = { version = "0.6.18" }
tokio = { version = "1.28.1", features = ["macros", "rt-multi-thread", "fs"] }
utoipa = { version = "3.3.0", features = ["axum_extras"] }
utoipa-swagger-ui = { version = "3.1.3", features = ["axum"] }
The Swagger UI is served on http://127.0.0.1:3000//
, but http://127.0.0.1:3000/
returns 303 See Other
with location: //
. Note that this does not count as a redirection and is not followed by user agents.
Using SwaggerUi::new("/")
or url("/openapi.json", ApiDoc::openapi())
result respectively in:
Paths must start with a `/`. Use "/" for root routes
and
Paths must start with a `/`
It's worse than just allowing to serve the Swagger UI at //
: utoipa-swagger-ui
actually captures everything under the provided path.
@juhaku, is there a plan to fix this? AFAICT, there's 2 issues here:
//
issue coupled with the lack of a redirect non-/
ending routes. Meaning, if we host Swagger UI on, say, /v1
, then visiting /v1
will produce a 404 because all static assets are loaded from ./*
(which in this case, would be root) -- but hosting on /v1/
also produces a 404, because Utoipa adds an implicit /
, making the full route /v1//*
.
- It's impossible to host on root, because of the greedy capture. It conflicts with any other GET route.
This is impossible to fix, since the Swagger UI is a dir with bunch of files so it needs to be a greedy capture in order to serve everything under the Swagger UI. It is same as effectively serving a static files assets IMO. If there is a way around this I am open for PRs and improvements.
- The // issue coupled with the lack of a redirect non-/ ending routes. Meaning, if we host Swagger UI on, say, /v1, then visiting /v1 will produce a 404 because all static assets are loaded from ./ (which in this case, would be root) -- but hosting on /v1/ also produces a 404, because Utoipa adds an implicit /, making the full route /v1//.
Maybe there is something that can be done to optimize the path but I am not able to focus on this at the moment.
If someone know how to improve this you can also submit a PR :slightly_smiling_face:
Seems that there is an problem when trying to host swagger-ui on the root URL with axum.
https://github.com/juhaku/utoipa/blob/970e10f4203edc8af68c78a009dbb8dc935703bb/utoipa-swagger-ui/src/axum.rs#L49-L57
A redirect from
/
to//
is created, and the other routes also become incorrect