grpc-gateway: Merging swagger specs fails to use rpc comments

I have two proto files:

a.proto:

syntax = "proto3";

package api.v1;

import "google/api/annotations.proto";

// A is a service for handling Foo stuff.
service A {
  // List all Foos
  //
  // Returns a (possibly paginated) list of all foo resources on success.
  rpc ListFoos (ListFoosRequest) returns (ListFoosResponse) {
    option (google.api.http) = { get: "/v1/foos" };
  }
}

// The ListFoos request message.
message ListFoosRequest {}

// The ListFoos response message.
message ListFoosResponse {}

b.proto:

syntax = "proto3";

package api.v1;

import "google/api/annotations.proto";

// B is a service for handling Bar stuff.
service B {
  // List all Bars
  //
  // Returns a (possibly paginated) list of all bar resources on success.
  rpc ListBars (ListBarsRequest) returns (ListBarsResponse) {
    option (google.api.http) = { get: "/v1/bars" };
  }
}

// The ListBars request message.
message ListBarsRequest {}

// The ListBars response message.
message ListBarsResponse {}

I tried to create a single swagger spec by using the allow_merge option. However, the generator removes some of the protobuf comments which get transformed into the endpoint description.

Steps you follow to reproduce the error:

  1. Grab the provided protobuf file a.proto and b.proto
  2. Generate the swagger spec without merging:
    protoc -I=. \
            -I=$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway \
            -I=$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
            --swagger_out=logtostderr=true:. \
            a.proto b.proto
    
  3. Generate the swagger spec with merging:
    protoc -I=. \
            -I=$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway \
            -I=$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
            --swagger_out=logtostderr=true,allow_merge=true:. \
            a.proto b.proto
    

What did you expect to happen instead:

Take a look at the separate specifications, the protobuf comments got transformed into endpoint descriptions:

a.swagger.json:

{
  "swagger": "2.0",
  "info": {
    "title": "a.proto",
    "version": "version not set"
  },
  "schemes": [
    "http",
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/v1/foos": {
      "get": {
        "summary": "List all Foos",
        "description": "Returns a (possibly paginated) list of all foo resources on success.",
        "operationId": "ListFoos",
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/v1ListFoosResponse"
            }
          }
        },
        "tags": [
          "A"
        ]
      }
    }
  },
  "definitions": {
    "v1ListFoosResponse": {
      "type": "object",
      "description": "The ListFoos response message."
    }
  }
}

b.swagger.json:

{
  "swagger": "2.0",
  "info": {
    "title": "b.proto",
    "version": "version not set"
  },
  "schemes": [
    "http",
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/v1/bars": {
      "get": {
        "summary": "List all Bars",
        "description": "Returns a (possibly paginated) list of all bar resources on success.",
        "operationId": "ListBars",
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/v1ListBarsResponse"
            }
          }
        },
        "tags": [
          "B"
        ]
      }
    }
  },
  "definitions": {
    "v1ListBarsResponse": {
      "type": "object",
      "description": "The ListBars response message."
    }
  }
}

This isn’t true for the merged specification:

apidocs.swagger.json:

{
  "swagger": "2.0",
  "info": {
    "title": "a.proto",
    "version": "version not set"
  },
  "schemes": [
    "http",
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/v1/bars": {
      "get": {
        "operationId": "ListBars",
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/v1ListBarsResponse"
            }
          }
        },
        "tags": [
          "B"
        ]
      }
    },
    "/v1/foos": {
      "get": {
        "summary": "List all Foos",
        "description": "Returns a (possibly paginated) list of all foo resources on success.",
        "operationId": "ListFoos",
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/v1ListFoosResponse"
            }
          }
        },
        "tags": [
          "A"
        ]
      }
    }
  },
  "definitions": {
    "v1ListBarsResponse": {
      "type": "object",
      "description": "The ListBars response message."
    },
    "v1ListFoosResponse": {
      "type": "object",
      "description": "The ListFoos response message."
    }
  }
}

This spec misses the description of the /v1/bars endpoint.

What’s your theory on why it isn’t working:

There seems to be a bug in the code which merges the two specs. I this its located around here: https://github.com/grpc-ecosystem/grpc-gateway/blob/a5b66c16bab6156b1cc525e76159bdff463123ba/protoc-gen-swagger/genswagger/generator.go#L93-L97

If merged to the leader, the code does not copy the comments.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 20 (5 by maintainers)

Commits related to this issue

Most upvoted comments

This is apparently still broken