Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 83 additions & 1 deletion docs/docs/mapping/customizing_openapi_output.md
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,88 @@ definitions:
type: string
```

### Deprecating parameters

{% endraw %}
With the `enable_field_deprecation` option, OpenAPI parameters will be marked as deprecated based on the protobuf `deprecated` field option. Allowed values are: `true`, `false`.

For example, if you are using `buf`:

```yaml
version: v1
plugins:
- name: openapiv2
out: .
opt:
- enable_field_deprecation=true
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=enable_field_deprecation=true ./path/to/file.proto
```

Input example:

```protobuf
message SearchRequest {
string legacy_filter = 1 [deprecated = true];
string query = 2;
}
```

Output (excerpt):

```yaml
paths:
/v1/search:
get:
parameters:
- name: legacy_filter
in: query
required: false
type: string
deprecated: true
- name: query
in: query
required: false
type: string
```

If you prefer to leave the protobuf definition active, you can use the `field_configuration.deprecated` annotation on the `openapiv2_field` option instead:

```protobuf
message SearchRequest {
string legacy_filter = 1 [
(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
description: "Legacy filter syntax. Prefer the new 'query' field."
field_configuration: { deprecated: true }
}
];
string query = 2;
}
```

This keeps the protobuf field untouched but still emits a deprecated parameter in the generated spec:

```yaml
paths:
/v1/search:
get:
parameters:
- name: legacy_filter
in: query
required: false
type: string
description: Legacy filter syntax. Prefer the new 'query' field.
deprecated: true
- name: query
in: query
required: false
type: string
```

If you set both the protobuf `deprecated = true` option and `field_configuration.deprecated`, the OpenAPI parameter is marked as deprecated regardless of the `enable_field_deprecation` option.


{% endraw %}
13 changes: 13 additions & 0 deletions internal/descriptor/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ type Registry struct {
// enableRpcDeprecation whether to process grpc method's deprecated option
enableRpcDeprecation bool

// enableFieldDeprecation whether to process proto field's deprecated option
enableFieldDeprecation bool

// expandSlashedPathPatterns, if true, for a path parameter carrying a sub-path, described via parameter pattern (i.e.
// the pattern contains forward slashes), this will expand the _pattern_ into the URI and will _replace_ the parameter
// with new path parameters inferred from patterns wildcards.
Expand Down Expand Up @@ -915,6 +918,16 @@ func (r *Registry) GetEnableRpcDeprecation() bool {
return r.enableRpcDeprecation
}

// SetEnableFieldDeprecation sets enableFieldDeprecation
func (r *Registry) SetEnableFieldDeprecation(enable bool) {
r.enableFieldDeprecation = enable
}

// GetEnableFieldDeprecation returns enableFieldDeprecation
func (r *Registry) GetEnableFieldDeprecation() bool {
return r.enableFieldDeprecation
}

func (r *Registry) SetExpandSlashedPathPatterns(expandSlashedPathPatterns bool) {
r.expandSlashedPathPatterns = expandSlashedPathPatterns
}
Expand Down
10 changes: 10 additions & 0 deletions protoc-gen-openapiv2/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def _run_proto_gen_openapi(
use_allof_for_refs,
disable_default_responses,
enable_rpc_deprecation,
enable_field_deprecation,
expand_slashed_path_patterns,
preserve_rpc_order,
generate_x_go_type):
Expand Down Expand Up @@ -155,6 +156,9 @@ def _run_proto_gen_openapi(
if enable_rpc_deprecation:
args.add("--openapiv2_opt", "enable_rpc_deprecation=true")

if enable_field_deprecation:
args.add("--openapiv2_opt", "enable_field_deprecation=true")

if expand_slashed_path_patterns:
args.add("--openapiv2_opt", "expand_slashed_path_patterns=true")

Expand Down Expand Up @@ -271,6 +275,7 @@ def _proto_gen_openapi_impl(ctx):
use_allof_for_refs = ctx.attr.use_allof_for_refs,
disable_default_responses = ctx.attr.disable_default_responses,
enable_rpc_deprecation = ctx.attr.enable_rpc_deprecation,
enable_field_deprecation = ctx.attr.enable_field_deprecation,
expand_slashed_path_patterns = ctx.attr.expand_slashed_path_patterns,
preserve_rpc_order = ctx.attr.preserve_rpc_order,
generate_x_go_type = ctx.attr.generate_x_go_type,
Expand Down Expand Up @@ -434,6 +439,11 @@ protoc_gen_openapiv2 = rule(
mandatory = False,
doc = "whether to process grpc method's deprecated option.",
),
"enable_field_deprecation": attr.bool(
default = False,
mandatory = False,
doc = "whether to process proto field's deprecated option.",
),
"expand_slashed_path_patterns": attr.bool(
default = False,
mandatory = False,
Expand Down
16 changes: 15 additions & 1 deletion protoc-gen-openapiv2/internal/genopenapi/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ func nestedQueryParams(message *descriptor.Message, field *descriptor.Field, pre
}
}

// verify if the field is deprecated, either via proto or annotation
protoDeprecated := field.GetOptions().GetDeprecated() && reg.GetEnableFieldDeprecation()
annotationDeprecated := getFieldConfiguration(reg, field).GetDeprecated()
deprecated := protoDeprecated || annotationDeprecated

param := openapiParameterObject{
Description: desc,
In: "query",
Expand All @@ -354,6 +359,7 @@ func nestedQueryParams(message *descriptor.Message, field *descriptor.Field, pre
Format: schema.Format,
Pattern: schema.Pattern,
Required: required,
Deprecated: deprecated,
UniqueItems: schema.UniqueItems,
extensions: schema.extensions,
Enum: schema.Enum,
Expand Down Expand Up @@ -1454,18 +1460,26 @@ func renderServices(services []*descriptor.Service, paths *openapiPathsObject, r
if regExp, ok := pathParamRegexpMap[parameterString]; ok {
pattern = regExp
}
if fc := getFieldConfiguration(reg, parameter.Target); fc != nil {
fc := getFieldConfiguration(reg, parameter.Target)
if fc != nil {
pathParamName := fc.GetPathParamName()
if pathParamName != "" && pathParamName != parameterString {
pathParamNames["{"+parameterString+"}"] = "{" + pathParamName + "}"
parameterString, _, _ = strings.Cut(pathParamName, "=")
}
}

// verify if the parameter is deprecated, either via proto or annotation
protoDeprecated := parameter.Target.GetOptions().GetDeprecated() && reg.GetEnableFieldDeprecation()
annotationDeprecated := fc.GetDeprecated()
deprecated := protoDeprecated || annotationDeprecated

parameters = append(parameters, openapiParameterObject{
Name: parameterString,
Description: desc,
In: "path",
Required: true,
Deprecated: deprecated,
Default: defaultValue,
// Parameters in gRPC-Gateway can only be strings?
Type: paramType,
Expand Down
Loading
Loading