Repository: grpc-ecosystem/grpc-gateway

Issue #3058: [protoc-gen-openapiv2] Incorrectly generated OpenAPIv2 spec when using field_behaviour annotation
Created: 2022-12-12T18:31:09Z
🐛 Bug Report
This is almost exactly the same error as in #1937:

With the introduction of #1806 rpc definitions definitions that have a non-wildcard body property now fail validation. The generated code breaks because it produces a swagger document whose body parameter is a reference to the request definition but also has a required entry in the object.
Note that this file swagger file failed npx @opernapitools/openapi-generator-cli generate with error saying that required is unexpected.

The #1937 is already resolved & closed but it seems this type of error was not resolved completely since I can reproduce it.
To Reproduce
I'm using Buf to deal with external dependencies (googleapis). But you should be able to reproduce it using only protoc, protoc-gen-openapiv2 and foo.proto, if you manually provide the googleapis.
Here's the whole Buf setup:
.
├── buf.gen.yaml
├── buf.work.yaml
└── proto
    ├── buf.lock
    ├── buf.yaml
    └── v1
        └── foo.proto

buf.gen.yaml
version: v1
managed:
  enabled: true
  go_package_prefix:
    default: github.com/foo
plugins:
  - name: openapiv2
    out: gen
buf.work.yaml
version: v1
directories:
  - proto
proto/buf.yaml
version: v1
deps:
  - buf.build/googleapis/googleapis
proto/buf.lock
Is generated by command:
cd proto && buf mod update
example content:
# Generated by buf. DO NOT EDIT.
version: v1
deps:
  - remote: buf.build
    owner: googleapis
    repository: googleapis
    commit: faacf837d7304c58b7c9020c7807fa6e
proto/v1/foo.proto
syntax = "proto3";

package v1;

import "google/api/annotations.proto";
import "google/api/field_behavior.proto";

message Foo {
}

message CreateFooRequest{
  Foo foo = 1 [(google.api.field_behavior) = REQUIRED];
}

service FooService {
  rpc CreateFoo (CreateFooRequest) returns (Foo) {
    option (google.api.http) = {
      post: "/v1/foos"
      body: "foo"
    };
  }
}
Finally, generate openapiv2 via buf command:
buf generate
(you should be also able to generate directly by using protoc but you have to provide the googleapis deps)
Expected behavior
gen/v1/foo.swagger.json
{
  "swagger": "2.0",
  "info": {
    "title": "v1/foo.proto",
    "version": "version not set"
  },
  "tags": [
    {
      "name": "FooService"
    }
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/v1/foos": {
      "post": {
        "operationId": "FooService_CreateFoo",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/v1Foo"
            }
          },
          "default": {
            "description": "An unexpected error response.",
            "schema": {
              "$ref": "#/definitions/rpcStatus"
            }
          }
        },
        "parameters": [
          {
            "name": "foo",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/v1Foo",
            }
          }
        ],
        "tags": [
          "FooService"
        ]
      }
    }
  },
  "definitions": {
    "protobufAny": {
      "type": "object",
      "properties": {
        "@type": {
          "type": "string"
        }
      },
      "additionalProperties": {}
    },
    "rpcStatus": {
      "type": "object",
      "properties": {
        "code": {
          "type": "integer",
          "format": "int32"
        },
        "message": {
          "type": "string"
        },
        "details": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/protobufAny"
          }
        }
      }
    },
    "v1Foo": {
      "type": "object"
    }
  }
}

Actual Behavior
gen/v1/foo.swagger.json
{
  "swagger": "2.0",
  "info": {
    "title": "v1/foo.proto",
    "version": "version not set"
  },
  "tags": [
    {
      "name": "FooService"
    }
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/v1/foos": {
      "post": {
        "operationId": "FooService_CreateFoo",
        "responses": {
          "200": {
            "description": "A successful response.",
            "schema": {
              "$ref": "#/definitions/v1Foo"
            }
          },
          "default": {
            "description": "An unexpected error response.",
            "schema": {
              "$ref": "#/definitions/rpcStatus"
            }
          }
        },
        "parameters": [
          {
            "name": "foo",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/v1Foo",
              "required": [ <-- THIS SHOULDN'T BE HERE
                "foo"           
              ]
            }
          }
        ],
        "tags": [
          "FooService"
        ]
      }
    }
  },
  "definitions": {
    "protobufAny": {
      "type": "object",
      "properties": {
        "@type": {
          "type": "string"
        }
      },
      "additionalProperties": {}
    },
    "rpcStatus": {
      "type": "object",
      "properties": {
        "code": {
          "type": "integer",
          "format": "int32"
        },
        "message": {
          "type": "string"
        },
        "details": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/protobufAny"
          }
        }
      }
    },
    "v1Foo": {
      "type": "object"
    }
  }
}

Your Environment
buf version: 1.10.0
protoc-gen-openapiv2 version: v2.14.0
go version: go1.19.1 darwin/amd64

Duplicate issue #3265: protoc-gen-openapiv2 not working for `google.api.field_behavior` as expected
Created: 2023-03-28T08:28:18Z
🐛 Bug Report
According to this, protoc-gen-openapiv2 can mark fields as required based on the google.api.field_behavior field option. But when I tried doing so, it does not mark the fields as required.
Note that the fields are only marked as required if I use specify them as required by using grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema.
To Reproduce
My proto file myproto.proto
syntax = "proto3";

option go_package = "tms.com/test";

import "protoc-gen-openapiv2/options/annotations.proto";
import "google/api/field_behavior.proto";
import "google/api/annotations.proto";

message TestMessage {
  // Works if I uncomment this block.
  // option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
  //  json_schema: { required: [ "my_required_field" ] }
  //};

  int32 my_optional_field = 1;
  int32 my_required_field = 2 [(google.api.field_behavior) = REQUIRED];
}
...

Generate spec via:
protoc -I /opt/include -I . --openapiv2_out=logtostderr=true,json_names_for_fields=true:gen myproto.proto
Expected behavior
...
    "TestMessage": {
      "type": "object",
      "properties": {
        "myOptionalField": {
          "type": "integer",
          "format": "int32"
        },
        "myRequiredField": {
          "type": "integer",
          "format": "int32"
        }
      },
      "required": [
        "my_required_field"
      ]
    },
...

Actual Behavior
...
    "TestMessage": {
      "type": "object",
      "properties": {
        "myOptionalField": {
          "type": "integer",
          "format": "int32"
        },
        "myRequiredField": {
          "type": "integer",
          "format": "int32"
        }
      }
    },
...

Your Environment
$ protoc --version
libprotoc 3.21.6

What am I missing? Is google.api.field_behavior not supported by protoc-gen-openapiv2?

Closing comment (2023-03-28T15:41:55Z): Hi. Sorry that you ran into this, but you are indeed right that this is not currently supported. This issue is a dupe of #3058.