juhaku / utoipa

Simple, Fast, Code first and Compile time generated OpenAPI documentation for Rust
Apache License 2.0
2.23k stars 173 forks source link

Auto collect schemas recursively from usages #1065

Open juhaku opened 5 days ago

juhaku commented 5 days ago

Description

Currently all schemas need to be manually listed to the OpenApi via #[openapi(components(schemas(...)))] or manually by adding them directly to the OpenApi. While this is fine, it gets burdensome for large projects and is prone to errors and in reality is not feasible in long run.

Solution

Allow utoipa to automatically collect schemas recursively within types that implement ToSchema trait (by derive) and all usages e.g. when type implementing ToSchema is defined as a request body or response body.

This does not change the fact that still handlers need to manually added to the schema either via #[openapi(paths(...))] or by other means.

Tasks

Closes #1025 Closes #465

Fixes #692

Relates #662 #591 #965 #779

leebenson commented 1 day ago

This is an incredible addition, thanks for your hard work 👍🏻

Migrating from Poem to Axum, the single biggest issue is runtime mismatch of schema types and actual types used in practice. It's easy to return a Json<ThingA> in Axum and forget to update the relevant utoipa::path responses definition to match

To that end, Is the plan to incorporate full type inference -- e.g. path/params, return types, etc from usage? Or would it still be necessary after this round to manually decorate utoipa::path with params(), body = <ReturnType>, etc?

Either way -- this is a great step forward, thank you.

juhaku commented 3 hours ago

Migrating from Poem to Axum, the single biggest issue is runtime mismatch of schema types and actual types used in practice. It's easy to return a Json in Axum and forget to update the relevant utoipa::path responses definition to match

That's true, it has been an issue for too long, though with the 5.0.0 it will recognize the types and if something does not exist, it will fail with compile error. Moreover if you happen to rename a type, it will get renamed in #[utoipa::path(...)] responses as well (same goes for request bodies as they are now linked with correct spans).

To that end, Is the plan to incorporate full type inference -- e.g. path/params, return types, etc from usage? Or would it still be necessary after this round to manually decorate utoipa::path with params(), body = , etc?

Yes, this round does not yet infer response body from return types. There has actually been a hidden feature flag auto_into_responses which should do something like that, but that is highly experimental and is for change in future. Adding such support with certain precepts is quite straight forward e.g. It will recognize Json<T> return type to 200 application/json of T and Result<T, E>, 200 of T and 500 of E. But since in rust it is also possible with many frameworks directly return an impl Trait for such cases the auto inference would not work.

This is something that most likely will be added after the 5.0.0 release. I will see further down the road when such feature will be added nonetheless.

For what comes to the params inference. For axum and actix-web that actually is possible, though not planned as of yet. Nevertheless the requirement for that is that the params will be always either wrapped with Path<T> or Query<T> in order to recognize the type of the parameters. Headers would be still necessary to list in params(...)

leebenson commented 2 hours ago

Love it, thanks @juhaku!