protoc-gen-openapi: path parameters are repeated in the body when using `body: "*"`
- Dominant language
- Go
- Stars
- 2.3k
- Forks
- 279
- PR merge metrics
- No merged PRs in 30d
Description
When a request has both path parameters and `body: "*"`, the path parameters are being repeated in the body in the resulting OpenAPI spec.
Note how the following example has `name` both in `parameters` and `requestBody` in the generated openapi spec.
**protobuf:**
```protobuf
service LibraryService {
rpc MergeShelves(MergeShelvesRequest) return (Shelf) {
option (google.api.http) = {
post: "/v1/{name=shelves/*}:merge"
body: "*"
};
}
}
// Describes the shelf being removed (other_shelf_name) and updated
// (name) in this merge.
message MergeShelvesRequest {
// The name of the shelf we're adding books to.
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference).type = "Shelf"
];
// The name of the shelf we're removing books from and deleting.
string other_shelf_name = 2 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference).type = "Shelf"
];
}
```
**openapi spec:**
```yaml
paths:
/v1/shelves/{shelf}:merge:
post:
tags:
- LibraryService
description: |-
Merges two shelves by adding all books from the shelf named
`other_shelf_name` to shelf `name`, and deletes
`other_shelf_name`. Returns the updated shelf.
The book ids of the moved books may not be the same as the original books.
Returns NOT_FOUND if either shelf does not exist.
This call is a no-op if the specified shelves are the same.
operationId: LibraryService_MergeShelves
parameters:
- name: shelf
in: path
description: The shelf id.
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MergeShelvesRequest'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Shelf'
components:
schemas:
MergeShelvesRequest:
required:
- name
- other_shelf_name
type: object
properties:
name:
type: string
description: The name of the shelf we're adding books to.
other_shelf_name:
type: string
description: The name of the shelf we're removing books from and deleting.
description: Describes the shelf being removed (other_shelf_name) and updated (name) in this merge.
```
According to [use_wildcard_in_body](https://cloud.google.com/endpoints/docs/grpc/transcoding#use_wildcard_in_body), every field **not bound by the path template** should be mapped to the request body.
So fields that are bound by the path template shouldn't be in the request body.
**Proposal:**
In these cases, create a new schema named `{method_name}RequestBody` which doesn't contain the fields bound by the path:
```yaml
paths:
/v1/shelves/{shelf}:merge:
post:
tags:
- LibraryService
description: |-
Merges two shelves by adding all books from the shelf named
`other_shelf_name` to shelf `name`, and deletes
`other_shelf_name`. Returns the updated shelf.
The book ids of the moved books may not be the same as the original books.
Returns NOT_FOUND if either shelf does not exist.
This call is a no-op if the specified shelves are the same.
operationId: LibraryService_MergeShelves
parameters:
- name: shelf
in: path
description: The shelf id.
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MergeShelvesRequestBody'
required: true
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Shelf'
components:
schemas:
MergeShelvesRequestBody:
required:
- other_shelf_name
type: object
properties:
other_shelf_name:
type: string
description: The name of the shelf we're removing books from and deleting.
description: Describes the shelf being removed (other_shelf_name) and updated (name) in this merge.
```
There's a PR on my fork that implements this proposal: https://github.com/istvan-hevele/gnostic/pull/1
Contributor guide
Assessment
This issue has not been assessed yet.