Skip to content

Repository files navigation

protoc-gen-connect-openapi

Go Go Report Card Go Reference

Generate OpenAPI v3.1 from protobuf matching the Connect protocol. With these OpenAPI specs, you can:

  • Generate Documentation (Elements, redoc, etc.)
  • Generate HTTP Clients for places where you cannot use gRPC (openapi-generator)
  • Datasource for automated endpoint validation/security testing
  • Datasource for monitoring dashboards
  • Many other things

Features:

Example Pipeline:

flowchart LR

protobuf(Protobuf) -->|protoc-gen-connect-openapi| openapi(OpenAPI)
openapi -->|elements| elements(API Documentation)
openapi -->|openapi-generator| other-languages(Other Language Support)
openapi -->|???| ???(Other Tooling!)
click elements "https://github.com/stoplightio/elements" _blank
click openapi-generator "https://github.com/OpenAPITools/openapi-generator" _blank
Loading

Why?

Connect makes your gRPC service look and feel like a normal HTTP/JSON API, at least for non-streaming RPC calls. It does this without an extra network hop and an extra proxy layer because the same Connect server can speak the Connect, gRPC and gRPC-Web protocols in a single port.

This is what a GET request looks like. Note that GET requests are available for methods with an option of idempotency_level=NO_SIDE_EFFECTS.

> GET /connectrpc.greet.v1.GreetService/Greet?encoding=json&message=%7B%22name%22%3A%22Buf%22%7D HTTP/1.1
> Host: demo.connectrpc.com

< HTTP/1.1 200 OK
< Content-Type: application/json
<
< {"greeting": "Hello, Buf!"}

We can document this API as if it's a real JSON/HTTP API... because it is, and the gRPC "flavor" isn't so noticable due to Connect. With protoc-gen-connect-openapi you can declare your API using protobuf, serve it using gRPC and Connect and fully document it without the API consumers ever knowing what protobuf is or how to read it.

Install

Binaries

You can download pre-built binaries from the Github releases page.

asdf

$ asdf plugin add protoc-gen-connect-openapi https://github.com/sudorandom/asdf-protoc-gen-connect-openapi.git
$ asdf list all protoc-gen-connect-openapi
$ asdf install protoc-gen-connect-openapi latest
$ asdf global protoc-gen-connect-openapi latest

Using Go

It isn't recommended, but you can also install directly using Go:

go install github.com/sudorandom/protoc-gen-connect-openapi@latest
protoc-gen-connect-openapi --version

Or you can actually use go run directly from buf.gen.yaml, if that's the protobuf generation tool that you're using:

version: v2
plugins:
  - local: ["go", "run", "github.com/sudorandom/protoc-gen-connect-openapi@latest"]
    out: gen

Using "go tool" support

If you are already using Go, it may make sense to also use the new "go tool" support added in Go 1.24:

go get -tool github.com/sudorandom/protoc-gen-connect-openapi@latest
go tool protoc-gen-connect-openapi --version

Again, you can run the plugin in this mode with buf generate using this buf.gen.yaml file:

version: v2
plugins:
  - local: ["go", "tool", "protoc-gen-connect-openapi"]
    out: gen

Usage

Using buf

This plugin is now available as a remote plugin in the BSR.

version: v2
plugins:
  - remote: buf.build/community/sudorandom-connect-openapi:v0.19.1
    out: gen
    opt:
    - base=example.base.yaml

If you use this config you don't actually need to do the install steps above. See the buf page on remote plugins for more information on this.

Of course, you can also use it locally, with a buf.gen.yaml that looks like this:

version: v2
plugins:
  - local: protoc-gen-connect-openapi
    out: gen
    opt:
    - base=example.base.yaml

And then run buf generate. See the documentation on buf generate for more help.

With protoc

This tool works as a plugin for protoc. Here's a basic example:

protoc internal/converter/fixtures/helloworld.proto --connect-openapi_out=gen

