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

Implement automatic schema collection for requests #1066

Merged
merged 1 commit into from
Sep 26, 2024

Conversation

juhaku
Copy link
Owner

@juhaku juhaku commented Sep 26, 2024

This PR implements functionality to recognize recursive schemas within types implementing ToSchema trait by (derive). These schema references will be collected to the single list of schemas which are added to the schema automatically from their usage point.

If schema is registered at schemas(MyType) for OpenApi then the type and it's schema references found recursively will be registered to the OpenApi.

If the type is defined in #[utoipa::path(request_body = ...)] the schema and it's recursively found schema references will be automatically added to the schema when the handler is registered to the OpenApi.

If the framework supports request body from http handler function arguments (like actix_web, axum) then the schema will be added to the OpenApi as well with recursively found schema references when the handler is registered to the OpenApi.

This commit also refactors the parsing for #[utoipa::path(request_body = ...)] Which enables the support for automatic schema reference recognition and collection. This also comes with the possibility to only add request_body(content_type = "my/type") without the schema if wanted. More over from now on the request_body supports defining multiple content objects allowing users to define multiple request body content's like the responses support.

Breaking changes

This request_body parsing is in over all breaking change and the changed spec need be checked from the docs or tests. In short the content_type = ... does not support anymore array syntax. E.g. content_type = [...] is not possible anymore. Instead to support multiple content types in request body on must define multiple content objects similar to responses.

 request_body(
    content(
        (Item = "content/type"),
        (Item = "content/type2"),
    )
 )

Example of supported syntax to demonstrate the automatic schema collecting from test_collect_schemas handler when registered to the OpenApi. Same way if Person was declared to OpenApi via schemas(Person) then Account would also get registered.

 #[derive(ToSchema)]
 struct Account {
     id: i32,
 }

 #[derive(ToSchema)]
 struct Person {
     name: String,
     account: Account,
 }

 #[utoipa::path(
     post,
     request_body = Person,
     path = "/test-collect-schemas",
     responses(
         (status = 200, description = "success response")
     ),
 )]
 async fn test_collect_schemas(_body: Person) -> &'static str {
     ""
 }

 #[derive(OpenApi)]
 #[openapi(paths(test_collect_schemas))]
 struct ApiDoc;

Fixes #692

Relates #662 #591 #965 #779

This PR implements functionality to recognize recursive schemas within
types implementing `ToSchema` trait by (derive). These schema references
will be collected to the single list of schemas which are added to the
schema automatically from their usage point.

If schema is registered at `schemas(MyType)` for `OpenApi` then the type
and it's schema references found recursively will be registered to the
`OpenApi`.

If the type is defined in `#[utoipa::path(request_body = ...)]` the
schema and it's recursively found schema references will be
automatically added to the schema when the handler is registered to the
`OpenApi`.

If the framework supports request body from http handler function
arguments (like `actix_web`, `axum`) then the schema will be added to
the `OpenApi` as well with recursively found schema references when the
handler is registered to the `OpenApi`.

This commit also refactors the parsing for `#[utoipa::path(request_body
= ...)]` Which enables the support for automatic schema reference
recognition and collection. This also comes with the possibility to only
add `request_body(content_type = "my/type")` without the schema if
wanted. More over from now on the `request_body` supports defining
multiple content objects allowing users to define multiple request body
content's like the responses support.

 ### Breaking changes

This `request_body` parsing is in over all breaking change and the
changed spec need be checked from the docs or tests. In short the
`content_type = ...` does not support anymore array syntax. E.g.
`content_type = [...]` is not possible anymore. Instead to support
multiple content types in request body on must define multiple content
objects similar to responses.
```text
 request_body(
    content(
        (Item = "content/type"),
        (Item = "content/type2"),
    )
 )
```

Example of supported syntax to demonstrate the automatic schema
collecting from `test_collect_schemas` handler when registered to the
`OpenApi`. Same way if `Person` was declared to `OpenApi` via
`schemas(Person)` then `Account` would also get registered.
```rust
 #[derive(ToSchema)]
 struct Account {
     id: i32,
 }

 #[derive(ToSchema)]
 struct Person {
     name: String,
     account: Account,
 }

 #[utoipa::path(
     post,
     request_body = Person,
     path = "/test-collect-schemas",
     responses(
         (status = 200, description = "success response")
     ),
 )]
 async fn test_collect_schemas(_body: Person) -> &'static str {
     ""
 }

 #[derive(OpenApi)]
 #[openapi(paths(test_collect_schemas))]
 struct ApiDoc;
```
@juhaku juhaku merged commit 5a06616 into master Sep 26, 2024
22 checks passed
@juhaku juhaku deleted the feature-auto-collect-schemas branch September 26, 2024 17:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Released
1 participant