juhaku/utoipa

Incomplete spec dump via `to_pretty_json` with auto registered schemas

Closed this issue · 2 comments

Calling openapi::OpenApi.to_pretty_json() produces an incomplete spec doc when used with schema auto-registration.

It's likely to trip people up following the readme example.

e.g. something basic like this:

#[derive(OpenApi)]
#[openapi(
    servers(
        (url = "http://localhost:3000", description = "Local Dev"),
        (url = "https://api.<remote-site>", description = "Remote API"),
    )
)]
pub struct ApiDoc;

Will produce this:

{
  "openapi": "3.1.0",
  "info": {
    "title": "server",
    "description": "",
    "license": {
      "name": ""
    },
    "version": "0.1.0"
  },
  "servers": [
    {
      "url": "http://localhost:3000",
      "description": "Local Dev"
    },
    {
      "url": "https://api.<remote-site>",
      "description": "Remote API"
    }
  ],
  "paths": {},
  "components": {}
}

A fix is to wrap in the router to ensure routes have been fully initialised:

let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi())
        .merge(api::routes())
        .split_for_parts()

... and then call api.to_pretty_json().

This is by design, though not sure whether this is actually a good design. But this is deliberate as I think there is no need to evaluate the all the variables from environment variables, over and over again when users call OpenApiRouter::new().

Yet we could create a function something like OpenApiRouter::from_env() for this purpose to deliberately instantiate a new instance of OpenApi with all variables resolved from the cargo environment variables.

Anyhow with_openapi(...) is there for that purpose because some information like the servers cannot be added via the router. This allows merging OpenAPIs from macro syntax with one in the router. Otherwise the servers need to be added manually after the .split_for_parts() call to the resulting OpenApi.

EDIT:

True the example in the README.md does not directly correlate behavior of utoipa-axum README.md example https://github.com/juhaku/utoipa/tree/master/utoipa-axum.

Perhaps I could change it the way that OpenApiRouter::default() would do what now the OpenApiRouter::new() does (creates completely empty OpenApi and then OpenApiRouter::new() would do the same as the #[derive(OpenApi)]

That sounds like a good default.

The way it worked previously was fine, when all schemas had to be manually registered. But with auto registration, it's a pretty easy footgun.

As always, thanks for the excellent work 👍🏻