nytimes / openapi2proto

A tool for generating Protobuf v3 schemas and gRPC service definitions from OpenAPI specifications
Apache License 2.0
964 stars 98 forks source link

`responses` not translated to proto #121

Closed Kaimaerah closed 4 years ago

Kaimaerah commented 4 years ago

I've come across an issue while trying to translate a swagger file with responses at the top level (see the bottom of https://swagger.io/docs/specification/2-0/describing-responses/) where the responses are simply dropped and the rpc call just returns empty.

Example: Swagger:

swagger: "2.0"

info:
  title: example
  description: An example API to demonstrate issue in responses
  version: 1.0.0
paths:
  /example:
    post:
      operationId: exampleOperation
      description: Example operation
      parameters:
        - in: body
          name: body
          schema:
            $ref: '#/definitions/ExampleRequest'
      responses:
        200:
          $ref: '#/responses/ExampleResponse'
        400:
          $ref: '#/responses/BadRequest'
definitions:
  ExampleRequest:
    type: object
    required:
      - example
    properties:
      example:
        type: string
responses:
  ExampleResponse:
    description: Example response
    schema:
      type: object
      properties:
        anotherExample:
          type: string
  BadRequest:
    description: Bad request

Expected proto:

syntax = "proto3";

package example;

message ExampleOperationRequest {
    ExampleRequest body = 1;
}

message ExampleRequest {
    string example = 1;
}

message ExampleResponse {
    string anotherExample = 1;
}

service ExampleService {
    // Example operation
    rpc ExampleOperation(ExampleOperationRequest) returns (ExampleResponse) {}
}

Generated proto:

syntax = "proto3";

package example;

import "google/protobuf/empty.proto";

message ExampleOperationRequest {
    ExampleRequest body = 1;
}

message ExampleRequest {
    string example = 1;
}

service ExampleService {
    // Example operation
    rpc ExampleOperation(ExampleOperationRequest) returns (google.protobuf.Empty) {}
}

I've worked around this by moving responses into definitions and inlined the response boilerplate onto each path but since this is part of the swagger spec, it should be supported

jprobinson commented 4 years ago

This is a great find, thanks @Kaimaerah,

I've just created a PR with a fix. Let me know if it meets your expectations.

snanurag commented 4 years ago

We are still facing this error.

Our swagger:

openapi: 3.0.0
info:
  version: 1.0.0

tags:
  - name: Multi-Cloud Organization
    description: APIs to manage Multi-Cloud Organizations

paths:
  ## Multi Cloud Organizations
  "/csp/mcm/api/v1/orgs/{orgId}/multi-cloud-orgs":
    post:
      tags:
        - Multi-Cloud Organization
      summary: Register a Multi-Cloud organization
      description: |
        Register a Multi-Cloud Organization

        <b>Authorization:</b>
        * csp:org_owner
      operationId: RegisterMultiCloudOrganization
      parameters:
        - name: orgId
          in: path
          required: true
          description: Parent CSP organization Id
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MultiCloudOrgRequest"
        description: Multi-Cloud org to register
        required: true
      responses:
        "200":
          description: Successfully registered Multi-Cloud org
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MultiCloudOrg"
  schemas:
    MultiCloudOrgRequest:
      type: object
      description: Multi-Cloud organization
      required:
        - cloudOrgId
        - name
        - cloudProvider
      properties:
        cloudOrgId:
          type: string
          description: Id of root account/org/tenant on cloud platform
        name:
          type: string
          description: Multi-Cloud organization name
        state:
          type: string
          enum:
            - MANAGED
            - UNMANAGED
          description: State of MultiCloud Org
        description:
          type: string
          description: Multi-Cloud org description
        cloudProvider:
          type: string
          enum:
            - AWS
            - AZURE
            - GCP
          description: CloudProvider could be AWS, GCP, AZURE
        attributes:
          $ref: "#/components/schemas/Attributes"
        tags:
          $ref: "#/components/schemas/Tags"
      example:
        cloudOrgId: 757224
        name: AWS-Root-Org
        cloudProvider: AWS
        state: MANAGED
        description: Developers Multi-Cloud Org
        tags:
          active: true
          dev: false
        attributes:
          externalID: aws-externalID

    MultiCloudOrg:
      type: object
      description: Multi-Cloud organization. It represents top level MasterAccount/Org/Tenant on cloud platform
      required:
        - id
        - cloudOrgId
        - name
        - cloudProvider
      properties:
        id:
          type: string
          description: Multi-Cloud organization Id (uuid) generated by SkyWalker. This is referred as 'multiCloudOrgId' in APIs path
        cloudOrgId:
          type: string
          description: Id of Multi-Cloud org on cloud platform
        name:
          type: string
          description: Multi-Cloud org name
        description:
          type: string
          description: Multi-Cloud org description
        cloudProvider:
          type: string
          enum:
            - AWS
            - AZURE
            - GCP
          description: CloudProvider could be AWS, GCP, AZURE
        state:
          type: string
          enum:
            - MANAGED
            - UNMANAGED
          description: State of MultiCloud Org
        tags:
          $ref: "#/components/schemas/Tags"
      example:
        id: 1f31641b-d805-4ebd-a1fd-7e684b6c601f
        cloudOrgId: 757224
        name: AWS-Root-Org
        cloudProvider: AWS
        description: Developers Multi-Cloud Org
        tags:
          active: true
          dev: false

Output is

syntax = "proto3";

package ;

import "google/api/annotations.proto";
import "google/protobuf/empty.proto";

message RegisterMultiCloudOrganizationRequest {
    // Parent CSP organization Id
    string orgId = 1;
}

service Service {
    // Register a Multi-Cloud organization
    // 
    // Register a Multi-Cloud Organization
    // 
    // <b>Authorization:</b>
    // * csp:org_owner
    rpc RegisterMultiCloudOrganization(RegisterMultiCloudOrganizationRequest) returns (google.protobuf.Empty) {
        option (google.api.http) = {
            post: "/csp/mcm/api/v1/orgs/{orgId}/multi-cloud-orgs"
        };
    }
}

It should not be Empty return from rpc.