grpc-ecosystem / grpc-gateway

gRPC to JSON proxy generator following the gRPC HTTP spec
https://grpc-ecosystem.github.io/grpc-gateway/
BSD 3-Clause "New" or "Revised" License
18.27k stars 2.25k forks source link

Incorrect google.protobuf.Empty representation with oneof in GET request #4758

Open lo00l opened 2 months ago

lo00l commented 2 months ago

🐛 Bug Report

Hi guys,

I have the following files

AdminAPI.proto:

syntax = "proto3";
option go_package = "./admin";

package admin;

import "google/protobuf/empty.proto";

service AdminService {
  rpc GetInstruments(GetInstrumentsRequest) returns (InstrumentList);
}

message InstrumentNameList {
  repeated string names = 1;
}

message GetInstrumentsRequest {
  oneof instrument_name_filter {
    google.protobuf.Empty all_instrument_names = 1;
    InstrumentNameList instrument_name_list = 2;
  }
}

message InstrumentList {
  repeated Instrument instruments = 1;
}

message Instrument {
  // long definition here
}

grpc_api_configuration.yaml:

type: google.api.Service
config_version: 3

http:
  rules:
    - selector: admin.AdminService.GetInstruments
      get: /v1/instruments

buf.gen.yaml:

version: v1
plugins:
  - plugin: go
    out: gen
    opt:
      - paths=source_relative
  - plugin: go-grpc
    out: gen
    opt:
      - paths=source_relative
  - plugin: grpc-gateway
    out: gen
    opt:
      - paths=source_relative
      - grpc_api_configuration=grpc_api_configuration.yaml
  - plugin: openapiv2
    out: docs
    opt:
      - grpc_api_configuration=grpc_api_configuration.yaml
      - output_format=yaml

After generating code with buf generate I get the following in my swagger:

paths:
  /v1/instruments:
    get:
      operationId: AdminService_GetInstruments
      responses:
        "200":
          description: A successful response.
          schema:
            $ref: '#/definitions/adminInstrumentList'
        default:
          description: An unexpected error response.
          schema:
            $ref: '#/definitions/rpcStatus'
      parameters:
        - name: allInstrumentNames
          in: query
          required: false
          type: object
        - name: instrumentNameList.names
          in: query
          required: false
          type: array
          items:
            type: string
          collectionFormat: multi
      tags:
        - AdminService

Seems it's impossible to provide allInstrumentNames in query. I tried different options, but always get an error

{
    "code": 3,
    "message": "parsing field \"all_instrument_names\": unsupported message type: \"google.protobuf.Empty\"",
    "details": []
}

Underlying gRPC service expects whether all_instrument_names or instrument_name_list to be filled, and we cannot change it.

If proto service method accepts just google.protobuf.Empty, everything works fine since REST server doesn't except any query parameters.

Also, if I change method to POST, everything becomes ok with the following request:

{
    "allInstrumentNames": {}
}

So are there any ways to fix it?

Expected behavior

There is a way to pass google.protobuf.Empty struct in query parameter.

Actual Behavior

REST server returns error

{
    "code": 3,
    "message": "parsing field \"all_instrument_names\": unsupported message type: \"google.protobuf.Empty\"",
    "details": []
}

Your Environment

grpc-gateway version is v2.22.0

johanbrandhorst commented 2 months ago

I don't know of any way to accomplish this, no.