With the JSON format:

protoc internal/converter/fixtures/helloworld.proto \
    --connect-openapi_out=gen \
--connect-openapi_opt=format=json

With a base OpenAPI file and without all of the streaming content type:

protoc internal/converter/fixtures/helloworld.proto \
    --connect-openapi_out=gen \
    --connect-openapi_opt=base=example.base.yaml,content-types=json

See protoc --help for more protoc options.

JSON Schema output

With format=jsonschema, the plugin renders standalone JSON Schema (draft 2020-12) documents instead of OpenAPI. Each proto file produces a {file}.jsonschema.json bundle (or one merged document when path= is set) with every message and enum under $defs:

version: v2
plugins:
  - local: protoc-gen-connect-openapi
    out: gen
    opt:
    - format=jsonschema

This mode renders just the schemas: no HTTP paths and no Connect-specific schemas (connect.error, protocol headers, etc.) are included, and internal references use #/$defs/ instead of #/components/schemas/. Options that shape schemas still apply, including trim-unused-types, services, allowed-visibilities, with-proto-names, fully-qualified-message-names, and all Protovalidate and Gnostic message/field annotations. The base and override options are not supported in this mode because those files are OpenAPI documents.

Protovalidate Support

protoc-gen-connect-openapi also has support for many Protovalidate annotations. Note that not every Protovalidate constraint translates clearly to OpenAPI.

See the Protovalidate documentation page for more information

gRPC-Gateway annotations

protoc-gen-connect-openapi also has support for the gRPC-Gateway annotations provided by the google/api/annotations.proto.

See the gRPC-Gateway annotation documentation page for more information

Gnostic Support

protoc-gen-connect-openapi also has support for the OpenAPI v3 annotations provided by the google/gnostic project.

See the gnostic documentation page for more information

Options

