grpc-ecosystem/grpc-gateway

[protoc-gen-openapiv2] Incorrectly generated OpenAPIv2 spec when using field_behaviour annotation

Open

#3 058 ouverte le 12 déc. 2022

Voir sur GitHub
 (10 commentaires) (0 réactions) (0 assignés)Go (2 250 forks)batch import
bughelp wantedopenapi

Métriques du dépôt

Stars
 (16 971 stars)
Métriques de merge PR
 (Merge moyen 1j 4h) (141 PRs mergées en 30 j)

Description

🐛 Bug Report

This is almost exactly the same error as in #1937:

With the introduction of https://github.com/grpc-ecosystem/grpc-gateway/pull/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

Guide contributeur