danielgtaylor / danielgtaylor/huma

[question/feature]: Is configuring multiple media types on request/response for the same operation possible?

Open
#864 1 comment 2 reactions 0 assignees View on GitHub
question
Dominant language
Go
Stars
4.4k
Forks
285
Avg merge
40m
Merged PRs (30d)
1

Description

Hi there!

I have a question/feature request.

I want to achieve the state where a single operation has multiple media types on request and response, and the exact type that's going to be used ( for unmarshalling the request/marshalling the response ) is decided in the negotiation phase ( with `Content-Type`/`Accept` headers ).

**Example**
Let's say we've got an operation `UserCreate` with `POST /users` path.

We define two versions of the `User` types.

`UserV1` with media type: `application/vnd.custom.user+json;version=1`

```go
type UserV1 struct {
FirstName string `json:"first_name" required:"true" doc:"The user's first name."`
LastName string `json:"last_name" required:"true" doc:"The user's last name."`
Email string `json:"email" required:"true" doc:"The user's email address."`
}
```

`UserV2` with media type: `application/vnd.custom.user+json;version=2`
```go
type UserV2 struct {
FirstName string `json:"first_name" required:"true" doc:"The user's first name."`
Age int `json:"age,omitempty" doc:"The user's age."`
}
```

`Input/Output` types
```go
type InputV1 struct {
Body struct {
User UserV1 `json:"user" required:"true" doc:"The user data."`
}
}

type InputV2 struct {
Body struct {
User UserV2 `json:"user" required:"true" doc:"The user data."`
}
}

type OutputV1 struct {
Body struct {
User UserV1 `json:"user" doc:"The user data."`
}
}

type OutputV2 struct {
Body struct {
User UserV2 `json:"created_user" doc:"The user data."`
}
}
```

They are **backward-incompatible** with each other, and we want to serve both versions.

**OAS**
From the OAS perspective, it would be smth like this:

```yaml
...
openapi: 3.1.0
paths:
/user:
post:
requestBody:
content:
application/vnd.custom.user+json;version=1:
schema:
$ref: "#/components/schemas/InputV1"
application/vnd.custom.user+json;version=2:
schema:
$ref: "#/components/schemas/InputV2"
responses:
"200":
content:
application/vnd.custom.user+json;version=1:
schema:
$ref: "#/components/schemas/OutputV1"
application/vnd.custom.user+json;version=2:
schema:
$ref: "#/components/schemas/OutputV2"
...
```

**Question**

Is there a way to define such an operation in the current Huma state and get versioning out of the box with all the Huma features ( OAS generation, validation, and so on )?

For example:
- A client sends `Content-type: application/vnd.custom.user+json;version=1` and `Accept: application/vnd.custom.user+json;version=1` and Huma validates and processes the request against `UserV1` type and uses it for the response.
- A client sends `Content-type: application/vnd.custom.user+json;version=2` and `Accept: application/vnd.custom.user+json;version=2` and Huma validates and processes the request against `UserV2` type and uses it for the response.
- A client sends `Content-type: application/json` and `Accept: application/json`, and Huma validates and processes the request against the default type ( e.g., `UserV2` ) and uses it for the response.

Thank you in advance.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.