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

Derive Responses implementation #412

Closed
2 tasks done
juhaku opened this issue Dec 12, 2022 · 0 comments · Fixed by #416, #419, #433 or #443
Closed
2 tasks done

Derive Responses implementation #412

juhaku opened this issue Dec 12, 2022 · 0 comments · Fixed by #416, #419, #433 or #443
Labels
enhancement New feature or request

Comments

@juhaku
Copy link
Owner

juhaku commented Dec 12, 2022

Background:
At the moment there is no support for deriving responses from Rust types. And they need to either implemented manually via implementing trait such as ToResponse or IntoResponses.

Propsed syntax:
I am planning to implement roughly derive syntax below. This would to my knowledge get around the OpenAPI response needs that are currently implemented for tuples (some are not yet released).

IntoResponses would be implemented for enum what can list possible responses. And ToResponse can be implemented either for struct or for enum depeding on whether handler is able to return multiple kind of responses.

However one draw back I can think of this desing is that the enums there must use serde(untagged) attribute if one wishes only return the end type as reponse and not composed type all the way from first enum A(B(C))). Though is there a better way to do this?

/// This is a FooBar entity.
#[derive(ToSchema, ToResponse)]
#[response(content_type = [...], headers(...), example = ..., examples(...)]
struct FooBar {
  user_name: String,
  password: String
}

/// Success response with inlined to_schema type
#[derive(ToResponse)]
struct FooBarSuccess(#[to_schema] Vec<Foobar>);

#[derive(ToResponse)]
enum Person {
  #[response(example = ..., examples(...))]
  User(#[content("application/json-v1")] User),

  Admin(#[content("application/json-v2")] Admin)
}

#[derive(ToSchema)]
pub struct User {
  name: String
}

#[derive(ToSchema)]
pub struct Admin {
  nickname: String
}

#[derive(IntoResponses)]
enum MyResponses {
  /// This is the description for the response
  /// 
  /// Long description is supported.
  #[response(status = 200, example = ..., examples = ..., headers = ..., ...)]
  Ok(FooBar),
  
  /// Unit type response
  #[response(status = CREATED)]
  Created,
  
  /// This is not found response
  #[response(status = 404)]
  NotFound(#[ref_response] NotFoundResponse),

  /// Server error
  #[response(status = 500)] 
  ServerError(#[to_response] NotFoundResponse),

  /// Inlined response object
  #[response(status = 404)]
  BadRequest {
    value: String
  }
}

#[derive(IntoResponses)]
#[response(status = 200)]
struct PersonSuccessResponse {
  id: String
}

#[derive(IntoResponses)]
#[response(status = NOT_FOUND)]
struct NotFoundResponse(String);

#[derive(IntoResponses)]
#[response(status = INTERNAL_SERVER_ERROR)]
struct SystemError(#[to_schema] Error);

Highlevel tasks to do:

  • Implement ToResponse derive functionality
  • Implement IntoResponses derive funtionality

Questions:

The question is am I missing something? Should something be done differently? @kellpossible @jacob-pro @cemoktra

Related issues:

#300 #201 #106

@juhaku juhaku added the enhancement New feature or request label Dec 12, 2022
@juhaku juhaku moved this to In Progress in utoipa kanban Dec 21, 2022
@github-project-automation github-project-automation bot moved this from In Progress to Done in utoipa kanban Jan 12, 2023
@juhaku juhaku moved this from Done to Released in utoipa kanban Jan 29, 2023
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