google / google/gnostic

protoc-gen-openapi: path parameters are repeated in the body when using `body: "*"`

Open
#323 5 comments 6 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.