Skip to content

ogen-go/protoc-gen-oas

protoc-gen-oas Go Reference codecov experimental

protoc-gen-oas is protoc plugin for generate OpenAPI v3.x.x from proto files.

Install

go install github.com/ogen-go/protoc-gen-oas/cmd/protoc-gen-oas@latest

Usage

protoc --oas_out=. service.proto

Features

Generate OpenAPI

Path param

syntax = "proto3";

package service.v1;

import "google/api/annotations.proto";

option go_package = "service/v1;service";

service Service {
  rpc GetItem(GetItemRequest) returns (Item) {
    option (google.api.http) = {
      get: "/api/v1/items/{id}" // <--
    };
  }
}

message GetItemRequest {
  string id = 1; // <--
}

message Item {
  string id = 1;
  string name = 2;
}
openapi: 3.1.0
info:
  title: ""
  version: ""
paths:
  /api/v1/items/{id}:
    get:
      operationId: getItem
      parameters:
        - name: id       # <--
          in: path       # <--
          required: true # <--
          schema:        # <--
            type: string # <--
      responses:
        "200":
          description: service.v1.Service.GetItem response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Item'
components:
  schemas:
    Item:
      type: object
      properties:
        id:
          type: string
        name:
          type: string

Query param

syntax = "proto3";

package service.v1;

import "google/api/annotations.proto";

option go_package = "service/v1;service";

service Service {
  rpc GetItems(GetItemsRequest) returns (GetItemsResponse) {
    option (google.api.http) = {
      get: "/api/v1/items"
    };
  }
}

message GetItemsRequest {
  int32 limit = 1;  // <--
  int32 offset = 2; // <--
}

message GetItemsResponse {
  repeated Item items = 1;
  int32 total_count = 2;
}

message Item {
  string id = 1;
  string name = 2;
}
openapi: 3.1.0
info:
  title: ""
  version: ""
paths:
  /api/v1/items:
    get:
      operationId: getItems
      parameters:
        - name: limit     # <--
          in: query       # <--
          schema:         # <--
            type: integer # <--
            format: int32 # <--
        - name: offset    # <--
          in: query       # <--
          schema:         # <--
            type: integer # <--
            format: int32 # <--
      responses:
        "200":
          description: service.v1.Service.GetItems response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetItemsResponse'
components:
  schemas:
    GetItemsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
        totalCount:
          type: integer
          format: int32
    Item:
      type: object
      properties:
        id:
          type: string
        name:
          type: string

Mark field as required

syntax = "proto3";

package service.v1;

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

option go_package = "service/v1;service";

service Service {
  rpc CreateItem(CreateItemRequest) returns (CreateItemResponse) {
    option (google.api.http) = {
      post: "/api/v1/items"
      body: "*"
    };
  }
}

message CreateItemRequest {
  string name = 1 [(google.api.field_behavior) = REQUIRED]; // <--
}

message CreateItemResponse {
  string id = 1 [(google.api.field_behavior) = REQUIRED]; // <--
}
openapi: 3.1.0
info:
  title: ""
  version: ""
paths:
  /api/v1/items:
    post:
      operationId: createItem
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateItemRequest'
        required: true
      responses:
        "200":
          description: service.v1.Service.CreateItem response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateItemResponse'
components:
  schemas:
    CreateItemRequest:
      type: object
      properties:
        name:
          type: string
      required: # <--
        - name  # <--
    CreateItemResponse:
      type: object
      properties:
        id:
          type: string
      required: # <--
        - id    # <--

Mark field as deprecated

syntax = "proto3";

package service.v1;

import "google/api/annotations.proto";

option go_package = "service/v1;service";

service Service {
  rpc GetItems(GetItemsRequest) returns (GetItemsResponse) {
    option (google.api.http) = {
      get: "/api/v1/items"
    };
  }
}

message GetItemsRequest {
  int32 limit = 1;
  int32 offset = 2 [deprecated = true]; // <--
}

message GetItemsResponse {
  repeated Item items = 1;
  int32 total_count = 2;
}

message Item {
  string id = 1;
  string name = 2 [deprecated = true]; // <--
}
openapi: 3.1.0
info:
  title: ""
  version: ""
paths:
  /api/v1/items:
    get:
      operationId: getItems
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            format: int32
        - name: offset       # <--
          in: query          # <--
          schema:            # <--
            type: integer    # <--
            format: int32    # <--
            deprecated: true # <--
      responses:
        "200":
          description: service.v1.Service.GetItems response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetItemsResponse'
components:
  schemas:
    GetItemsResponse:
      type: object
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/Item'
        totalCount:
          type: integer
          format: int32
    Item:
      type: object
      properties:
        id:
          type: string
        name:              # <--
          type: string     # <--
          deprecated: true # <--

Snake case

syntax = "proto3";

package service.v1;

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

option go_package = "service/v1;service";

service Service {
  rpc DeleteItem(DeleteItemRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/api/v1/items/{item_id}"
      body: "*"
    };
  }
}

message DeleteItemRequest {
  string item_id = 1 [json_name = "item_id"]; // <--
}
openapi: 3.1.0
info:
  title: ""
  version: ""
paths:
  /api/v1/items/{item_id}:
    delete:
      operationId: deleteItem
      parameters:
        - name: item_id  # <--
          in: path       # <--
          required: true # <--
          schema:        # <--
            type: string # <--
      responses:
        "200":
          description: service.v1.Service.DeleteItem response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Empty'
components:
  schemas:
    Empty:
      type: object

Set field format

syntax = "proto3";

package service.v1;

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

option go_package = "service/v1;service";

service Service {
  rpc GetItem(GetItemRequest) returns (Item) {
    option (google.api.http) = {
      get: "/api/v1/items/{id}"
    };
  }
}

message GetItemRequest {
  string id = 1 [(google.api.field_info).format = UUID4]; // <--
}

message Item {
  string id = 1 [(google.api.field_info).format = UUID4]; // <--
  string name = 2;
}
openapi: 3.1.0
info:
  title: ""
  version: ""
paths:
  /api/v1/items/{id}:
    get:
      operationId: getItem
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid # <--
      responses:
        "200":
          description: service.v1.Service.GetItem response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Item'
components:
  schemas:
    Item:
      type: object
      properties:
        id:
          type: string
          format: uuid # <--
        name:
          type: string