Option Values Description
allow-get - For methods that have IdempotencyLevel=IDEMPOTENT, this option will generate HTTP GET requests instead of POST.
asyncapi-path {filepath} Output filepath for the generated AsyncAPI v3.1 specification. If provided, the generator will write an AsyncAPI document documenting any client, server, or bidirectional streaming endpoints as WebSocket channels (conforming to the routing of grpc-websocket-proxy).
asyncapi-channel-template {template} Template pattern to customize the channel path mapping for WebSocket endpoints in the AsyncAPI spec. Available placeholders: {package}, {service}, {method}. Defaults to /ws/{package}.{service}/{method}.
base {filepath} The path to a base OpenAPI file to populate fields that this tool doesn't populate. This option does not work when used with the remote plugin.
content-types json;proto Semicolon-separated content types to generate requests/responses
disable-default-response - Disables the generation of the default 200 OK response for all operations. Only explicit responses (e.g., from google.api.http annotations) will be included.
format yaml, json, or jsonschema Which format to use for the output file, defaults to yaml. yaml and json render an OpenAPI document. jsonschema renders a standalone JSON Schema (draft 2020-12) document containing only the message and enum schemas, with every type under $defs; see JSON Schema output.
fully-qualified-message-names - Use fully qualified message names as the "title" for OpenAPI schemas. So it will be displayed as company.users.administration.v1.User instead of User.
ignore-googleapi-http - [DEPRECATED] Use plugins=connectrpc;gnostic;protovalidate;twirp instead. Ignore google.api.http options on methods when generating openapi specs
only-googleapi-http - [DEPRECATED] Use plugins=google.api.http;gnostic;protovalidate instead. Only generate routes for methods that have explicit google.api.http annotations. Methods without annotations will be skipped.
include-number-enum-values - Include number enum values beside the string versions, defaults to only showing strings
override {filepath} The path to an override OpenAPI file to override schema components generated by the plugin. This option does not work when used with the remote plugin.
path {filepath} Output filepath, defaults to per-proto file output if not given. When using buf, generating multiple files to the same path requires additional configuration to avoid overwriting files. See #159.
path-prefix {path} Prefixes the given string to the beginning of each HTTP path.
features {feature1};{feature2};[...] Semicolon-separated list of features to enable. Options: connectrpc, google.api.http, twirp, gnostic, protovalidate; Default: connectrpc;google.api.http;gnostic;protovalidate. If this option is used, only the specified features will be enabled.
allowed-visibilities {visibility1};{visibility2};[...] Semicolon-separated list of visibility labels to include. If an element (service, method, message, enum, enum value, or field) has a google.api.visibility rule, it will only be included in the generated OpenAPI specification if its visibility label is in this list. If this option is omitted, elements with visibility rules are filtered out by default. Elements without visibility rules are always included.
proto - Generate requests/responses with the protobuf content type
services {service_name} Specifies which services to include in the generated OpenAPI specification. If omitted, all services are included. The service name must be fully qualified (e.g., "package.name.ServiceName"). Wildcards (* and **) are supported; * matches a single package segment, while ** matches multiple. This option can be provided multiple times to include multiple services.
short-operation-ids - Set the operationId to shortServiceName + "_" + method short name instead of the full method name.
short-service-tags - Use the short service name instead of the full name for OpenAPI tags.
trim-unused-types - Remove types that aren't references from any method request or response.
well-known-type-descriptions full, concise, or omit How to render comments for well-known types (google.protobuf.Timestamp, google.protobuf.Duration, etc.). concise (default) uses a short JSON-oriented description. full copies comments from the type's .proto file; those comments describe the protobuf representation, which frequently doesn't match JSON. omit leaves the type undescribed. Descriptions written on your own fields are unaffected.
with-google-error-detail - Enables the generation of error details using error_details.proto from google.rpc
with-proto-annotations - Add protobuf type annotations to the end of descriptions so users know the protobuf type that the field converts to.
with-proto-names - Use protobuf field names instead of the camelCase JSON names for property names.
with-streaming - Generate OpenAPI for client/server/bidirectional streaming RPCs (can be messy).
without-default-tags - Avoid appending default tags in the resulting OAS doc. All tags need to be explicitly defined through annotations.
without-field-behavior-prefixes - Omit description prefixes from google.api.field_behavior annotations (OPTIONAL, IMMUTABLE, UNORDERED_LIST, NON_EMPTY_DEFAULT, IDENTIFIER). OpenAPI required, readOnly, and writeOnly are still applied.

Features

The features option allows you to control which protocol-specific annotations and functionalities are enabled during OpenAPI generation. This is useful for tailoring the output to your specific needs and avoiding unnecessary processing.

At least one of the following features is required: connectrpc, google.api.http, or twirp. These features dictate how RPC methods are translated into HTTP endpoints in the OpenAPI specification.

Available features:

  • connectrpc: Enables support for Connect RPC.
  • google.api.http: Enables support for google.api.http annotations (gRPC-Gateway style).
  • twirp: Enables support for Twirp RPC.
  • gnostic: Enables support for Gnostic OpenAPI v3 annotations.
  • protovalidate: Enables support for Protovalidate annotations.

Examples:

  • Enable only ConnectRPC support:

    opt:
      - features=connectrpc
  • Enable Google API HTTP and Protovalidate support:

    opt:
      - features=google.api.http;protovalidate
  • Enable all features:

    opt:
      - features=connectrpc;google.api.http;twirp;gnostic;protovalidate

Contributing

Contributions are accepted and welcome! Please make sure that all tests pass locally for you. Tests will automatically build the fixture descriptor set (fileset.binpb) on demand if buf is installed, or you can generate it manually:

go generate ./internal/converter/testdata

Otherwise, tests are run with:

go test ./...

# or, if you prefer:
just test

About

Plugin for generating OpenAPIv3 from protobufs matching the Connect RPC interface

Topics

Resources

Stars

307 stars

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages