Customizing OpenAPI Output
In proto comments
You can provide comments directly in your Protocol Buffer definitions and they will be translated into comments in the generated OpenAPI definitions:
message MyMessage {
// This comment will end up direcly in your Open API definition
string uuid = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The UUID field."}];
}
Using proto options
You can define options on your Protocol Buffer services, operations, messages, and field definitions to customize your Open API output. For instance, to customize the OpenAPI Schema Object for messages and fields:
import "protoc-gen-openapiv2/options/annotations.proto";
message ABitOfEverything {
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
json_schema: {
title: "A bit of everything"
description: "Intentionaly complicated message type to cover many features of Protobuf."
required: ["uuid", "int64_value", "double_value"]
}
external_docs: {
url: "https://github.com/grpc-ecosystem/grpc-gateway";
description: "Find out more about ABitOfEverything";
}
example: "{\"uuid\": \"0cf361e1-4b44-483d-a159-54dabdf7e814\"}"
};
string uuid = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The UUID field."}];
}
Operations can also be customized:
service ABitOfEverythingService {
rpc Delete(grpc.gateway.examples.internal.proto.sub2.IdMessage) returns (google.protobuf.Empty) {
option (google.api.http) = {
delete: "/v1/example/a_bit_of_everything/{uuid}"
};
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
security: {
security_requirement: {
key: "ApiKeyAuth";
value: {}
}
security_requirement: {
key: "OAuth2";
value: {
scope: "read";
scope: "write";
}
}
}
extensions: {
key: "x-irreversible";
value {
bool_value: true;
}
}
};
}
}
Please see this a_bit_of_everything.proto for examples of the options being used.
Using google.api.field_behavior
Google provides an field option for defining the behavior of fields that is also supported:
import "google/api/field_behavior.proto";
message MyMessage {
string a_required_field = 1 [(google.api.field_behavior) = REQUIRED];
}
The following options are used in the Open API output:
REQUIRED
- marks a field as requiredOUTPUT_ONLY
- marks a field as readonly
Google defines a couple of other options - OPTIONAL
, IMMUTABLE
, INPUT_ONLY
- that are not currently used. OPTIONAL
support is currently under discussion in this issue.
For IMMUTABLE
and INPUT_ONLY
fields, there is an open issue in the Open API specification for adding functionality for write-once or immutable fields to the spec.
Using go templates in proto file comments
Use Go templates in your proto file comments to allow more advanced documentation such as:
- Documentation about fields in the proto objects.
- Import the content of external files (such as Markdown).
How to use it
By default this function is turned off, so if you want to use it you have to add the use_go_templates
option:
--openapiv2_out . --openapiv2_opt use_go_templates=true
or:
--openapiv2_out=use_go_templates=true:.
Example script
Example of a bash script with the use_go_templates
flag set to true:
$ protoc -I. \
--go_out . --go-grpc_out . \
--grpc-gateway_out . --grpc-gateway_opt logtostderr=true \
--openapiv2_out . \
--openapiv2_opt logtostderr=true \
--openapiv2_opt use_go_templates=true \
path/to/my/proto/v1/myproto.proto
Example proto file
Example of a proto file with Go templates. This proto file imports documentation from another file, tables.md
:
service LoginService {
// Login
//
// {{.MethodDescriptorProto.Name}} is a call with the method(s) {{$first := true}}{{range .Bindings}}{{if $first}}{{$first = false}}{{else}}, {{end}}{{.HTTPMethod}}{{end}} within the "{{.Service.Name}}" service.
// It takes in "{{.RequestType.Name}}" and returns a "{{.ResponseType.Name}}".
//
// {{import "tables.md"}}
rpc Login (LoginRequest) returns (LoginReply) {
option (google.api.http) = {
post: "/v1/example/login"
body: "*"
};
}
}
message LoginRequest {
// The entered username
string username = 1;
// The entered password
string password = 2;
}
message LoginReply {
// Whether you have access or not
bool access = 1;
}
The content of tables.md
:
## {{.RequestType.Name}}
| Field ID | Name | Type | Description |
| ----------- | --------- | --------------------------------------------------------- | ---------------------------- | {{range .RequestType.Fields}}
| {{.Number}} | {{.Name}} | {{if eq .Label.String "LABEL_REPEATED"}}[]{{end}}{{.Type}} | {{fieldcomments .Message .}} | {{end}}
## {{.ResponseType.Name}}
| Field ID | Name | Type | Description |
| ----------- | --------- | ---------------------------------------------------------- | ---------------------------- | {{range .ResponseType.Fields}}
| {{.Number}} | {{.Name}} | {{if eq .Label.String "LABEL_REPEATED"}}[]{{end}}{{.Type}} | {{fieldcomments .Message .}} | {{end}}
OpenAPI output
SwaggerUI
This is how the OpenAPI file would be rendered in Swagger UI.
Postman
This is how the OpenAPI file would be rendered in Postman.
For a more detailed example of a proto file that has Go, templates enabled, see the examples.