# Technical Documentation: grpc-ecosystem/grpc-gateway

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/grpc-ecosystem/grpc-gateway)

### Overview (`README.md`)

<div align="center">
<h1>gRPC-Gateway</h1>
<p>
gRPC to JSON proxy generator following the gRPC HTTP spec
</p>
<a href="https://github.com/grpc-ecosystem/grpc-gateway/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/grpc-ecosystem/grpc-gateway/ci.yml?color=379c9c&label=build&logo=github&logoColor=ffffff&style=flat-square"/></a>
<a href="https://app.slack.com/client/T029RQSE6/CBATURP1D"><img src="https://img.shields.io/badge/slack-grpc--gateway-379c9c?logo=slack&logoColor=ffffff&style=flat-square"/></a>
<a href="https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"><img src="https://img.shields.io/github/license/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square"/></a>
<a href="https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/v2"><img src="https://img.shields.io/badge/godoc-reference-379c9c?style=flat-square&logo=go&logoColor=ffffff"/></a>
<a href="https://github.com/grpc-ecosystem/grpc-gateway/releases"><img src="https://img.shields.io/github/v/release/grpc-ecosystem/grpc-gateway?color=379c9c&logoColor=ffffff&style=flat-square"/></a>
<a href="https://github.com/grpc-ecosystem/grpc-gateway/stargazers"><img src="https://img.shields.io/github/stars/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square"/></a>
<a href="https://slsa.dev/images/gh-badge-level3.svg"><img src="https://slsa.dev/images/gh-badge-level3.svg"/></a>

</div>

## About

The gRPC-Gateway is a plugin of the Google protocol buffers compiler
[protoc](https://github.com/protocolbuffers/protobuf).
It reads protobuf service definitions and generates a reverse-proxy server which
translates a RESTful HTTP API into gRPC. This server is generated according to the
[`google.api.http`](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto#L46)
annotations in your service definitions.

This helps you provide your APIs in both gRPC and RESTful style at the same time.

<div align="center">
<img src="docs/assets/images/architecture_introduction_diagram.svg" />
</div>

## Docs

You can read our docs at:

- https://grpc-ecosystem.github.io/grpc-gateway/

## Testimonials

> We use the gRPC-Gateway to serve millions of API requests per day,
> and have been since 2018 and through all of that,
> we have never had any issues with it.
>
> _- William Mill, [Ad Hoc](http://adhocteam.us/)_

## Background

gRPC is great -- it generates API clients and server stubs in many programming
languages, it is fast, easy-to-use, bandwidth-efficient and its design is
combat-proven by Google. However, you might still want to provide a traditional
RESTful JSON API as well. Reasons can range from maintaining
backward-compatibility, supporting languages or clients that are not well supported by
gRPC, to simply maintaining the aesthetics and tooling involved with a RESTful
JSON architecture.

This project aims to provide that HTTP+JSON interface to your gRPC service.
A small amount of configuration in your service to attach HTTP semantics is all
that's needed to generate a reverse-proxy with this library.

## Installation

### Compile from source

The following instructions assume you are using
[Go Modules](https://go.dev/wiki/Modules) for dependency
management. Use a
[tool dependency](https://go.dev/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module)
to track the versions of the following executable packages:

For Go 1.24 and later, prefer the `tool` directive in `go.mod` described in the "Tracking Tools in `go.mod`" section. The following blank-import pattern is mainly useful for projects that are not using Go 1.24 yet.

```go
// +build tools

package tools

import (
    _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway"
    _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2"
    _ "google.golang.org/grpc/cmd/protoc-gen-go-grpc"
    _ "google.golang.org/protobuf/cmd/protoc-gen-go"
)
```

Run `go mod tidy` to resolve the versions. Install by running

```sh
go install \
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway \
    github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 \
    google.golang.org/protobuf/cmd/protoc-gen-go \
    google.golang.org/grpc/cmd/protoc-gen-go-grpc
```

This will place four binaries in your `$GOBIN`;

- `protoc-gen-grpc-gateway`
- `protoc-gen-openapiv2`
- `protoc-gen-go`
- `protoc-gen-go-grpc`

Make sure that your `$GOBIN` is in your `$PATH`.

If you want to emit OpenAPI 3.1 instead of (or in addition to) Swagger 2.0,
install `protoc-gen-openapiv3` as well:

```sh
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3
```

> ⚠️ **Alpha.** `protoc-gen-openapiv3` is new and its output is not yet
> stable — the emitted JSON shape for oneofs, wrappers, enums, and similar
> constructs may change in response to real-world feedback before the
> plugin graduates. Don't rely on the exact spec bytes being stable across
> minor releases; the proto-to-OpenAPI mapping rules are likely to
> tighten, and tooling-compatibility compromises (documented in the
> generator source) may be revisited as consumer OpenAPI 3.1 support
> matures. `protoc-gen-openapiv2` is the production-stable option.

See [OpenAPI 3.1 Output](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/openapi_v3/)
for what it supports and how it differs from `protoc-gen-openapiv2`.

### **Using the `tool` Directive in Go 1.24**

Starting from Go 1.24, the `tool` directive in `go.mod` provides a structured way to track and manage executable dependencies. This replaces the previous workaround of using a separate `tools.go` file with blank imports.

#### **Tracking Tools in `go.mod`**

Instead of manually importing tool dependencies in a Go source file, you can now use the `tool` directive in `go.mod` to declare the tools your project depends on. For example:

```go
module tools

go 1.24

tool (
	github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
	github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
	google.golang.org/grpc/cmd/protoc-gen-go-grpc
	google.golang.org/protobuf/cmd/protoc-gen-go
)
```

#### **Managing Tool Dependencies**

To add tools to your module, use the `-tool` flag with `go get`:

```sh
go get -tool github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get -tool github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
go get -tool google.golang.org/protobuf/cmd/protoc-gen-go
go get -tool google.golang.org/grpc/cmd/protoc-gen-go-grpc
```

This automatically updates `go.mod`, adding the tools under the `tool` directive along with `require` statements to ensure version tracking.

### Install Tools

Once the tool dependencies are properly recorded in the `go.mod` file, simply execute the following command in the root directory of your project:

```sh
go install tool
```

This will place four binaries in your `$GOBIN`;

- `protoc-gen-grpc-gateway`
- `protoc-gen-openapiv2`
- `protoc-gen-go`
- `protoc-gen-go-grpc`

Make sure that your `$GOBIN` is in your `$PATH`.

### Download the binaries

You may alternatively download the binaries from the [GitHub releases page](https://github.com/grpc-ecosystem/grpc-gateway/releases/latest).
We generate [SLSA3 signatures](https://slsa.dev) using the OpenSSF's [slsa-framework/slsa-github-generator](https://github.com/slsa-framework/slsa-github-generator) during the release process. To verify a release binary:

1. Install the verification tool from [slsa-framework/slsa-verifier#installation](https://github.com/slsa-framework/slsa-verifier#installation).
2. Download the provenance file `attestation.intoto.jsonl` from the [GitHub releases page](https://github.com/grpc-ecosystem/grpc-gateway/releases/latest).
3. Run the verifier:

```shell
slsa-verifier -artifact-path <the-binary> -provenance attestation.intoto.jsonl -source github.com/grpc-ecosystem/grpc-gateway -tag <the-tag>
```

Alternatively, see the section on remotely managed plugin versions below.

## Usage

### 1.Define your [gRPC](https://grpc.io/docs/) service using protocol buffers

`your_service.proto`:

```protobuf
 syntax = "proto3";
 package your.service.v1;
 option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";

 message StringMessage {
   string value = 1;
 }

 service YourService {
   rpc Echo(StringMessage) returns (StringMessage) {}
 }
```

### 2. Generate gRPC stubs

This step generates the gRPC stubs that you can use to implement the service and consume from clients:

Here's an example `buf.gen.yaml` you can use to generate the stubs with [buf](https://github.com/bufbuild/buf):

```yaml
version: v2
plugins:
  - local: protoc-gen-go
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: gen/go
    opt:
      - paths=source_relative
```

With this file in place, you can generate your files using `buf generate`.

> For a complete example of using `buf generate` to generate protobuf stubs, see
> [the boilerplate repo](https://github.com/johanbrandhorst/grpc-gateway-boilerplate).
> For more information on generating the stubs with buf, see
> [the official documentation](https://docs.buf.build/generate-usage).

If you are using `protoc` to generate stubs, here's an example of what a command
might look like:

```sh
protoc -I . \
    --go_out ./gen/go/ --go_opt paths=source_relative \
    --go-grpc_out ./gen/go/ --go-grpc_opt paths=source_relative \
    your/service/v1/your_service.proto
```

### 3. Implement your service in gRPC as usual.

### 4. Generate reverse-proxy using `protoc-gen-grpc-gateway`

At this point, you have 3 options:

- no further modifications, use the default mapping to HTTP semantics (method, path, etc.)
  - this will work on any `.proto` file, but will not allow setting HTTP paths, request parameters or similar
- additional `.proto` modifications to use a custom mapping
  - relies on parameters in the `.proto` file to set custom HTTP mappings
- no `.proto` modifications, but use an external configuration file
  - relies on an external configuration file to set custom HTTP mappings
  - mostly useful when the source proto file isn't under your control

#### 1. Using the default mapping

This requires no additional modification to the `.proto` file but does require enabling a specific option when executing the plugin.
The `generate_unbound_methods` should be enabled.

Here's what a `buf.gen.yaml` file might look like with this option enabled:

```yaml
version: v2
plugins:
  - local: protoc-gen-go
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-grpc-gateway
    out: gen/go
    opt:
      - paths=source_relative
      - generate_unbound_methods=true
```

With `protoc` (just the grpc-gateway stubs):

```sh
protoc -I . --grpc-gateway_out ./gen/go \
    --grpc-gateway_opt paths=source_relative \
    --grpc-gateway_opt generate_unbound_methods=true \
    your/service/v1/your_service.proto
```

#### 2. With custom annotations

Add a [`google.api.http`](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto#L46)
annotation to your .proto file

`your_service.proto`:

```diff
 syntax = "proto3";
 package your.service.v1;
 option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";
+
+import "google/api/annotations.proto";
+
 message StringMessage {
   string value = 1;
 }

 service YourService {
-  rpc Echo(StringMessage) returns (StringMessage) {}
+  rpc Echo(StringMessage) returns (StringMessage) {
+    option (google.api.http) = {
+      post: "/v1/example/echo"
+      body: "*"
+    };
+  }
 }
```

> You will need to provide the required third party protobuf files to the protobuf compiler.
> If you are using [buf](https://github.com/bufbuild/buf), this dependency can
> be added to the `deps` array in your `buf.yaml` under the name
> `buf.build/googleapis/googleapis`:
>
> ```yaml
> version: v2
> name: buf.build/yourorg/myprotos
> deps:
>   - buf.build/googleapis/googleapis
> ```
>
> Always run `buf dep update` after adding a dependency to your `buf.yaml`.

See [a_bit_of_everything.proto](examples/internal/proto/examplepb/a_bit_of_everything.proto)
for examples of more annotations you can add to customize gateway behavior
and generated OpenAPI output.

Here's what a `buf.gen.yaml` file might look like:

```yaml
version: v2
plugins:
  - local: protoc-gen-go
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-grpc-gateway
    out: gen/go
    opt:
      - paths=source_relative
```

If you are using `protoc` to generate stubs, you need to ensure the required
dependencies are available to the compiler at compile time. These can be found
by manually cloning and copying the relevant files from the
[googleapis repository](https://github.com/googleapis/googleapis), and providing
them to `protoc` when running. The files you will need are:

```
google/api/annotations.proto
google/api/field_behavior.proto
google/api/http.proto
google/api/httpbody.proto
```

Here's what a `protoc` execution might look like:

```sh
protoc -I . --grpc-gateway_out ./gen/go \
    --grpc-gateway_opt paths=source_relative \
    your/service/v1/your_service.proto
```

#### 3. External configuration

If you do not want to (or cannot) modify the proto file for use with gRPC-Gateway you can
alternatively use an external
[gRPC Service Configuration](https://cloud.google.com/endpoints/docs/grpc/grpc-service-config) file.
[Check our documentation](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/grpc_api_configuration/)
for more information. This is best combined with the `standalone=true` option
to generate a file that can live in its own package, separate from the files
generated by the source protobuf file.

Here's what a `buf.gen.yaml` file might look like with this option enabled:

```yaml
version: v2
plugins:
  - local: protoc-gen-go
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-grpc-gateway
    out: gen/go
    opt:
      - paths=source_relative
      - grpc_api_configuration=path/to/config.yaml
      - standalone=true
```

With `protoc` (just the grpc-gateway stubs):

```sh
protoc -I . --grpc-gateway_out ./gen/go \
    --grpc-gateway_opt paths=source_relative \
    --grpc-gateway_opt grpc_api_configuration=path/to/config.yaml \
    --grpc-gateway_opt standalone=true \
    your/service/v1/your_service.proto
```

### 5. Write an entrypoint for the HTTP reverse-proxy server

```go
package main

import (
  "context"
  "flag"
  "net/http"

  "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
  "google.golang.org/grpc"
  "google.golang.org/grpc/credentials/insecure"
  "google.golang.org/grpc/grpclog"

  gw "github.com/yourorg/yourrepo/proto/gen/go/your/service/v1/your_service"  // Update
)

var (
  // command-line options:
  // gRPC server endpoint
  grpcServerEndpoint = flag.String("grpc-server-endpoint",  "localhost:9090", "gRPC server endpoint")
)

func run() error {
  ctx := context.Background()
  ctx, cancel := context.WithCancel(ctx)
  defer cancel()

  // Register gRPC server endpoint
  // Note: Make sure the gRPC server is running properly and accessible
  mux := runtime.NewServeMux()
  opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
  err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux,  *grpcServerEndpoint, opts)
  if err != nil {
    return err
  }

  // Start HTTP server (and proxy calls to gRPC server endpoint)
  return http.ListenAndServe(":8081", mux)
}

func main() {
  flag.Parse()

  if err := run(); err != nil {
    grpclog.Fatal(err)
  }
}
```

### 6. (Optional) Generate OpenAPI definitions using `protoc-gen-openapiv2`

Here's what a `buf.gen.yaml` file might look like:

```yaml
version: v2
plugins:
  - local: protoc-gen-go
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-go-grpc
    out: gen/go
    opt:
      - paths=source_relative
  - local: protoc-gen-grpc-gateway
    out: gen/go
    opt:
      - paths=source_relative
      - generate_unbound_methods=true
  - local: protoc-gen-openapiv2
    out: gen/go
```

To use the custom protobuf annotations supported by `protoc-gen-openapiv2`, we need
another dependency added to our protobuf generation step. If you are using
`buf`, you can add the `buf.build/grpc-ecosystem/grpc-gateway` dependency
to your `deps` array:

```yaml
version: v2
name: buf.build/yourorg/myprotos
deps:
  - buf.build/googleapis/googleapis
  - buf.build/grpc-ecosystem/grpc-gateway
```

With `protoc` (just the swagger file):

```sh
protoc -I . --openapiv2_out ./gen/openapiv2 \
    your/service/v1/your_service.proto
```

If you are using `protoc` to generate stubs, you will need to copy the protobuf
files from the `protoc-gen-openapiv2/options` directory of this repository,
and providing them to `protoc` when running.

Note that this plugin also supports generating OpenAPI definitions for unannotated methods;
use the `generate_unbound_methods` option to enable this.

It is possible with the HTTP mapping for a gRPC service method to create duplicate mappings
with the only difference being constraints on the path parameter.

`/v1/{name=projects/*}` and `/v1/{name=organizations/*}` both become `/v1/{name}`. When
this occurs the plugin will rename the path parameter with a "\_1" (or "\_2" etc) suffix
to differentiate the different operations. So in the above example, the 2nd path would become
`/v1/{name_1=organizations/*}`. This can also cause OpenAPI clients to URL encode the "/" that is
part of the path parameter as that is what OpenAPI defines in the specification. To allow gRPC gateway to
accept the URL encoded slash and still route the request, use the UnescapingModeAllCharacters or
UnescapingModeLegacy (which is the default currently though may change in future versions). See
[Customizing Your Gateway](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/customizing_your_gateway/)
for more information.

#### Alternative: OpenAPI 3.1 with `protoc-gen-openapiv3`

> ⚠️ **Alpha.** `protoc-gen-openapiv3` is new and its output is not yet
> stable. Expect breaking changes to the emitted JSON shape (oneof
> encodings, wrapper types, enum form, path-template expansion, etc.)
> between minor releases while the mapping rules settle in response to
> real-world feedback. Use it if you want to follow that evolution;
> otherwise `protoc-gen-openapiv2` remains the stable choice.

`protoc-gen-openapiv3` is a separate generator that emits OpenAPI
**3.1.0** JSON directly from `google.api.http` annotations. It's a good
choice when your downstream tooling requires 3.1, when you want the richer
JSON Schema 2020-12 constructs (proper `oneOf` encoding for proto oneofs,
spec-accurate literal expansion of constrained path templates like
`{name=shelves/*/books/*}`, etc.).

Add it to your `buf.gen.yaml` alongside (or instead of) `protoc-gen-openapiv2`:

```yaml
version: v2
plugins:
  - local: protoc-gen-openapiv3
    out: gen/openapiv3
```

Or invoke it directly with `protoc`:

```sh
protoc -I. --openapiv3_out=./gen/openapiv3 your/service/v1/your_service.proto
```

A `.openapi.json` file appears next to each proto file that declares HTTP
bindings; files with no HTTP-bound services produce no output.
See [OpenAPI 3.1 Output](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/openapi_v3/) for
more information about the capabilities of protoc-gen-openapiv3.

## Usage with remote plugins

As an alternative to all of the above, you can use `buf` with
[remote plugins](https://buf.build/docs/bsr/remote-plugins/usage)
to manage plugin versions and generation. An example `buf.gen.yaml` using remote
plugin generation looks like this:

```yaml
version: v2
plugins:
  - remote: buf.build/protocolbuffers/go:v1.31.0
    out: gen/go
    opt:
      - paths=source_relative
  - remote: buf.build/grpc/go:v1.3.0
    out: gen/go
    opt:
      - paths=source_relative
  - remote: buf.build/grpc-ecosystem/gateway:v2.16.2
    out: gen/go
    opt:
      - paths=source_relative
  - remote: buf.build/grpc-ecosystem/openapiv2:v2.16.2
    out: gen/openapiv2
```

This requires no local installation of any plugins. Be careful to use the same
version of the generator as the runtime library, i.e. if using `v2.16.2`, run

```shell
$ go get github.com/grpc-ecosystem/grpc-gateway/v2@v2.16.2
```

To get the same version of the runtime in your `go.mod`.

Note that usage of remote plugins is incompatible with usage of external configuration files like [grpc_api_configuration](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/grpc_api_configuration/#using-an-external-configuration-file).

## Video intro

This GopherCon UK 2019 presentation from our maintainer [@JohanBrandhorst](https://github.com/johanbrandhorst) provides a good intro to using the gRPC-Gateway. It uses the following boilerplate repo as a base: https://github.com/johanbrandhorst/grpc-gateway-boilerplate.

<div align="center">
<a href="https://www.youtube.com/watch?v=Pq1paKC-fXk">
<img src="https://img.youtube.com/vi/Pq1paKC-fXk/0.jpg" />
</a>
</div>

## Parameters and flags

When using `buf` to generate stubs, flags and parameters are passed through
the `opt` field in your `buf.gen.yaml` file, for example:

```yaml
version: v2
plugins:
  - local: protoc-gen-grpc-gateway
    out: gen/go
    opt:
      - paths=source_relative
      - grpc_api_configuration=path/to/config.yaml
      - standalone=true
```

During code generation with `protoc`, flags to gRPC-Gateway tools must be passed
through `protoc` using one of 2 patterns:

- as part of the `--<tool_suffix>_out` `protoc` parameter: `--<tool_suffix>_out=<flags>:<path>`

```sh
--grpc-gateway_out=repeated_path_param_separator=ssv:.
--openapiv2_out=repeated_path_param_separator=ssv:.
```

- using additional `--<tool_suffix>_opt` parameters: `--<tool_suffix>_opt=<flag>[,<flag>]*`

```sh
--grpc-gateway_opt repeated_path_param_separator=ssv
--openapiv2_opt repeated_path_param_separator=ssv
```

## More examples

More examples are available under the `examples/internal` directory.

- `proto/examplepb/echo_service.proto`, `proto/examplepb/a_bit_of_everything.proto`, `proto/examplepb/unannotated_echo_service.proto`: service definition
  - `proto/examplepb/echo_service.pb.go`, `proto/examplepb/a_bit_of_everything.pb.go`, `proto/examplepb/unannotated_echo_service.pb.go`: [generated] stub of the service
  - `proto/examplepb/echo_service.pb.gw.go`, `proto/examplepb/a_bit_of_everything.pb.gw.go`, `proto/examplepb/unannotated_echo_service.pb.gw.go`: [generated] reverse proxy for the service
  - `proto/examplepb/unannotated_echo_service.yaml`: gRPC API Configuration for `unannotated_echo_service.proto`
- `server/main.go`: service implementation
- `cmd/example-gateway-server/`: entrypoint of the generated reverse proxy

To use the same port for custom HTTP handlers (e.g. serving `swagger.json`),
gRPC-Gateway, and a gRPC server, see
[this example by CoreOS](https://github.com/philips/grpc-gateway-example/blob/master/cmd/serve.go)
(and its accompanying [blog post](https://web.archive.org/web/20201112010739/https://coreos.com/blog/grpc-protobufs-swagger.html)).

[This example by neiro.ai](https://github.com/mynalabsai/grpc_gateway_media_example) (and its accompanying [blog post](https://medium.com/neiro-ai/grpc-gateway-for-media-api-by-neiro-9033caab12c8)) shows how mediafiles using `multipart/form-data` can be integrated into rpc messages using a middleware.

See also these community example repositories:

- [grpc-gateway-boilerplate](https://github.com/johanbrandhorst/grpc-gateway-boilerplate): a starter/boilerplate for new gRPC-Gateway projects.
- [grpc-template](https://github.com/cosmotek/grpc-template): an example using Chi as the HTTP router, a custom base path, and embedded Swagger UI.

## Features

### Supported

- Generating JSON API handlers.
- Method parameters in the request body.
- Method parameters in the request path.
- Method parameters in the query string.
- Enum fields in the path parameter (including repeated enum fields).
- Mapping streaming APIs to newline-delimited JSON streams.
- Mapping HTTP headers with `Grpc-Metadata-` prefix to gRPC metadata (prefixed with `grpcgateway-`)
- Optionally emitting API definitions for
  [OpenAPI (Swagger) v2](https://swagger.io/docs/specification/2-0/basic-structure/).
- Setting [gRPC timeouts](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests)
  through inbound HTTP `Grpc-Timeout` header.
- Partial support for [gRPC API Configuration](https://cloud.google.com/endpoints/docs/grpc/grpc-service-config)
  files as an alternative to annotation.
- Automatically translating PATCH requests into Field Mask gRPC requests. See
  [the docs](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/patch_feature/)
  for more information.
- [Protobuf Editions](https://protobuf.dev/editions/overview/) support (edition 2023).
- Go [Opaque API](https://go.dev/blog/protobuf-opaque) support.

### No plan to support

But patches are welcome.

- Method parameters in HTTP headers.
- Handling trailer metadata.
- Encoding request/response body in XML.
- True bi-directional streaming.

## Mapping gRPC to HTTP

- [How gRPC error codes map to HTTP status codes in the response](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/runtime/errors.go#L15).
- HTTP request source IP is added as `X-Forwarded-For` gRPC request header.
- HTTP request host is added as `X-Forwarded-Host` gRPC request header.
- HTTP `Authorization` header is added as `authorization` gRPC request header.
- Remaining Permanent HTTP header keys (as specified by the IANA
  [here](http://www.iana.org/assignments/message-headers/message-headers.xhtml))
  are prefixed with `grpcgateway-` and added with their values to gRPC request
  header.
- HTTP headers that start with 'Grpc-Metadata-' are mapped to gRPC metadata
  (prefixed with `grpcgateway-`).
- While configurable, the default {un,}marshaling uses
  [protojson](https://pkg.go.dev/google.golang.org/protobuf/encoding/protojson).
- The path template used to map gRPC service methods to HTTP endpoints supports the [google.api.http](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto)
  path template syntax. For example, `/api/v1/{name=projects/*/topics/*}` or `/prefix/{path=organizations/**}`.

## Contribution

See [CONTRIBUTING.md](http://github.com/grpc-ecosystem/grpc-gateway/blob/main/CONTRIBUTING.md).

## License

gRPC-Gateway is licensed under the BSD 3-Clause License.
See [LICENSE](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE) for more details.

---

### Overview (`openapiv3-merge/README.md`)

# openapiv3-merge

`openapiv3-merge` combines multiple OpenAPI 3.1 JSON documents into a single
document. It is the companion tool for [`protoc-gen-openapiv3`](../protoc-gen-openapiv3/),
which emits one document per proto file. Pipe its output through
`openapiv3-merge` to produce a single combined spec.

## Why a separate binary

`protoc-gen-openapiv3` follows the protobuf convention of one output file per
input file. That keeps the plugin well-behaved under all protoc/buf
invocations and avoids forcing `buf` users onto `strategy: all`. The trade-off
is that consumers who want one document have to combine the per-file outputs
themselves. `openapiv3-merge` is that step.

## Install

```sh
go install github.com/grpc-ecosystem/grpc-gateway/v2/openapiv3-merge@latest
```

## Usage

```sh
openapiv3-merge FILE [FILE ...] > merged.openapi.json
```

The merged document is written to stdout. Errors go to stderr and the
process exits with a non-zero status. Input order matters: the first
input's `info`, `servers`, and `externalDocs` are kept in the merged
document, so put the file with the broadest scope first.

### With buf

```sh
#!/usr/bin/env bash
set -euo pipefail

buf generate

# Put the file with the shared openapiv3_document annotation first so
# its info/servers/externalDocs are kept; sort the rest for determinism.
root=gen/api/v1/api.openapi.json
mapfile -t rest < <(find gen -name '*.openapi.json' ! -path "$root" | sort)
openapiv3-merge "$root" "${rest[@]}" > gen/api.openapi.json
```

### With protoc

```sh
#!/usr/bin/env bash
set -euo pipefail

protoc -I. \
  --openapiv3_out=./gen \
  $(find . -name '*.proto')

root=gen/api/v1/api.openapi.json
mapfile -t rest < <(find gen -name '*.openapi.json' ! -path "$root" | sort)
openapiv3-merge "$root" "${rest[@]}" > gen/api.openapi.json
```

### One-shot

For trivial trees where any input may go first:

```sh
openapiv3-merge $(find . -name '*.openapi.json' | sort) > api.openapi.json
```

## Merge rules

The merger is strict: anything that could be a silent overwrite is rejected.

| Field | Rule |
| --- | --- |
| `openapi` | Must match across all inputs. |
| `info`, `servers`, `externalDocs` | Taken from the first input. Later inputs' values are dropped. |
| `paths`, `webhooks` | Unioned in input order. Same path with non-identical content → error. |
| `components/*` | Unioned with sorted keys. Same name with non-identical content → error. |
| `tags` | Deduplicated by `name`. Same name with non-identical metadata → error. |
| `security` | First input to declare a non-empty array wins. Later inputs that declare a different non-empty array → error. |
| Unknown top-level keys (extensions, `x-*`) | Taken from the first input. |

"Non-identical content" is compared canonically: two values that differ only
in key order are equal. This means component schemas with the same fully
qualified name (which is what `protoc-gen-openapiv3` emits — e.g.
`example.v1.User`) merge cleanly across packages.

## Output

- Top-level fields appear in OpenAPI 3.1.0 declaration order.
- `paths` and `webhooks` are emitted in input order.
- `components/*` sub-maps are sorted by key, matching `protoc-gen-openapiv3`.
- Tags appear in first-occurrence order.

---

### Overview (`examples/internal/README.md`)

# One way to run the example

```bash
# Handle dependencies (this repository uses Go modules)
$ go mod download
```

Follow the guides from this [README.md](./browser/README.md) to run the server and gateway.
```bash
# Make sure you are in the correct directory: 
# $GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/v2/examples/internal
$ cd examples/internal/browser
$ pwd

# Install gulp
$ npm install gulp-cli
$ npm install
$ gulp

# Run
$ gulp bower
$ gulp backends
```

Then you can use curl or a browser to test:

```bash
# List all apis
$ curl http://localhost:8080/openapiv2/echo_service.swagger.json

# Visit the apis
$ curl -XPOST http://localhost:8080/v1/example/echo/foo
{"id":"foo"}

$ curl  http://localhost:8080/v1/example/echo/foo/123
{"id":"foo","num":"123"}

```

So you have visited the apis by HTTP successfully. You can also try other apis.

---

### Overview (`internal/casing/README.md`)

# Case conversion

This package contains two functions:
- `Camel` copied from the `github.com/golang/protobuf/protoc-gen-go/generator` package.
- `JSONCamelCase` copied from the `github.com/protocolbuffers/protobuf-go/internal/strs` package.

Both these modules are licensed by The Go Authors, as reflected in this package's [LICENSE.md].

---

### Overview (`examples/internal/browser/README.md`)

# Browser example

This directory contains an example use of gRPC-Gateway with web browsers.
The following commands automatically runs integration tests with phantomjs.

```shell-session
$ npm install gulp-cli
$ npm install
$ gulp
```

## Other examples

### Very simple example

Run

```shell-session
$ gulp bower
$ gulp backends
```

then, open `index.html`.

### Integration test with your browser

Run

```shell-session
$ gulp serve
```

then, open `http://localhost:8000` with your browser.

---

### Index (`docs/index.md`)

---
layout: default
title: gRPC-Gateway
nav_order: 0
description: "Documentation site for the gRPC-Gateway"
permalink: /
---

# gRPC-Gateway
{: .fs-9 }

gRPC-Gateway is a plugin of [protoc](https://github.com/protocolbuffers/protobuf). It reads a [gRPC](https://grpc.io/) service definition and generates a reverse-proxy server which translates a RESTful JSON API into gRPC. This server is generated according to [custom options](https://cloud.google.com/service-infrastructure/docs/service-management/reference/rpc/google.api#http) in your gRPC definition.
{: .fs-6 .fw-300 }

[Get started](#getting-started){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } [View it on GitHub](https://github.com/grpc-ecosystem/grpc-gateway){: .btn .fs-5 .mb-4 .mb-md-0 }

---

## Getting started

<a href="https://github.com/grpc-ecosystem/grpc-gateway/actions/workflows/main.yml"><img src="https://img.shields.io/github/workflow/status/grpc-ecosystem/grpc-gateway/main?color=379c9c&label=build&logo=github&logoColor=ffffff&style=flat-square"/></a>
<a href="https://app.slack.com/client/T029RQSE6/CBATURP1D"><img src="https://img.shields.io/badge/slack-grpc--gateway-379c9c?logo=slack&logoColor=ffffff&style=flat-square"/></a>
<a href="https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE"><img src="https://img.shields.io/github/license/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square"/></a>
<a href="https://github.com/grpc-ecosystem/grpc-gateway/releases"><img src="https://img.shields.io/github/v/release/grpc-ecosystem/grpc-gateway?color=379c9c&logoColor=ffffff&style=flat-square"/></a>
<a href="https://github.com/grpc-ecosystem/grpc-gateway/stargazers"><img src="https://img.shields.io/github/stars/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square"/></a>

gRPC-Gateway helps you to provide your APIs in both gRPC and RESTful style at the same time.

<div align="center">
<img src="assets/images/architecture_introduction_diagram.svg" />
</div>

To learn more about gRPC-Gateway check out the documentation.

## Contribution

See [CONTRIBUTING.md](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/CONTRIBUTING.md).

## License

gRPC-Gateway is licensed under the BSD 3-Clause License.

See [LICENSE](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE) for more details.

### Thank you to the contributors of gRPC-Gateway

<ul class="list-style-none">
{% for contributor in site.github.contributors %}
<li class="d-inline-block mr-1">
<a href="{{ contributor.html_url }}"><img src="{{ contributor.avatar_url }}" width="32" height="32" alt="{{ contributor.login }}"/></a>
</li>
{% endfor %}
</ul>

---

### Docs Contributing Index (`docs/docs/contributing/index.md`)

---
layout: default
title: Contributing
nav_order: 5
has_children: true
---

---

### Docs Development Index (`docs/docs/development/index.md`)

---
layout: default
title: Development
nav_order: 4
has_children: true
---

---

### Docs Mapping Index (`docs/docs/mapping/index.md`)

---
layout: default
title: Mapping
nav_order: 2
has_children: true
---

---

### Docs Operations Index (`docs/docs/operations/index.md`)

---
layout: default
title: Operations
nav_order: 3
has_children: true
---

---

### Docs Overview Index (`docs/docs/overview/index.md`)

---
layout: default
title: Overview
nav_order: 1
has_children: true
---

---

### Docs Tutorials Index (`docs/docs/tutorials/index.md`)

---
layout: default
title: Tutorials
nav_order: 6
has_children: true
---

---

### Docs Tutorials Generating Stubs Index (`docs/docs/tutorials/generating_stubs/index.md`)

---
layout: default
title: Generating stubs
parent: Tutorials
nav_order: 2
has_children: true
---

For generating the stubs, we have two alternatives: `protoc` and `buf`. `protoc` is the more classic generation experience that is used widely in the industry, but it has a pretty steep learning curve. `buf` is a newer tool that is built with user experience and speed in mind. It also offers linting and breaking change detection, something `protoc` doesn't offer. We offer instructions for both here.

---

###  Config.Yml (`docs/_config.yml`)

# Site settings
# These are used to personalize your new site. If you look in the HTML files,
# you will see them accessed via {{ site.title }}, {{ site.github_repo }}, and so on.
# You can create any custom variable you would like, and they will be accessible
# in the templates via {{ site.myvariable }}.
title: gRPC-Gateway
description: gRPC-Gateway Documentation Website
baseurl: "/grpc-gateway" # the subpath of your site, e.g. /blog
url: "https://grpc-ecosystem.github.io" # the base hostname & protocol for your site, e.g. http://example.com

repository: grpc-ecosystem/grpc-gateway
remote_theme: pmarsceill/just-the-docs@v0.6.2

permalink: pretty
exclude: ["run.sh"]

# Set a path/url to a logo that will be displayed instead of the title
#logo: "/assets/images/grpc-gateway.png"

# Enable or disable the site search
# Supports true (default) or false
search_enabled: true
search:
  # Split pages into sections that can be searched individually
  # Supports 1 - 6, default: 2
  heading_level: 2
  # Maximum amount of previews per search result
  # Default: 3
  previews: 2
  # Maximum amount of words to display before a matched word in the preview
  # Default: 5
  preview_words_before: 3
  # Maximum amount of words to display after a matched word in the preview
  # Default: 10
  preview_words_after: 3
  # Set the search token separator
  # Default: /[\s\-/]+/
  # Example: enable support for hyphenated search words
  tokenizer_separator: /[\s/]+/
  # Display the relative url in search results
  # Supports true (default) or false
  rel_url: true
  # Enable or disable the search button that appears in the bottom right corner of every page
  # Supports true or false (default)
  button: false

# Enable or disable heading anchors
heading_anchors: true

# Aux links for the upper right navigation
aux_links:
  "gRPC-Gateway on GitHub":
    - "https://github.com/grpc-ecosystem/grpc-gateway"

# Makes Aux links open in a new tab. Default is false
aux_links_new_tab: false

# Sort order for navigation links
# nav_sort: case_insensitive # default, equivalent to nil
nav_sort: case_sensitive # Capital letters sorted before lowercase

# Footer content
# appears at the bottom of every page's main content

# Back to top link
back_to_top: true
back_to_top_text: "Back to top"

footer_content: 'Copyright &copy; the gRPC-Gateway Authors. Distributed by a <a href="https://github.com/grpc-ecosystem/grpc-gateway/tree/main/LICENSE">BSD 3-Clause License.</a>'

# Footer last edited timestamp
last_edit_timestamp: true # show or hide edit time - page must have `last_modified_date` defined in the frontmatter
last_edit_time_format: "%b %e %Y at %I:%M %p" # uses ruby's time format: https://ruby-doc.org/stdlib-2.7.0/libdoc/time/rdoc/Time.html

# Footer "Edit this page on GitHub" link text
gh_edit_link: true # show or hide edit this page link
gh_edit_link_text: "Edit this page on GitHub"
gh_edit_repository: "https://github.com/grpc-ecosystem/grpc-gateway" # the github URL for your repo
gh_edit_branch: "main" # the branch that your docs is served from
gh_edit_source: docs # the source that your files originate from
gh_edit_view_mode: "tree" # "tree" or "edit" if you want the user to jump into the editor immediately

# Color scheme currently only supports "dark", "light"/nil (default), or a custom scheme that you define
color_scheme: nil

# Disqus Comments
# disqus:
# Leave shortname blank to disable comments site-wide.
# Enable comments for any post by adding `comments: true` to that post's YAML Front Matter.
# shortname:

# Google Analytics Tracking
# e.g, UA-1234567-89
# ga_tracking:
# ga_tracking_anonymize_ip: true # Use GDPR compliant Google Analytics settings (true/nil by default)

plugins:
  - jekyll-seo-tag
  - jekyll-include-cache

kramdown:
  syntax_highlighter_opts:
    block:
      line_numbers: false

compress_html:
  clippings: all
  comments: all
  endings: all
  startings: []
  blanklines: false
  profile: false
  # ignore:
  # envs: all

---

### Docs Faq (`docs/docs/faq.md`)

---
layout: default
title: FAQ
nav_order: 7
---

# FAQ

## How can I write the annotations which gRPC-Gateway requires?

The gRPC-Gateway follows the spec of [`google.api.HttpRule`](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto), so first check out the documentation if it is feasible in the spec.

For situations where annotating the proto file is not an option please reference the documentation on [gRPC API Configuration](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/grpc_api_configuration/)

See also [a past discussion](https://groups.google.com/d/msg/grpc-io/Xqx80hG0D44/VNCDHjeE6pUJ) in the grpc-io mailing list.

## I want to support a certain style of HTTP request but the code generated by gRPC-Gateway does not. How can I support this style?

See the question above at first.

The gRPC-Gateway is intended to cover 80% of use cases without forcing you to write comprehensive but complicated annotations. So the gateway itself does not always cover all the use cases you have by design. In other words, the gateway automates typical boring boilerplate mapping between gRPC and HTTP/1 communication, but it does not do arbitrarily complex custom mappings for you.

On the other hand, you can still add whatever you want as a middleware which wraps
[`runtime.ServeMux`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#ServeMux). Since `runtime.ServeMux` is just a standard [`http.Handler`](http://golang.org/pkg/http#Handler), you can easily write a custom wrapper of `runtime.ServeMux`, leveraged with existing third-party libraries in Go (e.g. [gateway main.go program](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/gateway/main.go)).

## My gRPC server is written in (Scala or C++ or Ruby or Haskell etc). Is there a (Scala or C++ or Ruby or Haskell etc) version of gRPC-Gateway?

As of now, No. But it should not be a big issue because the reverse-proxy which gRPC-Gateway generates usually works as an independent process and communicates with your gRPC server over TCP or a Unix domain sockets (Unix systems only).

## Why are the models in the OpenAPI specification prefixed with the last part of the proto package name?

The reason to generate the prefixes is that we don't have a guaranteed unique namespace. If two packages produce different `Foo` messages then we will have trouble.

## Why not strip the prefix?

When a message is added which happens to conflict with another message (e.g. by importing a message with the same name from a different package) it will break code that is very far away from the code that changed. This is in an effort to adhere to the [principle of least astonishment](https://en.wikipedia.org/wiki/Principle_of_least_astonishment).

## What is the difference between the gRPC-Gateway and grpc-httpjson-transcoding?

The gRPC-Gateway is a generator that generates a Go implementation of a JSON/HTTP-gRPC reverse proxy based on annotations in your proto file, while the [grpc-httpjson-transcoding](https://github.com/grpc-ecosystem/grpc-httpjson-transcoding) library doesn't require the generation step, it uses protobuf descriptors as config. It can be used as a component of an existing proxy. Google Cloud Endpoints and the gRPC-JSON transcoder filter in Envoy are using this.


**Behavior differences:**
- By default, gRPC-Gateway does not escape path parameters in the same way. [This can be configured.](mapping/customizing_your_gateway.md#Controlling-path-parameter-unescaping)

## What is the difference between the gRPC-Gateway and gRPC-web?

### Usage

In the gRPC-Gateway, we generate a reverse-proxy from the proto file annotations. In the front-end, we call directly through REST APIs. We can generate an OpenAPI v2 specification that may further be used to generate the frontend client from using `protoc-gen-openapiv2`.

In gRPC-web, the client code is generated directly from the proto files and can be used in the frontend.

### Performance

The gRPC-Gateway parses JSON to the protobuf binary format before sending it to the gRPC server. It then has to parse the reply back from the protobuf binary format to JSON again The parsing overhead has a negative impact on performance.

In gRPC-web, the message is sent in the protobuf binary format already, so there is no additional parsing cost on the proxy side.

### Maintenance

With the gRPC-Gateway, if your proto file changes, we have to regenerate the gateway reverse proxy code. If you are using the HTTP/JSON interface you probably have to change the front-end too, which means making changes in two places.

In gRPC-web, regenerating the files from the proto file will automatically update the front-end client.

---

### Docs Related Projects (`docs/docs/related_projects.md`)

---
layout: default
title: Related projects
nav_order: 8
---

# Related projects

- [grpc-dynamic-gateway](https://github.com/konsumer/grpc-dynamic-gateway)

   A dynamically configured alternative to the grpc-gateway written in Node.

- [rest2grpc](https://www.npmjs.com/package/rest2grpc)

   A statically configured alternative to the grpc-gateway written in Node.

- The Envoy proxy [gRPC-JSON transcoder](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/grpc_json_transcoder_filter)

   An Envoy proxy filter that translates incoming JSON requests to gRPC and back.

- Google Cloud Platform [HTTP/JSON gRPC transcoding](https://cloud.google.com/endpoints/docs/grpc/transcoding)

   A GCP product that behaves like the grpc-gateway.

- gRPC gateway project generator [gen-grpc-gateway-api](https://github.com/akoserwal/gen-grpc-gateway-api) 

   A shell script that can be used to generate a Go project that utilizes the gRPC-gateway and protobuf to expose a simple API.

   Tutorial guide: [Automate gRPC-Gateway project generation in Go with gen-grpc-gateway-api](https://akoserwal.medium.com/automate-grpc-gateway-project-generation-in-golang-with-gen-grpc-gateway-api-015759f1e51b)

- [grpc-starter transcoding](https://danielliu1123.github.io/grpc-starter/docs/extensions/grpc-http-transcoding/)

   A Java implementation of grpc-gateway based on Spring Boot.

- [grpc-rest-api-example](https://github.com/bullet-tooth/grpc-rest-api-example)

   An example repo showcasing how to use gRPC-Gateway with a Java Maven multi-module project.

---

### Docs Using Custom Query Parser (`docs/docs/using_custom_query_parser.md`)

# Custom Query Parameter Parsing in gRPC-Gateway
The gRPC-Gateway allows you to customize the way query parameters are parsed and mapped to your gRPC request messages. This can be particularly useful when dealing with nested fields or complex query parameter mappings that are not directly supported by the default behavior.

## Example: Custom Query Parameter Parser for Nested Fields
Suppose you have a gRPC service definition where you want to map query parameters to a nested message field. Here is how you can achieve this using a custom query parameter parser.

## Protobuf Definition:
```protobuf
syntax = "proto3";

import "google/api/annotations.proto";

package your.service.v1;

message PageOptions {
  int32 limit = 1;
  int32 page = 2;
}

message ListStuffRequest {
  string stuff_uuid = 1;
  PageOptions pagination = 2;
}

message ListStuffResponse {
  repeated string stuff = 1;
}

service MyService {
  rpc ListStuff(ListStuffRequest) returns (ListStuffResponse) {
    option (google.api.http) = {
      get: "/path/to/{stuff_uuid}/stuff"
    };
  }
}
```

## The Problem
The ListStuffRequest message contains a nested PageOptions message that represents pagination options for the list operation. By default, creating a ServerMux in gRPC-Gateway will be able to parse query parameters for the `stuff_uuid` and other basic fields (that are not your own custom message). Given that `PageOptions` is a custom message, and therefore will lead to a nested RequestMessage (the root message), it can only parse query parameters for the `PageOptions` message if they are in the format `url?pagination.limit=x`. If your endpoint constraints require query parameters to be in the format `url?limit=x`, without specifying the full qualified path in the url, you will need to implement a custom parser to map these parameters correctly into the nested PageOptions message.

## Custom Query Parameter Parser

Create a custom [QueryParameterParser](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/runtime/query.go#L30) to handle the nested PageOptions message.
```go
package customparser

import (
	"net/url"
	"strconv"

	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
	"google.golang.org/protobuf/proto"

	your_service_v1 "path/to/your/service/v1"
)

// CustomQueryParameterParser parses query parameters into the appropriate gRPC message fields.
type CustomQueryParameterParser struct{}

// Parse parses query parameters and populates the appropriate fields in the gRPC request message.
func (p *CustomQueryParameterParser) Parse(target proto.Message, values url.Values, filter *utilities.DoubleArray) error {
	switch req := target.(type) {
	// Different messages/requests can have different parsers, of course
	case *your_service_v1.ListStuffRequest:
		return populateListStuffParams(values, req)
	}
	
	return (runtime.DefaultQueryParser{}).Parse(target, values, filter)
}

// populateListStuffParams populates the ListStuffRequest with query parameters.
func populateListStuffParams(values url.Values, r *your_service_v1.ListStuffRequest) error {
	pageOptions := &your_service_v1.PageOptions{}
	
	if limit := values.Get("limit"); limit != "" {
		if parsedLimit, err := strconv.Atoi(limit); err == nil {
			pageOptions.Limit = int32(parsedLimit)
		}
	}
	if page := values.Get("page"); page != "" {
		if parsedPage, err := strconv.Atoi(page); err == nil {
			pageOptions.Page = int32(parsedPage)
		}
	}

	r.Pagination = pageOptions
	return nil
}
```
## Integrate Your Custom Query Parameter Parser in gRPC-Gateway Setup

All you need to do now is update the gRPC-Gateway setup, particularly wherever you are [defining the mux server](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/runtime/mux.go#L293), to [use the custom query parameter parser](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/runtime/mux.go#L110).
```go
package main

import (
	"context"
	"net/http"
	
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/grpc/metadata"
	"google.golang.org/protobuf/encoding/protojson"

	"your_module/path/customparser"
)

// create a new ServeMux with custom parser and other runtime options as needed
func createGRPCGatewayMux() *runtime.ServeMux {
	// whatever custom code you may need before you create the mux...
	
	return runtime.NewServeMux(
		// Custom query parameter parser
		runtime.SetQueryParameterParser(&customparser.CustomQueryParameterParser{}),
		
		// other runtime options you may need...
	)
}
```

---

### Docs Contributing 2020 Season Of Docs (`docs/docs/contributing/2020_season_of_docs.md`)

---
layout: default
title: Google Season of Docs
nav_order: 1
parent: Contributing
---

# 2020 Season of Docs

<div align="center">
<img src="https://developers.google.com/season-of-docs/images/logo/SeasonofDocs_Logo_SecondaryGrey_300ppi.png" />
</div>

The gRPC-Gateway participated in the 2020 [Google Season of Docs](https://g.co/seasonofdocs).
The project was completed by [@iamrajiv](https://github.com/iamrajiv). A summary of the project
work can be found in the
[project report](https://github.com/iamrajiv/GSoD-2020/blob/master/GSoD_2020_Project_Report.md).

---

### Docs Contributing Getting Started (`docs/docs/contributing/getting_started.md`)

---
layout: default
title: Getting started
nav_order: 0
parent: Contributing
---

# How to contribute

See [CONTRIBUTING.md](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/CONTRIBUTING.md).

---

### Docs Development Grpc Gateway V2 Migration Guide (`docs/docs/development/grpc-gateway_v2_migration_guide.md`)

---
layout: default
title: gRPC-Gateway v2 migration guide
nav_order: 0
parent: Development
---

# gRPC-Gateway v2 migration guide

This guide is supposed to help users of the gateway migrate from v1 to v2. See [the original issue](https://github.com/grpc-ecosystem/grpc-gateway/issues/1223) for detailed information on all changes that were made specifically to v2.

The following behavioural defaults have been changed:

## protoc-gen-swagger has been renamed protoc-gen-openapiv2

See [the original issue](https://github.com/grpc-ecosystem/grpc-gateway/issues/675)
for more information. Apart from the new name, the only real difference to users will be a slightly different proto annotation:

```protobuf
import "protoc-gen-openapiv2/options/annotations.proto";
```

instead of

```protobuf
import "protoc-gen-swagger/options/annotations.proto";
```

and

```protobuf
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
```

instead of

```protobuf
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
```

The Bazel rule has been renamed `protoc_gen_openapiv2`.

## The example field in the OpenAPI annotations is now a string

This was a `google.protobuf.Any` type, but it was only used for the JSON representation, and it was breaking some tools and it was generally unclear to the user how it works. It is now a string instead. The value is copied verbatim to the output OpenAPI file. Remember to escape any quotes in the strings.

For example, if you had an example that looked like this:

```protobuf
example: { value: '{ "uuid": "0cf361e1-4b44-483d-a159-54dabdf7e814" }' }
```

It would now look like this:

```protobuf
example: "{\"uuid\": \"0cf361e1-4b44-483d-a159-54dabdf7e814\"}"
```

See [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/a_bit_of_everything.proto) in the example protos for more examples.

## We now use the camelCase JSON names by default

See [the original issue](https://github.com/grpc-ecosystem/grpc-gateway/issues/375) and
[original pull request](https://github.com/grpc-ecosystem/grpc-gateway/pull/540) for more information.

If you want to revert to the old behaviour, configure a custom marshaler with `UseProtoNames: true`:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
		Marshaler: &runtime.JSONPb{
			MarshalOptions: protojson.MarshalOptions{
				UseProtoNames:   true,
				EmitUnpopulated: true,
			},
			UnmarshalOptions: protojson.UnmarshalOptions{
				DiscardUnknown: true,
			},
		},
	}),
)
```

To change the OpenAPI generator behaviour to match, set `json_names_for_fields=false` when generating:

```sh
--openapiv2_out=json_names_for_fields=false:./gen/openapiv2 path/to/my/proto/v1/myproto.proto
```

If using the Bazel rule, set `json_names_for_fields=False`.

## We now emit default values for all fields

See [the original issue](https://github.com/grpc-ecosystem/grpc-gateway/issues/233)
for more information.

If you want to revert to the old behaviour, configure a custom marshaler with
`EmitUnpopulated: false`:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
		Marshaler: &runtime.JSONPb{
			MarshalOptions: protojson.MarshalOptions{
				EmitUnpopulated: false,
			},
			UnmarshalOptions: protojson.UnmarshalOptions{
				DiscardUnknown: true,
			},
		},
	}),
)
```

## We now support google.api.HttpBody message types by default

The `runtime.SetHTTPBodyMarshaler` function has disappeared, and is now
enabled by default. If you for some reason don't want `HttpBody` messages to be
respected, you can disable it by overwriting the default marshaler with one which
does not wrap `runtime.JSONPb` in `runtime.HTTPBodyMarshaler`:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{
		MarshalOptions: protojson.MarshalOptions{
			EmitUnpopulated: true,
		},
		UnmarshalOptions: protojson.UnmarshalOptions{
			DiscardUnknown: true,
		},
	}),
)
```

## runtime.DisallowUnknownFields has been removed

All marshalling settings are now inherited from the configured marshaler. If you wish
to disallow unknown fields, configure a custom marshaler:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.HTTPBodyMarshaler{
		Marshaler: &runtime.JSONPb{
			MarshalOptions: protojson.MarshalOptions{
				EmitUnpopulated: true,
			},
			UnmarshalOptions: protojson.UnmarshalOptions{
				DiscardUnknown: false,
			},
		},
	}),
)
```

## WithLastMatchWins and allow_colon_final_segments=true is now default behaviour

If you were previously specifying these, please remove them, as this is now
the default behaviour. See [the original issue](https://github.com/grpc-ecosystem/grpc-gateway/issues/224) for more information.

There is no workaround for this, as we considered it a correct interpretation of the spec. If this breaks your application, carefully consider the order in which you define your services.

## Error handling configuration has been overhauled

`runtime.HTTPError`, `runtime.OtherErrorHandler`, `runtime.GlobalHTTPErrorHandler`, `runtime.WithProtoErrorHandler` are all gone. Error handling is rewritten around the use of gRPCs Status types. If you wish to configure how the gateway handles errors, please use `runtime.WithErrorHandler` and `runtime.WithStreamErrorHandler`. To handle routing errors (similar to the removed `runtime.OtherErrorHandler`) please use `runtime.WithRoutingErrorHandler`.

## Default query parameter parsing behaviour change

The default behaviour for query parameter parsing has changed to return an `InvalidArgument` (`400 Bad Request`) error when more than one of the same matching query parameters is parsed. Previously, it would log but not return an error, using the first query parameter that matched and ignoring any others. See [the original issue](https://github.com/grpc-ecosystem/grpc-gateway/issues/2632) for more information.

---

### Docs Development Installation For Cygwin (`docs/docs/development/installation_for_cygwin.md`)

---
layout: default
title: Installation for Cygwin
nav_order: 1
parent: Development
---

# Installation for Cygwin

<div>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Cygwin_logo.svg/1024px-Cygwin_logo.svg.png" width="145"/>
</div>

## Installation

First, you need to install the [Go language](https://golang.org/dl/). Please install the latest version, not the one that is listed here.

    wget -N https://storage.googleapis.com/golang/go1.8.1.windows-amd64.msi
    msiexec /i go1.8.1.windows-amd64.msi /passive /promptrestart

Then you need to install [ProtocolBuffers 3.0.0-beta-3](https://github.com/google/protobuf/releases) or later. Use the Windows release as no native Cygwin `protoc` with version 3 is available yet.

    wget -N https://github.com/google/protobuf/releases/download/v3.2.0/protoc-3.2.0-win32.zip`
    7z x protoc-3.2.0-win32.zip -o/usr/local/

Then you need to set up your Go workspace. Create the workspace dir.

    mkdir /home/user/go
    mkdir /home/user/go/bin
    mkdir /home/user/go/pkg
    mkdir /home/user/go/src

From an elevated cmd.exe prompt set the GOPATH variable in Windows and add the `$GOPATH/bin` directory to your path using `reg add` instead of `setx` because [setx can truncate your PATH variable to 1024 characters](https://encrypted.google.com/search?hl=en&q=setx%20truncates%20PATH%201024#safe=off&hl=en&q=setx+truncated+PATH+1024).

    setx GOPATH c:\path\to\your\cygwin\home\user\go /M
    set pathkey="HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment"
    for /F "usebackq skip=2 tokens=2*" %A IN (`reg query %pathkey% /v Path`) do (reg add %pathkey% /f /v Path /t REG_SZ /d "%B;c:\path\to\your\cygwin\home\user\go\bin")

Then `go get -u -v` the following packages:

    go get -u -v github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
    go get -u -v github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
    go get -u -v google.golang.org/protobuf/cmd/protoc-gen-go
    go get -u -v google.golang.org/grpc/cmd/protoc-gen-go-grpc

This will probably fail with a similar output to this:

    github.com/grpc-ecosystem/grpc-gateway (download)
    # cd .; git clone https://github.com/grpc-ecosystem/grpc-gateway C:\path\to\your\cygwin\home\user\go\src\github.com\grpc-ecosystem\grpc-gateway
    Cloning into 'C:\path\to\your\cygwin\home\user\go\src\github.com\grpc-ecosystem\grpc-gateway'...
    fatal: Invalid path '/home/user/go/C:\path\to\your\cygwin\home\user\go\src\github.com\grpc-ecosystem\grpc-gateway': No such file or directory
    package github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway: exit status 128

To fix this you need to run the `go get -u -v` commands and look for all lines starting with `# cd .;`. Copy and paste these lines into your shell and change the clone destination directories.

    git clone https://github.com/grpc-ecosystem/grpc-gateway $(cygpath -u $GOPATH)/src/github.com/grpc-ecosystem/grpc-gateway
    git clone https://github.com/golang/protobuf $(cygpath -u $GOPATH)/src/github.com/golang/protobuf
    git clone https://github.com/google/go-genproto $(cygpath -u $GOPATH)/src/google.golang.org/genproto

Once the clone operations are finished the `go get -u -v` commands shouldn't give you an error anymore.

## Usage

Follow the [instructions](https://github.com/grpc-ecosystem/grpc-gateway#usage) in the [README](https://github.com/grpc-ecosystem/grpc-gateway#readme).

Adjust steps 3, 5 and 7 like this. `protoc` expects native Windows paths.

    protoc -I. -I$(cygpath -w /usr/local/include) -I${GOPATH}/src --go_out=. --go-grpc_out=. ./path/to/your_service.proto
    protoc -I. -I$(cygpath -w /usr/local/include) -I${GOPATH}/src ./path/to/your_service.proto
    protoc -I. -I$(cygpath -w /usr/local/include) -I${GOPATH}/src ./path/to/your_service.proto

Then `cd` into the directory where your entry-point `main.go` file is located and run:

    go get -v

This will fail in this same way as it did during the installation. Look for all lines starting with `# cd .;`. Copy and paste these lines into your shell and change the clone destination directories.

    git clone https://go.googlesource.com/net $(cygpath -u $GOPATH)/src/golang.org/x/net
    git clone https://go.googlesource.com/text $(cygpath -u $GOPATH)/src/golang.org/x/text
    git clone https://github.com/grpc/grpc-go $(cygpath -u $GOPATH)/src/google.golang.org/grpc

Once the clone operations are finished the `go get -v` commands shouldn't give you an error anymore.

Then run:

    go install

This will compile and install your gRPC-Gateway service into `$GOPATH/bin`.

---

### Docs Mapping Binary File Uploads (`docs/docs/mapping/binary_file_uploads.md`)

---
layout: default
title: Binary file uploads
nav_order: 2
parent: Mapping
---

# Binary file uploads

If you need to do a binary file upload, e.g. via;

```sh
curl -X POST -F "attachment=@/tmp/somefile.txt" http://localhost:9090/v1/files
```

then your request will contain the binary data directly and there is no way to model this using gRPC.

What you can do instead is to add a custom route directly on the `mux` instance.

## Custom route on a mux instance

Here we'll setup a handler (`handleBinaryFileUpload`) for `POST` requests: 

```go
// Create a mux instance
mux := runtime.NewServeMux()

// Attachment upload from http/s handled manually
mux.HandlePath("POST", "/v1/files", handleBinaryFileUpload)
```

And then in your handler you can do something like:

```go
func handleBinaryFileUpload(w http.ResponseWriter, r *http.Request, params map[string]string) {
	err := r.ParseForm()
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to parse form: %s", err.Error()), http.StatusBadRequest)
		return
	}

	f, header, err := r.FormFile("attachment")
	if err != nil {
		http.Error(w, fmt.Sprintf("failed to get file 'attachment': %s", err.Error()), http.StatusBadRequest)
		return
	}
	defer f.Close()

	//
	// Now do something with the io.Reader in `f`, i.e. read it into a buffer or stream it to a gRPC client side stream.
	// Also `header` will contain the filename, size etc of the original file.
	//
}
```

---

### Docs Mapping Custom Marshalers (`docs/docs/mapping/custom_marshalers.md`)

---
layout: default
title: Custom marshalers
nav_order: 6
parent: Mapping
---

# Custom marshalers

[`Marshaler`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#Marshaler)
implementations can implement optional additional methods to customize their
behaviour beyond the methods required by the core interface.

## Stream delimiters

By default, a streamed response delimits each response body with a single
newline (`"\n"`). You can change this delimiter by having your marshaler
implement
[`Delimited`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime#Delimited).

For example, to separate each entry with a pipe (`"|"`) instead:

```go
type YourMarshaler struct {
  // ...
}

// ...

func (*YourMarshaler) Delimiter() []byte {
  return []byte("|")
}
```

## Stream content type

By default, a streamed response emits a `Content-Type` header that is the same
for a unary response, from the `ContentType()` method of the
[`Marshaler`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#Marshaler)
interface.

If you require the server to declare a distinct content type for stream
responses versus unary responses, the marshaler must implement
[`StreamContentType`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime#StreamContentType).
This provides the MIME type when specifically responding to a streaming
response.

For example, by default the
[`JSONPb`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime#JSONPb)
marshaler results in `application/json` for its `Content-Type` response header,
irrespective of unary versus streaming. This can be changed for streaming
endpoints by wrapping the marshaler with a custom marshaler that implements
[`StreamContentType`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime#StreamContentType)
to return the [NDJSON](https://github.com/ndjson/ndjson-spec) MIME type for
streaming response endpoints:

```go
type CustomJSONPb struct {
  runtime.JSONPb
}

func (*CustomJSONPb) Delimiter() []byte {
  // Strictly speaking this is already the default delimiter for JSONPb, but
  // providing it here for completeness with an NDJSON marshaler all in one
  // place.
  return []byte("\n")
}

func (*CustomJSONPb) StreamContentType(interface{}) string {
  return "application/x-ndjson"
}
```

---

### Docs Mapping Customizing Openapi Output (`docs/docs/mapping/customizing_openapi_output.md`)

---
layout: default
title: Customizing OpenAPI Output
nav_order: 4
parent: Mapping
---

{% raw %}

# 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:

```protobuf
message MyMessage {
  // This comment will end up directly in your Open API definition
  string uuid = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The UUID field."}];
}
```

You can disable this behavior and exclude all protobuf comments from OpenAPI output via the `ignore_comments` option.

## Using proto options

You can define options on your Protocol Buffer services, operations, messages, enums and field definitions to customize your Open API output. For instance, to customize the [OpenAPI Schema Object](https://swagger.io/specification/v2/#schemaObject) for messages and fields:

```protobuf
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: "Intentionally 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\"}"
        extensions: {
            key: "x-irreversible";
            value {
                bool_value: true;
            }
        }
    };

    string uuid = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {description: "The UUID field."}];
}
```
Enums can be customized like messages:

```protobuf
// NumericEnum is one or zero.
enum NumericEnum {
  option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum) = {
    description: "NumericEnum is one or zero."
    title: "NumericEnum"
    extensions: {
      key: "x-a-bit-of-everything-foo"
      value {
        string_value: "bar"
      }
    }
    external_docs: {
      url: "https://github.com/grpc-ecosystem/grpc-gateway"
      description: "Find out more about ABitOfEverything"
    }
    example: "\"ZERO\""
  };
  // ZERO means 0
  ZERO = 0;
  // ONE means 1
  ONE = 1;
}
```

Operations can also be customized:

```protobuf
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;
                }
            }
        };
    }
}
```

[Swagger Extensions](https://swagger.io/docs/specification/2-0/swagger-extensions/) can be added as key-value pairs to the options. Keys must begin with `x-` and values can be of any type listed [here](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#value). For example:
```
extensions: {
  key: "x-amazon-apigateway-authorizer";
  value {
    struct_value {
      fields {
        key: "type";
        value {
          string_value: "token";
        }
      }
      fields {
        key: "authorizerResultTtlInSeconds";
        value {
          number_value: 60;
        }
      }
    }
  }
}
```

Please see this [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/a_bit_of_everything.proto) for examples of the options being used.

## Using google.api.field_behavior

Google provides a [field option](https://github.com/googleapis/googleapis/blob/master/google/api/field_behavior.proto) for defining the behavior of fields that is also supported:

```protobuf
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 required
- `OUTPUT_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](https://github.com/grpc-ecosystem/grpc-gateway/issues/669).

For `IMMUTABLE` and `INPUT_ONLY` fields, there is an [open issue](https://github.com/OAI/OpenAPI-Specification/issues/1497) 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](https://golang.org/pkg/text/template/) 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](https://en.wikipedia.org/wiki/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:

```sh
--openapiv2_out . --openapiv2_opt use_go_templates=true
```

or:

```sh
--openapiv2_out=use_go_templates=true:.
```

#### Example script

Example of a bash script with the `use_go_templates` flag set to true:

```sh
$ protoc -I. \
    --go_out . --go-grpc_out . \
    --grpc-gateway_out . \
    --openapiv2_out . \
    --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`:

```protobuf
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`:

```markdown
## {{.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](https://swagger.io/tools/swagger-ui/).



#### Postman

This is how the OpenAPI file would be rendered in [Postman](https://www.getpostman.com/).



For a more detailed example of a proto file that has Go, templates enabled, [see the examples](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/use_go_template.proto).

### Using custom values

Custom values can be specified in the [Go templates](https://golang.org/pkg/text/template/) that generate your proto file comments.

A use case might be to interpolate different external documentation URLs when rendering documentation for different environments.

#### How to use it

The `use_go_templates` option has to be enabled as a prerequisite.

Provide customized values in the format of `go_template_args=my_key=my_value`. `{{arg "my_key"}}` will be replaced with `my_value` in the Go template.

Specify the `go_template_args` option multiple times if needed.

```sh
--openapiv2_out . --openapiv2_opt use_go_templates=true --openapiv2_opt go_template_args=my_key1=my_value1 --openapiv2_opt go_template_args=my_key2=my_value2
...
```

#### Example script

Example of a bash script with the `use_go_templates` flag set to true and custom template values set:

```sh
$ protoc -I. \
    --go_out . --go-grpc_out . \
    --grpc-gateway_out . \
    --openapiv2_out . \
    --openapiv2_opt use_go_templates=true \
    --openapiv2_opt go_template_args=environment=test1 \
    --openapiv2_opt go_template_args=environment_label=Test1 \
    path/to/my/proto/v1/myproto.proto
```

#### Example proto file

Example of a proto file with Go templates and custom values:

```protobuf
service LoginService {
    // Login (Environment: {{arg "environment_label"}})
    //
    // {{.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}}".
    // This only works in the {{arg "environment"}} domain.
    //
    rpc Login (LoginRequest) returns (LoginReply) {
        option (google.api.http) = {
            post: "/v1/example/login"
            body: "*"
        };
    }
}
```

## Other plugin options

A comprehensive list of OpenAPI plugin options can be found [here](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/protoc-gen-openapiv2/main.go). Options can be passed via `protoc` CLI:

```sh
--openapiv2_out . --openapiv2_opt bar=baz,color=red
```

Or, with `buf` in `buf.gen.yaml`:

```yaml
  - name: openapiv2
    out: foo
    opt: bar=baz,color=red
```

### Merging output

If your protobuf definitions are spread across multiple files, the OpenAPI plugin will create a file for each `.proto` input. This may make sense for Go bindings, since they still share a package space, but fragmenting OpenAPI specifications across multiple files changes the schema itself.

To merge disparate `.proto` inputs into a single OpenAPI file, use the `allow_merge` and `merge_file_name` options.

`opt: allow_merge=true,merge_file_name=foo` will result in a single `foo.swagger.json`. Note that you may need to set
the [generation strategy](https://docs.buf.build/configuration/v1/buf-gen-yaml/#strategy) to `all` when merging many files:

```yaml
  - name: openapiv2
    out: foo
    strategy: all
    opt: allow_merge=true,merge_file_name=foo
```

File-level options of the merged output (such as `info`, `host` or `tags`) are taken from the first input file that has
an `openapiv2_swagger` option, either as an annotation or in the `openapi_configuration` file. File-level options set
on any other input file are ignored.

### Enums as integers

To generate enums as integers instead of strings, use `enums_as_ints`.

`opt: enums_as_ints=true` will result in:


```json
{
    "name": "enumValue",
    "description": " - Example enums",
    "in": "query",
    "required": false,
    "type": "int",
    "enum": [
        0,
        1
    ],
    "default": 0
},
```

### Omitting the default value of enums

If you define enum types with non default value such as declaring 0 value with UNKNOWN and want to omit the default value from generated swagger file, use `omit_enum_default_value`.
This option also applies if enums_as_ints option is enalbled to generate enums as integer.

`opt: omit_enum_default_value=true` will result in:

Input Example:
```
enum enumValue {
    UNKNOWN = 0;
    FOO = 1;
}
```

Output json:
```json
{
    "name": "enumValue",
    "description": " - Example enums",
    "in": "query",
    "required": false,
    "type": "string",
    "enum": [
        "FOO"
    ]
},
```

### Hiding fields, methods, services and enum values

If you require internal or unreleased fields and APIs to be hidden from your API documentation, [`google.api.VisibilityRule`](https://github.com/googleapis/googleapis/blob/9916192ab15e3507e41ba2c5165182fec06120d0/google/api/visibility.proto#L89) annotations can be added to customize where they are generated. Combined with the option `visibility_restriction_selectors`, overlapping rules will appear in the OpenAPI output.

`visibility_restriction_selectors` can be declared multiple times as an option to include multiple visibility restrictions in the output.
e.g. if you are using `buf`:

```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - visibility_restriction_selectors=PREVIEW
      - visibility_restriction_selectors=INTERNAL
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=visibility_restriction_selectors=PREVIEW --openapiv2_opt=visibility_restriction_selectors=INTERNAL ./path/to/file.proto
```

Elements without `google.api.VisibilityRule` annotations will appear as usual in the generated output.

These restrictions and selectors are completely arbitrary and you can define whatever values or hierarchies you want. In this example we use `INTERNAL` and `PREVIEW`, but `INTERNAL`, `ALPHA`, `BETA`, `RELEASED`, or anything else could be used if you wish.

Note: Annotations are only supported on Services, Methods, Fields and Enum Values.

`opt: visibility_restriction_selectors=PREVIEW` will result in:

Input Example:
```protobuf
service Echo {
    rpc EchoInternal(VisibilityRuleSimpleMessage) returns (VisibilityRuleSimpleMessage) {
        option (google.api.method_visibility).restriction = "INTERNAL";
        option (google.api.http) = {
            get: "/v1/example/echo_internal"
        };
    }
    rpc EchoInternalAndPreview(VisibilityRuleSimpleMessage) returns (VisibilityRuleSimpleMessage) {
        option (google.api.method_visibility).restriction = "INTERNAL,PREVIEW";
        option (google.api.http) = {
            get: "/v1/example/echo_internal_and_preview"
        };
    }
}

message VisibilityRuleSimpleMessage {
     enum VisibilityEnum {
          UNSPECIFIED = 0;
          VISIBLE = 1;
          INTERNAL = 2 [(google.api.value_visibility).restriction = "INTERNAL"];
          PREVIEW = 3 [(google.api.value_visibility).restriction = "INTERNAL,PREVIEW"];
     }

     string internal_field = 1 [(google.api.field_visibility).restriction = "INTERNAL"];
     string preview_field = 2 [(google.api.field_visibility).restriction = "INTERNAL,PREVIEW"];
     VisibilityEnum an_enum = 3;
}
```

Output json:
```
/* Detailed source-code truncated for AI context efficiency. */
```

For a more in depth example see [visibility_rule_echo_service.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/visibility_rule_echo_service.proto) and the following output files for different values of `visibility_restriction_selectors`:
- [`visibility_restriction_selectors=PREVIEW`](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/visibility_rule_preview_echo_service.swagger.json)
- [`visibility_restriction_selectors=INTERNAL`](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/visibility_rule_internal_echo_service.swagger.json)
- [`visibility_restriction_selectors=INTERNAL,visibility_restriction_selectors=PREVIEW`](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/visibility_rule_preview_and_internal_echo_service.swagger.json)
- [Not set](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/visibility_rule_none_echo_service.swagger.json)

### Path parameters

When defining HTTP bindings with path parameters that contain multiple path segments, as suggested by the [Google AIPs](https://google.aip.dev/), the path parameter names are numbered to avoid generating duplicate paths in the OpenAPI file.

For example, consider:
```protobuf
service LibraryService {
  rpc GetShelf(GetShelfRequest) returns (Shelf) {
    option (google.api.http) = {
      get: "/v1/{name=shelves/*}"
    };
  }
  rpc GetBook(GetBookRequest) returns (Book) {
    option (google.api.http) = {
      get: "/v1/{name=shelves/*/books/*}"
    };
  }
}

message GetShelfRequest {
  string name = 1;
}

message GetBookRequest {
  string name = 1;
}
```

This will generate the following paths:
- `/v1/{name}`
- `/v1/{name_1}`

To override the path parameter names, annotate the field used as path parameter:
```protobuf
message GetShelfRequest {
  string name = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {field_configuration: {path_param_name: "shelfName"}}];
}
message GetBookRequest {
  string name = 1 [(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {field_configuration: {path_param_name: "bookName"}}];
}
```

This will instead generate the following paths:
- `/v1/{shelfName}`
- `/v1/{bookName}`

Note that path parameters in OpenAPI does not support values with `/`, as discussed in
[Support for path parameters which can contain slashes #892](https://github.com/OAI/OpenAPI-Specification/issues/892),
so tools as Swagger UI will URL encode any `/` provided as parameter value. A possible workaround for this is to write
a custom post processor for your OAS file to replace any path parameter with `/` into multiple parameters.

#### Expand path parameters containing sub-path segments

Alternative to the above, you can enable the `expand_slashed_path_patterns` compiler option to expand path parameters containing sub-path segments into the URI.

For example, consider:
```protobuf
rpc GetBook(GetBookRequest) returns (Book) {
  option (google.api.http) = {
    get: "/v1/{name=publishers/*/books/*}"
  };
}
```

Where the `GetBook` has a path parameter `name` with a pattern `publishers/*/books/*`. When you enable the `expand_slashed_path_patterns=true` option the path pattern is expanded into the URI and each wildcard in the pattern is transformed into new path parameter. The generated schema for previous protobuf is:

```JSON
{
 "/v1/publishers/{publisher}/books/{book}": {
      "get": {
        "parameters": [
          {
            "name": "publisher",
            "in": "path",
            "required": true,
            "type": "string",
          },
          {
            "name": "book",
            "in": "path",
            "required": true,
            "type": "string",
          }
        ]
      }
    }
}
```

The URI is now pretty descriptive and there are two path parameters `publisher` and `book` instead of one `name`. The name of the new parameters is derived from the path segment before the wildcard in the pattern.

Caveats:

- the fact that the original `name` parameter is missing might complicate the usage of the API if you intend to pass in the `name` parameters from the resources,
- when the `expand_slashed_path_patterns` compiler flag is enabled, the [`path_param_name`](#path-parameters) field annotation is ignored.

### Output format

By default the output format is JSON, but it is possible to configure it using the `output_format` option. Allowed values are: `json`, `yaml`. The output format will also change the extension of the output files.

For example, if using `buf`:
```yaml
  - name: openapiv2
    out: pkg
    opt: output_format=yaml
```

Input example:
```protobuf
syntax = "proto3";

package helloproto.v1;
option go_package = "helloproto/v1;helloproto";

import "google/api/annotations.proto";

service EchoService {
    rpc Hello(HelloReq) returns (HelloResp) {
        option (google.api.http) = {
            get: "/api/hello"
        };
    }
}

message HelloReq {
    string name = 1;
}

message HelloResp {
    string message = 1;
}
```

Output:
```yaml
swagger: "2.0"
info:
  title: helloproto/v1/example.proto
  version: version not set
tags:
- name: EchoService
consumes:
- application/json
produces:
- application/json
paths:
  /api/hello:
    get:
      operationId: EchoService_Hello
      responses:
        "200":
          description: A successful response.
          schema:
            $ref: '#/definitions/v1HelloResp'
        default:
          description: An unexpected error response.
          schema:
            $ref: '#/definitions/rpcStatus'
      parameters:
      - name: name
        in: query
        required: false
        type: string
      tags:
      - EchoService
definitions:
  protobufAny:
    type: object
    properties:
      '@type':
        type: string
    additionalProperties: {}
  rpcStatus:
    type: object
    properties:
      code:
        type: integer
        format: int32
      message:
        type: string
      details:
        type: array
        items:
          $ref: '#/definitions/protobufAny'
  v1HelloResp:
    type: object
    properties:
      message:
        type: string
```

### Disable service tag generation

By default service tags are generated for backend services, but it is possible to disable it using the `disable_service_tags` option. Allowed values are: `true`, `false`.

For example, if you are using `buf`:
```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - disable_service_tags=true
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=disable_service_tags=true ./path/to/file.proto
```

Input example:
```protobuf
syntax = "proto3";

package helloproto.v1;
option go_package = "helloproto/v1;helloproto";

import "google/api/annotations.proto";

service EchoService {
    rpc Hello(HelloReq) returns (HelloResp) {
        option (google.api.http) = {
            get: "/api/hello"
        };
    }
}

message HelloReq {
    string name = 1;
}

message HelloResp {
    string message = 1;
}
```

Output (tags object are not generated):
```yaml
swagger: "2.0"
info:
  title: helloproto/v1/example.proto
  version: version not set
consumes:
  - application/json
produces:
  - application/json
paths:
  /api/hello:
    get:
      operationId: EchoService_Hello
```

### Allow proto files without a go_package option

By default, `protoc-gen-openapiv2` requires every proto file to declare a `go_package` option, even though the generator never emits Go source and has no real use for the value. Set `ignore_go_package_option=true` to tolerate proto files that don't declare one — a placeholder import path is synthesized instead of erroring. Note: if `generate_x_go_type` is also enabled, the synthesized placeholder (not a real Go import path) will appear in the generated `x-go-type` extension for any file that used this fallback.

For example, if you are using `buf`:
```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - ignore_go_package_option=true
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=ignore_go_package_option=true ./path/to/file.proto
```

### Disable default responses

By default a 200 OK response is rendered for each service operation. But it is possible to disable this and explicitly define your service's responses, using the `disable_default_responses` option. Allowed values are: `true`, `false`.

**Note**: This does not alter the behavior of the gateway itself and should be coupled with a `ForwardResponseWriter` when altering status codes, see [Controlling HTTP Response Codes](https://grpc-ecosystem.github.io/grpc-gateway/docs/mapping/customizing_your_gateway/#controlling-http-response-status-codes).

For example, if you are using `buf`:

```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - disable_default_responses=true
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=disable_default_responses=true ./path/to/file.proto
```

Input example:

```protobuf
syntax = "proto3";

package helloproto.v1;

import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option go_package = "helloproto/v1;helloproto";

service EchoService {
  rpc Hello(HelloReq) returns (HelloResp) {
    option (google.api.http) = {get: "/api/hello"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      responses: {
        key: "201",
        value: {
          description: "Created";
          schema: {
            json_schema: {ref: ".helloproto.v1.HelloResp"}
          }
        }
      };
    };
  }
}

message HelloReq {
  string name = 1;
}

message HelloResp {
  string message = 1;
}
```

Output (default response not generated):

```yaml
swagger: "2.0"
info:
  title: helloproto/v1/hello.proto
  version: version not set
consumes:
  - application/json
produces:
  - application/json
paths:
  /api/hello:
    get:
      operationId: EchoService_Hello
      responses:
        "201":
          description: Created
          schema:
            $ref: "#/definitions/v1HelloResp"
      parameters:
        - name: name
          in: query
          required: false
          type: string
definitions:
  v1HelloResp:
    type: object
    properties:
      message:
        type: string
```

### Omit array item type when $ref is a sibling

By default, when generating OpenAPI schemas for array items that reference other definitions, both `type: object` and `$ref` properties are included. However, some strict OpenAPI validators enforce the `no-$ref-siblings` rule, which prohibits having `$ref` alongside other properties at the same level. To comply with this strict validation, you can use the `omit_array_item_type_when_ref_sibling` option. When enabled, this option omits the `type: object` property from array items when a `$ref` is present, since `$ref` already implies the type. Allowed values are: `true`, `false`.

**Note**: This option only affects the generated OpenAPI specification and does not alter the behavior of the gateway itself.

For example, if you are using `buf`:

```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - omit_array_item_type_when_ref_sibling=true
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=omit_array_item_type_when_ref_sibling=true ./path/to/file.proto
```

Input example:

```protobuf
syntax = "proto3";

package example.v1;

import "google/api/annotations.proto";

option go_package = "example/v1;example";

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

message GetItemsRequest {}

message GetItemsResponse {
  repeated Item items = 1;
}

message Item {
  string id = 1;
  string name = 2;
}
```

Output without the option (default behavior):

```yaml
definitions:
  v1GetItemsResponse:
    type: object
    properties:
      items:
        type: array
        items:
          type: object  # This can violate strict no-$ref-siblings rule
          $ref: "#/definitions/v1Item"
  v1Item:
    type: object
    properties:
      id:
        type: string
      name:
        type: string
```

Output with `omit_array_item_type_when_ref_sibling=true`:

```yaml
definitions:
  v1GetItemsResponse:
    type: object
    properties:
      items:
        type: array
        items:
          $ref: "#/definitions/v1Item"  # type: object is omitted
  v1Item:
    type: object
    properties:
      id:
        type: string
      name:
        type: string
```

### Custom HTTP Header Request Parameters

By default the parameters for each operation are generated from the protocol buffer definition however you can extend the parameters to include extra HTTP headers if required.

**NOTE**: These annotations do not alter the behaviour of the gateway and must be coupled with custom header parsing behaviour in the application. Also be aware that adding header parameters can alter the forwards and backwards compatibility of the schema. You must also set a type for your header which can be one of `STRING`, `INTEGER`, `NUMBER` or `BOOLEAN`.

```protobuf
syntax = "proto3";

package helloproto.v1;

import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

option go_package = "helloproto/v1;helloproto";

service EchoService {
  rpc Hello(HelloReq) returns (HelloResp) {
    option (google.api.http) = {get: "/api/hello"};
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      parameters: {
        headers: {
          name: "X-Foo";
          description: "Foo Header";
          type: STRING,
          required: true;
        };
        headers: {
          name: "X-Bar";
          description: "Bar Header";
          type: NUMBER,
        };
      };
    };
  }
}

message HelloReq {
  string name = 1;
}

message HelloResp {
  string message = 1;
}
```

Output:

```yaml
swagger: "2.0"
info:
  title: helloproto/v1/hello.proto
  version: version not set
consumes:
  - application/json
produces:
  - application/json
paths:
  /api/hello:
    get:
      operationId: Hello
      responses:
        "200":
          description: A successful response.
          schema:
            $ref: "#/definitions/helloproto.v1.HelloResp"
      parameters:
        - name: name
          in: query
          required: false
          type: string
        - name: X-Foo
          description: Foo Header
          in: header
          required: true
          type: string
        - name: X-Bar
          description: Bar Header
          in: header
          required: false
          type: number
definitions:
  helloproto.v1.HelloResp:
    type: object
    properties:
      message:
        type: string
```

### Ignore comments

If you want to exclude all protobuf comments (such as `// buf:lint:ignore`) from OpenAPI output, use the `ignore_comments` option. Allowed values are: `true`, `false`.

**Note**: `ignore_comments` and `use_go_templates` are mutually exclusive and cannot be enabled at the same time.

If you are using `buf`:
```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - ignore_comments=true
```

or with `protoc`:

```sh
protoc --openapiv2_out=. --openapiv2_opt=ignore_comments=true ./path/to/file.proto
```

### Removing internal comments

If you want to remove internal comments from the from OpenAPI output (such as `TODO` and `FIXME` directives) you can use the `remove_internal_comments` option.
If set to `true`, this will remove all comment text located between `(--` and `--)` as per [AIP 192: Internal comments](https://google.aip.dev/192#internal-comments).

### Preserve RPC Path Order

By default, generated Swagger files emit paths found in proto files in alphabetical order. If you would like to 
preserve the order of emitted paths to mirror the path order found in proto files, you can use the `preserve_rpc_order` option. If set to `true`, this option will ensure path ordering is preserved for Swagger files with both json and yaml formats.

This option will also ensure path ordering is preserved in the following scenarios:

1. When using additional bindings, paths will preserve their ordering within an RPC.
2. When using multiple services, paths will preserve their ordering between RPCs in the whole protobuf file.
3. When merging protobuf files, paths will preserve their ordering depending on the order of files specified on the command line.

`preserve_rpc_order` can be passed via the `protoc` CLI:

```sh
protoc --openapiv2_out=. --openapiv2_opt=preserve_rpc_order=true ./path/to/file.proto
```

Or, with `buf` in `buf.gen.yaml`:

```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - preserve_rpc_order=true
```

### Enable RPC deprecation

With `enable_rpc_deprecation` option you can deprecate openapi method using standard method's option. Allowed values are: `true`, `false`.

For example, if you are using `buf`:

```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - enable_rpc_deprecation=true
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=enable_rpc_deprecation=true ./path/to/file.proto
```

Input example:

```protobuf
syntax = "proto3";

package helloproto.v1;

import "google/api/annotations.proto";

option go_package = "helloproto/v1;helloproto";

service EchoService {
  rpc Hello(HelloReq) returns (HelloResp) {
    option deprecated = true;
    option (google.api.http) = {get: "/api/hello"};
  }
}

message HelloReq {
  string name = 1;
}

message HelloResp {
  string message = 1;
}
```

Output:

```yaml
swagger: "2.0"
info:
  title: helloproto/v1/example.proto
  version: version not set
tags:
  - name: EchoService
consumes:
  - application/json
produces:
  - application/json
paths:
  /api/hello:
    get:
      operationId: EchoService_Hello
      responses:
        "200":
          description: A successful response.
          schema:
            $ref: '#/definitions/v1HelloResp'
        default:
          description: An unexpected error response.
          schema:
            $ref: '#/definitions/rpcStatus'
      parameters:
        - name: name
          in: query
          required: false
          type: string
      tags:
        - EchoService
      deprecated: true
definitions:
  protobufAny:
    type: object
    properties:
      '@type':
        type: string
    additionalProperties: {}
  rpcStatus:
    type: object
    properties:
      code:
        type: integer
        format: int32
      message:
        type: string
      details:
        type: array
        items:
          type: object
          $ref: '#/definitions/protobufAny'
  v1HelloResp:
    type: object
    properties:
      message:
        type: string
```

### Deprecating parameters

With the `enable_field_deprecation` option, OpenAPI parameters will be marked as deprecated based on the protobuf `deprecated` field option. Allowed values are: `true`, `false`.

For example, if you are using `buf`:

```yaml
version: v1
plugins:
  - name: openapiv2
    out: .
    opt:
      - enable_field_deprecation=true
```

or with `protoc`

```sh
protoc --openapiv2_out=. --openapiv2_opt=enable_field_deprecation=true ./path/to/file.proto
```

Input example:

```protobuf
message SearchRequest {
  string legacy_filter = 1 [deprecated = true];
  string query = 2;
}
```

Output (excerpt):

```yaml
paths:
  /v1/search:
    get:
      parameters:
        - name: legacy_filter
          in: query
          required: false
          type: string
          deprecated: true
        - name: query
          in: query
          required: false
          type: string
```

If you prefer to leave the protobuf definition active, you can use the `field_configuration.deprecated` annotation on the `openapiv2_field` option instead:

```protobuf
message SearchRequest {
  string legacy_filter = 1 [
    (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
      description: "Legacy filter syntax. Prefer the new 'query' field."
      field_configuration: { deprecated: true }
    }
  ];
  string query = 2;
}
```

This keeps the protobuf field untouched but still emits a deprecated parameter in the generated spec:

```yaml
paths:
  /v1/search:
    get:
      parameters:
        - name: legacy_filter
          in: query
          required: false
          type: string
          description: Legacy filter syntax. Prefer the new 'query' field.
          deprecated: true
        - name: query
          in: query
          required: false
          type: string
```

If you set both the protobuf `deprecated = true` option and `field_configuration.deprecated`, the OpenAPI parameter is marked as deprecated regardless of the `enable_field_deprecation` option.


{% endraw %}

---

### Docs Mapping Customizing Your Gateway (`docs/docs/mapping/customizing_your_gateway.md`)

---
layout: default
title: Customizing your gateway
nav_order: 5
parent: Mapping
---

# Customizing your gateway

## Message serialization

### Custom serializer

You might want to serialize request/response messages in MessagePack instead of JSON, for example:

1. Write a custom implementation of
   [`Marshaler`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#Marshaler).
   See [Custom marshalers](custom_marshalers.md) for some additional
   customization options.

2. Register your marshaler with [`WithMarshalerOption`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#WithMarshalerOption).

   e.g.

   ```go
   var m your.MsgPackMarshaler
   mux := runtime.NewServeMux(
   	runtime.WithMarshalerOption("application/x-msgpack", m),
   )
   ```

You can see [the default implementation for JSON](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/runtime/marshal_jsonpb.go) for reference.

### Using proto names in JSON

The protocol buffer compiler generates camelCase JSON tags that are used by default.
If you want to use the exact case used in the proto files, set `UseProtoNames: true`:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{
		MarshalOptions: protojson.MarshalOptions{
			UseProtoNames: true,
		},
		UnmarshalOptions: protojson.UnmarshalOptions{
			DiscardUnknown: true,
		},
	}),
)
```

### Pretty-print JSON responses when queried with ?pretty

You can have Elasticsearch-style `?pretty` support in your gateway's endpoints as follows:

1. Wrap the ServeMux using a stdlib [`http.HandlerFunc`](https://golang.org/pkg/net/http/#HandlerFunc) that translates the provided query parameter into a custom `Accept` header.

2. Register a pretty-printing marshaler for that MIME code.

For example:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption("application/json+pretty", &runtime.JSONPb{
		MarshalOptions: protojson.MarshalOptions{
			Indent: "  ",
			Multiline: true, // Optional, implied by presence of "Indent".
		},
		UnmarshalOptions: protojson.UnmarshalOptions{
			DiscardUnknown: true,
		},
	}),
)
prettier := func(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// checking Values as map[string][]string also catches ?pretty and ?pretty=
		// r.URL.Query().Get("pretty") would not.
		if _, ok := r.URL.Query()["pretty"]; ok {
			r.Header.Set("Accept", "application/json+pretty")
		}
		h.ServeHTTP(w, r)
	})
}
http.ListenAndServe(":8080", prettier(mux))
```

Now, either when passing the header `Accept: application/json+pretty` or appending `?pretty` to your HTTP endpoints, the response will be pretty-printed.

Note that this will conflict with any methods having input messages with fields named `pretty`; also, this example code does not remove the query parameter `pretty` from further processing.

## Customize unmarshaling per Content-Type

Having different unmarshaling options per Content-Type is as easy as configuring a custom marshaler:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption("application/json+strict", &runtime.JSONPb{
		UnmarshalOptions: &protojson.UnmarshalOptions{
			DiscardUnknown: false, // explicit "false", &protojson.UnmarshalOptions{} would have the same effect
		},
	}),
)
```

Note: The incoming `Authorization` HTTP header can not be removed or overwritten. It will always be forwarded in the gRPC metadata under the `authorization` key. However, values can be appended.

## Mapping from HTTP request headers to gRPC client metadata

You might not like [the default mapping rule](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#DefaultHeaderMatcher) and might want to pass through all the HTTP headers, for example:

1. Write a [`HeaderMatcherFunc`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#HeaderMatcherFunc).

2. Register the function with [`WithIncomingHeaderMatcher`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#WithIncomingHeaderMatcher)

   e.g.

   ```go
   func CustomMatcher(key string) (string, bool) {
   	switch key {
   	case "X-Custom-Header1":
   		return key, true
   	case "X-Custom-Header2":
   		return "custom-header2", true
   	default:
   		return key, false
   	}
   }

   mux := runtime.NewServeMux(
   	runtime.WithIncomingHeaderMatcher(CustomMatcher),
   )
   ```

To keep the [default mapping rule](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#DefaultHeaderMatcher) alongside with your own rules write:

```go
func CustomMatcher(key string) (string, bool) {
	switch key {
	case "X-User-Id":
		return key, true
	default:
		return runtime.DefaultHeaderMatcher(key)
	}
}
```

It will work with both:

```sh
$ curl --header "x-user-id: 100d9f38-2777-4ee2-ac3b-b3a108f81a30" ...
```

and

```sh
$ curl --header "X-USER-ID: 100d9f38-2777-4ee2-ac3b-b3a108f81a30" ...
```

To access this header on gRPC server side use:

```go
userID := ""
if md, ok := metadata.FromIncomingContext(ctx); ok {
	if uID, ok := md["x-user-id"]; ok {
		userID = strings.Join(uID, ",")
	}
}
```

## Mapping from gRPC server metadata to HTTP response headers

Use [`WithOutgoingHeaderMatcher`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#WithOutgoingHeaderMatcher). See [gRPC metadata docs](https://github.com/grpc/grpc-go/blob/master/Documentation/grpc-metadata.md) for more info on sending / receiving gRPC metadata, for example:

```go
if appendCustomHeader {
	grpc.SendHeader(ctx, metadata.New(map[string]string{
		"x-custom-header1": "value",
	}))
}
```

## Mutate response messages or set response headers

### Set HTTP headers

You might want to return a subset of response fields as HTTP response headers; You might want to simply set an application-specific token in a header. Or you might want to mutate the response messages to be returned.

1. Write a filter function.

```go
func myFilter(ctx context.Context, w http.ResponseWriter, resp proto.Message) error {
	t, ok := resp.(*externalpb.Tokenizer)
	if ok {
		w.Header().Set("X-My-Tracking-Token", t.Token)
		t.Token = ""
	}
	return nil
}
```

2. Register the filter with [`WithForwardResponseOption`](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#WithForwardResponseOption)

e.g.

```go
mux := runtime.NewServeMux(
	runtime.WithForwardResponseOption(myFilter),
)
```

### Controlling HTTP response status codes

To have the most control over the HTTP response status codes, you can use custom metadata.

While handling the rpc, set the intended status code:

```go
_ = grpc.SetHeader(ctx, metadata.Pairs("x-http-code", "401"))
```

Now, before sending the HTTP response, we need to check for this metadata pair and explicitly set the status code for the response if found.
To do so, create a function and hook it into the gRPC-Gateway as a Forward Response Option.

The function looks like this:

```go
func httpResponseModifier(ctx context.Context, w http.ResponseWriter, p proto.Message) error {
	md, ok := runtime.ServerMetadataFromContext(ctx)
	if !ok {
		return nil
	}

	// set http status code
	if vals := md.HeaderMD.Get("x-http-code"); len(vals) > 0 {
		code, err := strconv.Atoi(vals[0])
		if err != nil {
			return err
		}
		// delete the headers to not expose any grpc-metadata in http response
		delete(md.HeaderMD, "x-http-code")
		delete(w.Header(), "Grpc-Metadata-X-Http-Code")
		w.WriteHeader(code)
	}

	return nil
}
```

And it gets hooked into the gRPC-Gateway with:

```go
gwMux := runtime.NewServeMux(
	runtime.WithForwardResponseOption(httpResponseModifier),
)
```

Additional responses can be added to the Protocol Buffer definitions to match the new status codes:

```protobuf
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      post: "/v1/example/echo"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      responses: {
        key: "201"
        value: {
          description: "A successful response."
          schema: {
            json_schema: {
              ref: ".mypackage.HelloReply"
            }
          }
        }
      }
    };
  }

  rpc SayGoodbye (GoodbyeRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/v1/example/echo/{id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      responses: {
        key: "204"
        value: {
          description: "A successful response."
          schema: {}
        }
      }
    };
  }
}
```

### Fully Overriding Custom HTTP Responses

To fully override custom HTTP responses, you can use both a Forward Response Option and a Custom Marshaler.

For example with proto response message as:

```proto
message CreateUserResponse {
  string name = 1;
}
```

The default HTTP response:

```json5
HTTP 200 OK
Content-Type: application/json

{"name":"John Doe"}
```

But you want to return a `201 Created` status code along with a custom response structure:

```json5
HTTP 201 Created
Content-Type: application/json

{"success":true,"data":{"name":"John Doe"}}
```

First, set up the gRPC-Gateway with the custom options:

```go
mux := runtime.NewServeMux(
  runtime.WithForwardResponseOption(setStatus),
  runtime.WithForwardResponseRewriter(responseEnvelope),
)
```

Define the `setStatus` function to handle specific response types:

```go
func setStatus(ctx context.Context, w http.ResponseWriter, m protoreflect.ProtoMessage) error {
  switch v := m.(type) {
  case *pb.CreateUserResponse:
    w.WriteHeader(http.StatusCreated)
  }
  // keep default behavior
  return nil
}
```

Define the `responseEnvelope` function to rewrite the response to a different type/shape:

```go
func responseEnvelope(_ context.Context, response proto.Message) (interface{}, error) {
  switch v := response.(type) {
  case *pb.CreateUserResponse:
    // wrap the response in a custom structure
    return map[string]any{
      "success": true,
      "data":    response,
    }, nil
  }
  return response, nil
}
```

In this setup:

- The `setStatus` function intercepts the response and uses its type to send `201 Created` only when it sees `*pb.CreateUserResponse`.
- The `responseEnvelope` function ensures that specific types of responses are wrapped in a custom structure before being sent to the client.

❗ **NOTE:** Using `WithForwardResponseRewriter` is partially incompatible with OpenAPI annotations. Because response
rewriting happens at runtime, it is not possible to represent that in `protoc-gen-openapiv2` output.

## Error handler

To override error handling for a `*runtime.ServeMux`, use the
`runtime.WithErrorHandler` option. This will configure all unary error
responses to pass through this error handler.

## Stream Error Handler

The error handler described in the previous section applies only to RPC methods that have a unary response.

When the method has a streaming response, gRPC-Gateway handles that by emitting a newline-separated stream of "chunks". Each chunk is an envelope that can contain either a response message or an error. Only the last chunk will include an error, and only when the RPC handler ends abnormally (i.e. with an error code).

Because of the way the errors are included in the response body, the other error handler signature is insufficient. So for server streams, you must install a _different_ error handler:

```go
mux := runtime.NewServeMux(
	runtime.WithStreamErrorHandler(handleStreamError),
)
```

The signature of the handler is much more rigid because we need to know the structure of the error payload to properly encode the "chunk" schema into an OpenAPI spec.

So the function must return a `*runtime.StreamError`. The handler can choose to omit some fields and can filter/transform the original error, such as stripping stack traces from error messages.

Here's an example custom handler:

```go
// handleStreamError overrides default behavior for computing an error
// message for a server stream.
//
// It uses a default "502 Bad Gateway" HTTP code, only emits "safe"
// messages and does not set the details field (so it will
// be omitted from the resulting JSON object that is sent to client).
func handleStreamError(ctx context.Context, err error) *status.Status {
	code := codes.Internal
	msg := "unexpected error"
	if s, ok := status.FromError(err); ok {
		code = s.Code()
		// default message, based on the gRPC status
		msg = s.Message()
		// see if error details include "safe" message to send
		// to external callers
		for _, msg := range s.Details() {
			if safe, ok := msg.(*SafeMessage); ok {
				msg = safe.Text
				break
			}
		}
	}
	return status.Errorf(code, msg)
}
```

If no custom handler is provided, the default stream error handler will include any gRPC error attributes (code, message, detail messages), if the error being reported includes them. If the error does not have these attributes, a gRPC code of `Unknown` (2) is reported.

## Controlling path parameter unescaping



By default, gRPC-Gateway unescapes the entire URL path string attempting to route a request. This causes routing errors when the path parameter contains an illegal character such as `/`.

To replicate the behavior described in [google.api.http](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto#L224), use [runtime.WithUnescapingMode()](https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/runtime?tab=doc#WithUnescapingMode) to configure the unescaping behavior, as in the example below:

```go
mux := runtime.NewServeMux(
	runtime.WithUnescapingMode(runtime.UnescapingModeAllExceptReserved),
)
```

For multi-segment parameters (e.g. `{id=**}`) [RFC 6570](https://tools.ietf.org/html/rfc6570) Reserved Expansion characters are left escaped and the gRPC API will need to unescape them.

To replicate the default V2 escaping behavior but also allow passing pct-encoded `/` characters, the ServeMux can be configured as in the example below:

```go
mux := runtime.NewServeMux(
	runtime.WithUnescapingMode(runtime.UnescapingModeAllCharacters),
)
```

## Routing Error handler

To override the error behavior when `*runtime.ServeMux` was not able to serve the request due to routing issues, use the `runtime.WithRoutingErrorHandler` option.

This will configure all HTTP routing errors to pass through this error handler. The default behavior is to map HTTP error codes to gRPC errors.

HTTP statuses and their mappings to gRPC statuses:

- HTTP `404 Not Found` -> gRPC `5 NOT_FOUND`
- HTTP `405 Method Not Allowed` -> gRPC `12 UNIMPLEMENTED`
- HTTP `400 Bad Request` -> gRPC `3 INVALID_ARGUMENT`

This method is not used outside of the initial routing.

### Customizing Routing Errors

If you want to retain HTTP `405 Method Not Allowed` instead of allowing it to be converted to the equivalent of the gRPC `12 UNIMPLEMENTED`, which is HTTP `501 Not Implemented` you can use the following example:

```go
func handleRoutingError(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, r *http.Request, httpStatus int) {
	if httpStatus != http.StatusMethodNotAllowed {
		runtime.DefaultRoutingErrorHandler(ctx, mux, marshaler, w, r, httpStatus)
		return
	}

	// Use HTTPStatusError to customize the DefaultHTTPErrorHandler status code
	err := &runtime.HTTPStatusError{
		HTTPStatus: httpStatus,
		Err:        status.Error(codes.Unimplemented, http.StatusText(httpStatus)),
	}

	runtime.DefaultHTTPErrorHandler(ctx, mux, marshaler, w, r, err)
}
```

To use this routing error handler, construct the mux as follows:

```go
mux := runtime.NewServeMux(
	runtime.WithRoutingErrorHandler(handleRoutingError),
)
```

## Disabling X-HTTP-Method-Override

By default, the gRPC-Gateway allows clients to send a `POST` request with an
`X-HTTP-Method-Override` header to override the HTTP method. For example, a
`POST` request with `X-HTTP-Method-Override: GET` will be routed as if it were
a `GET` request. This is part of the path length fallback behavior, which
allows HTML forms (which only support `GET` and `POST`) to call other methods.

This can lead to HTTP method confusion when your gateway sits behind a Web
Application Firewall (WAF) or reverse proxy that enforces method-based access
controls. For example, if a WAF is configured to only allow `POST` requests to
a particular endpoint, a client could send a `POST` with
`X-HTTP-Method-Override: DELETE` and the gateway would route the request to the
`DELETE` handler, bypassing the WAF's intended restrictions. The WAF sees a
`POST` request, but the gateway processes it as a `DELETE`.

To disable the `X-HTTP-Method-Override` header handling, use the
`WithDisableHTTPMethodOverride` option:

```go
mux := runtime.NewServeMux(
	runtime.WithDisableHTTPMethodOverride(),
)
```

This disables only the method override header. The path length fallback (routing
a `POST` with `Content-Type: application/x-www-form-urlencoded` to a matching
`GET` handler) remains available unless separately disabled with
`WithDisablePathLengthFallback`.

---

### Docs Mapping Examples (`docs/docs/mapping/examples.md`)

---
layout: default
title: Examples
nav_order: 0
parent: Mapping
---

# Examples

Examples are available under `examples/internal` directory.

- [`proto/examplepb/echo_service.proto`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/echo_service.proto), [`proto/examplepb/a_bit_of_everything.proto`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/a_bit_of_everything.proto), [`proto/examplepb/unannotated_echo_service.proto`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/unannotated_echo_service.proto):
  protobuf service definitions.
- [`proto/examplepb/echo_service.pb.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/echo_service.pb.go), [`proto/examplepb/a_bit_of_everything.pb.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/a_bit_of_everything.pb.go), [`proto/examplepb/unannotated_echo_service.pb.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/unannotated_echo_service.pb.go):
  generated Go service stubs and types.
- [`proto/examplepb/echo_service.pb.gw.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/echo_service.pb.gw.go), [`proto/examplepb/a_bit_of_everything.pb.gw.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/a_bit_of_everything.pb.gw.go), [`proto/examplepb/unannotated_echo_service.pb.gw.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/unannotated_echo_service.pb.gw.go):
  generated gRPC-Gateway clients.
- [`proto/examplepb/unannotated_echo_service.yaml`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/unannotated_echo_service.yaml):
  gRPC API Configuration for `unannotated_echo_service.proto`.
- [`server/main.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/server/main.go):
  service implementation.
- [`main.go`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/gateway/main.go):
  entrypoint of the generated reverse proxy.

To use the same port for custom HTTP handlers (e.g. serving `swagger.json`),
gRPC-Gateway, and a gRPC server, see [this code example by CoreOS](https://github.com/philips/grpc-gateway-example/blob/master/cmd/serve.go) (and its accompanying
[blog post](https://coreos.com/blog/grpc-protobufs-swagger.html)).

---

### Docs Mapping Grpc Api Configuration (`docs/docs/mapping/grpc_api_configuration.md`)

---
layout: default
title: gRPC API Configuration
nav_order: 3
parent: Mapping
---

# gRPC API Configuration

In some situations annotating the proto file of service is not an option. For example, you might not have control over the proto file, or you might want to expose the same gRPC API multiple times in completely different ways.

gRPC-Gateway supports 2 ways of dealing with these situations:

- [gRPC API Configuration](#grpc-api-configuration)
  - [`generate_unbound_methods`](#generate_unbound_methods)
  - [`strict_deep_wildcard`](#strict_deep_wildcard)
  - [Using an external configuration file](#using-an-external-configuration-file)
    - [Usage of gRPC API Configuration YAML files](#usage-of-grpc-api-configuration-yaml-files)

## `generate_unbound_methods`

Providing this parameter to the `protoc` plugin will make it produce the HTTP mapping even for methods without any `HttpRule` annotation. This is similar to how [Cloud Endpoints behaves](https://cloud.google.com/endpoints/docs/grpc/transcoding#where_to_configure_transcoding) and uses the way [gRPC itself](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md) maps to HTTP/2:

- HTTP method is `POST`
- URI path is built from the service's name and method: `/<fully qualified service name>/<method name>` (e.g.: `/my.package.EchoService/Echo`)
- HTTP body is the serialized protobuf message.

NOTE: the same option is also supported by the `gen-openapiv2` plugin.

## `strict_deep_wildcard`

By default a deep wildcard (`**`) that follows another path segment may match zero path segments, so `/v3/files/{path=**}` also matches `/v3/files` with an empty `path`. Providing `strict_deep_wildcard=true` to the `protoc-gen-grpc-gateway` plugin makes such patterns require at least one remaining path segment, so `/v3/files` no longer matches and can be routed to a separately registered `/v3/files` handler. A request with a trailing slash (`/v3/files/`) still matches with an empty capture, and a bare `**` with nothing before it still matches zero segments.

```sh
protoc --grpc-gateway_out=. --grpc-gateway_opt=strict_deep_wildcard=true ...
```

The generated code requires a version of the `runtime` package that includes `runtime.NewPatternWithOptions`.

## Using an external configuration file

Google Cloud Platform offers a way to do this for services
hosted with them called ["gRPC API Configuration"](https://cloud.google.com/endpoints/docs/grpc/grpc-service-config). It can be used to define the behavior of a gRPC API service without modifications to the service itself in the form of [YAML](https://en.wikipedia.org/wiki/YAML) configuration files.

gRPC-Gateway generators implement the [HTTP rules part](https://cloud.google.com/endpoints/docs/grpc-service-config/reference/rpc/google.api#httprule) of this specification. This allows you to take a completely unannotated service proto file, add a YAML file describing its HTTP endpoints and use them together like an annotated proto file with the gRPC-Gateway generators.

OpenAPI options may also be configured via ["OpenAPI Configuration"](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/internal/descriptor/openapiconfig/openapiconfig.proto) in the form of YAML configuration files.

### Usage of gRPC API Configuration YAML files

The following is equivalent to the basic [`README.md`](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/README.md#usage) example but without direct
annotation for gRPC-Gateway in the proto file. Only some steps require minor changes to use a gRPC API Configuration YAML file instead:

1. Define your service in gRPC as usual

   your_service.proto:

   ```protobuf
   syntax = "proto3";
   package your.service.v1;
   option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1";
   message StringMessage {
     string value = 1;
   }

   service YourService {
     rpc Echo(StringMessage) returns (StringMessage) {}
   }
   ```

2. Instead of annotating the proto file in this step leave it untouched
   and create a `your_service.yaml` with the following content:

   ```yaml
   type: google.api.Service
   config_version: 3

   http:
     rules:
       - selector: your.service.v1.YourService.Echo
         post: /v1/example/echo
         body: "*"
   ```

   Use a [linter](http://www.yamllint.com/) to validate your YAML.

3. Generate gRPC stub as before

   ```sh
   protoc -I . \
     --go_out ./gen/go/ \
     --go_opt paths=source_relative \
     --go-grpc_out ./gen/go/ \
     --go-grpc_opt paths=source_relative \
     your/service/v1/your_service.proto
   ```

It will generate a stub file with path `./gen/go/your/service/v1/your_service.pb.go`.

4. Implement your service in gRPC as usual

5. Generate the reverse-proxy. Here we have to pass the path to
   the `your_service.yaml` in addition to the proto file:

   ```sh
   protoc -I . \
     --grpc-gateway_out ./gen/go \
     --grpc-gateway_opt paths=source_relative \
     --grpc-gateway_opt grpc_api_configuration=path/to/your_service.yaml \
     your/service/v1/your_service.proto
   ```

   This will generate a reverse proxy `gen/go/your/service/v1/your_service.pb.gw.go` that is identical to the one produced for the annotated proto.

    **Using Buf with one configuration for multiple services**

    When a single gRPC API Configuration YAML file contains selectors for
    services defined in different directories, set `strategy: all` for each
    local Buf plugin that uses the configuration. Buf invokes local plugins
    once per directory by default, so each invocation sees only part of the
    schema and reports rules for services in other directories as unmatched.

    ```yaml
    version: v2
    plugins:
      - local: protoc-gen-grpc-gateway
        out: gen/go
        strategy: all
        opt:
          - paths=source_relative
          - grpc_api_configuration=path/to/your_service.yaml
      - local: protoc-gen-openapiv2
        out: gen/openapiv2
        strategy: all
        opt:
          - grpc_api_configuration=path/to/your_service.yaml
    ```

    See [Buf's invocation strategy documentation](https://buf.build/docs/configuration/v2/buf-gen-yaml/#strategy).

   In situations where you only need the reverse-proxy you can use the `standalone=true` option when generating the code. This will ensure the `types` used within `your_service.pb.gw.go` reference the external source appropriately.

   ```
   protoc -I . \
     --grpc-gateway_out ./gen/go \
     --grpc-gateway_opt paths=source_relative \
     --grpc-gateway_opt standalone=true \
     --grpc-gateway_opt grpc_api_configuration=path/to/your_service.yaml \
     your/service/v1/your_service.proto
   ```

6. Generate the optional your_service.swagger.json

   ```sh
   protoc -I . --openapiv2_out ./gen/go \
     --openapiv2_opt grpc_api_configuration=path/to/your_service.yaml \
     your/service/v1/your_service.proto
   ```

   or using an OpenAPI configuration file

   ```sh
   protoc -I . --openapiv2_out ./gen/go \
     --openapiv2_opt grpc_api_configuration=path/to/your_service.yaml \
     --openapiv2_opt openapi_configuration=path/to/your_service_swagger.yaml \
     your/service/v1/your_service.proto
   ```

   For an example of an OpenAPI configuration file, see [unannotated_echo_service.swagger.yaml](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/unannotated_echo_service.swagger.yaml), which adds OpenAPI options to [unannotated_echo_service.proto](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/proto/examplepb/unannotated_echo_service.proto).

   ```sh
   protoc -I . --openapiv2_out ./gen/go \
     --openapiv2_opt grpc_api_configuration=path/to/your_service.yaml \
     your/service/v1/your_service.proto
   ```

All other steps work as before. If you want you can remove the `googleapis` include path in step 3 and 4 as the unannotated proto no longer requires them.

---

### Docs Mapping Httpbody Messages (`docs/docs/mapping/httpbody_messages.md`)

---
layout: default
title: HttpBody Messages
nav_order: 1
parent: Mapping
---

# HttpBody Messages

The [HTTPBody](https://github.com/googleapis/googleapis/blob/master/google/api/httpbody.proto) messages allow a response message to be specified with custom data content and a custom content-type header. The values included in the HTTPBody response will be used verbatim in the returned message from the gateway. Make sure you format your response carefully!

`google.api.HttpBody` is also the native gRPC-Gateway response shape to use for
binary downloads and other raw payload responses where you need to control the
returned content type directly.

## Example Usage

1. Define your service in gRPC with an `HttpBody` response message.

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

service HttpBodyExampleService {
	rpc HelloWorld(google.protobuf.Empty) returns (google.api.HttpBody) {
		option (google.api.http) = {
			get: "/helloworld"
		};
	}
	rpc Download(google.protobuf.Empty) returns (stream google.api.HttpBody) {
		option (google.api.http) = {
			get: "/download"
		};
	}
}
```

2. Generate gRPC and reverse-proxy stubs and implement your service.

## Example service implementation

```go
func (*HttpBodyExampleService) Helloworld(ctx context.Context, in *empty.Empty) (*httpbody.HttpBody, error) {
	return &httpbody.HttpBody{
		ContentType: "text/html",
		Data:        []byte("Hello World"),
	}, nil
}

func (HttpBodyExampleService) Download(_ *empty.Empty, stream HttpBodyExampleService_DownloadServer) error {
	msgs := []*httpbody.HttpBody{
		{
			ContentType: "text/html",
			Data:        []byte("Hello 1"),
		},
		{
			ContentType: "text/html",
			Data:        []byte("Hello 2"),
		},
	}

	for _, msg := range msgs {
		if err := stream.Send(msg); err != nil {
			return err
		}
	}

	return nil
}
```

---

### Docs Mapping Openapi V3 (`docs/docs/mapping/openapi_v3.md`)

---
layout: default
title: OpenAPI 3.1 Output
nav_order: 7
parent: Mapping
---

# OpenAPI 3.1 Output

{: .warning }
**Alpha — output is not yet stable.** `protoc-gen-openapiv3` is a new
generator and the exact JSON shape it emits may change between minor
releases as the mapping rules settle in response to user feedback.
Specifically expect the encodings for oneofs, wrapper types, enums, and
path-template expansion to evolve, and expect tooling-compatibility
compromises (documented inline in the generator source) to be revisited
as consumer OpenAPI 3.1 support matures. If you need a production-stable
OpenAPI pipeline today, use [`protoc-gen-openapiv2`](./customizing_openapi_output.md).

{: .note }
`protoc-gen-openapiv3` emits OpenAPI 3.1.0 JSON directly from
`google.api.http` annotations. It is intentionally smaller in scope than
[`protoc-gen-openapiv2`](./customizing_openapi_output.md) and does **not**
consume the `grpc.gateway.protoc_gen_openapiv2.options` annotations. If
you rely on those options, continue to use the v2 generator.

## What it does

`protoc-gen-openapiv3` walks every proto file it is asked to generate, finds
services with HTTP bindings, and emits **one OpenAPI 3.1.0 JSON document per
proto file** (`foo.proto` → `foo.openapi.json`). Files with no HTTP-bound
services produce no output.

The output is deterministic and byte-stable across runs: paths are emitted in
RPC declaration order, component schemas are sorted alphabetically, and
response codes are emitted default-first then sorted.

## What it does not do

The generator is deliberately opinionated. The following are **not** supported today:

- The `grpc.gateway.protoc_gen_openapiv2.options` annotation set.
- OpenAPI 2.0 / Swagger output (use `protoc-gen-openapiv2` for that).
- YAML output.
- Alternative naming strategies. Component names are always the
  fully-qualified proto name with the leading dot stripped
  (e.g. `lib.v1.Book`).
- Integer enums. Enums are always rendered as strings.

Features can be added back as concrete needs emerge — if you want one of the
above, please open an issue describing your use case.

## Plugin options

### `disable_default_errors`

By default, every operation gets an auto-injected `default` response entry
pointing to the `google.rpc.Status` component schema. If you use a custom
error handler that returns a different response shape, you can suppress this
behaviour with the `disable_default_errors` option.

With **buf** (`buf.gen.yaml`):

```yaml
version: v2
plugins:
  - local: protoc-gen-openapiv3
    out: .
    opt:
      - disable_default_errors=true
```

With **protoc**:

```sh
protoc -I. \
  --openapiv3_out=. \
  --openapiv3_opt=disable_default_errors=true \
  path/to/your/service.proto
```

When set, neither the `default` response entry nor the `google.rpc.Status`
component schema are emitted.

### `visibility_restriction_selectors`

See [Hiding fields, methods, services and enum values](#hiding-fields-methods-services-and-enum-values) below.

## Installation

```sh
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv3@latest
```

## Usage with buf

Add the plugin to your `buf.gen.yaml`:

```yaml
version: v2
plugins:
  - local: protoc-gen-openapiv3
    out: .
```

Then run `buf generate` as usual. A `.openapi.json` file will appear next to
each proto file that declares HTTP bindings.

## Usage with protoc

```sh
protoc -I. \
  --openapiv3_out=. \
  path/to/your/service.proto
```

## Hiding fields, methods, services and enum values

If you require internal or unreleased fields and APIs to be hidden from
your API documentation,
[`google.api.VisibilityRule`](https://github.com/googleapis/googleapis/blob/9916192ab15e3507e41ba2c5165182fec06120d0/google/api/visibility.proto#L89)
annotations can be added to services, methods, fields and enum values.
The generator drops any annotated element whose restriction labels do
not overlap with the configured `visibility_restriction_selectors`.
Elements without a `VisibilityRule` annotation are always emitted.

`visibility_restriction_selectors` can be declared multiple times to
include multiple visibility restrictions in the output. For example,
with `buf`:

```yaml
version: v2
plugins:
  - local: protoc-gen-openapiv3
    out: .
    opt:
      - visibility_restriction_selectors=PREVIEW
      - visibility_restriction_selectors=INTERNAL
```

or with `protoc`:

```sh
protoc --openapiv3_out=. \
  --openapiv3_opt=visibility_restriction_selectors=PREVIEW \
  --openapiv3_opt=visibility_restriction_selectors=INTERNAL \
  ./path/to/file.proto
```

The restriction labels are arbitrary. `INTERNAL` and `PREVIEW` are the
conventional pair, but any label scheme works (`ALPHA`, `BETA`,
`RELEASED`, ...) as long as the annotations and the selector flag use
the same vocabulary.

When a service is hidden, all of its methods are hidden along with it
and the service's tag is omitted from `tags[]`. When every field in a
`oneof` group is hidden, the group's "at most one set" constraint is
also dropped.

Visibility annotations on fields used as HTTP path parameters (via
`google.api.http` path templates) are ignored — the path template
itself always exposes the parameter's name. To hide an operation that
takes a restricted input, apply `google.api.method_visibility` to the
method (or `google.api.api_visibility` to the whole service) instead
of annotating the path field.

If every value of an enum ends up hidden, the enum's component schema
is still emitted (a visible field may reference it) but falls back to
an unconstrained `type: string`. A log line is written when this
happens; broaden the selectors or hide the referring fields to silence
it.

## Mapping rules

The mapping from proto constructs to OpenAPI is fixed and summarised below.

### Services and methods

| Proto                    | OpenAPI                                           |
| ------------------------ | ------------------------------------------------- |
| Service                  | Tag (`tags[]`) plus `tags` on each operation      |
| Method                   | Operation under a `PathItem`                      |
| Method leading comment   | Operation `summary` / `description`               |
| Method `deprecated=true` | Operation `deprecated: true`                      |
| Additional bindings      | Extra operations; `operationId` suffixed `_<idx>` |

The default `operationId` is `<Service>_<Method>`. When a method has multiple
HTTP bindings, the first uses the bare ID and subsequent bindings append
`_1`, `_2`, ... so the spec remains valid.

The service's tag is named after the service and described by its leading
comment. The service-level `openapiv3_tag` annotation overrides it: a
non-empty `name` renames the tag, which the service's operations then use by
default, and `description`, `external_docs` and `extensions` set the
corresponding fields of the OpenAPI
[Tag Object](https://spec.openapis.org/oas/v3.1.0#tag-object). An
operation-level `openapiv3_operation.tags` list still replaces the default for
that operation.

```protobuf
import "protoc-gen-openapiv3/options/annotations.proto";

service BookService {
  option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_tag) = {
    name: "Books"
    description: "Manage the books in the library."
    external_docs: {
      description: "Library guide"
      url: "https://example.com/docs/books"
    }
  };

  rpc GetBook(GetBookRequest) returns (Book) {
    option (google.api.http) = {get: "/v1/books/{id}"};
  }
}
```

### Parameters

- Path parameters from the `google.api.http` URL template become `in: path`
  parameters.
- Constrained path templates like `{name=shelves/*}` are **expanded** into
  the OpenAPI URL verbatim: the literal prefix stays in the URL and each
  wildcard becomes its own OpenAPI parameter. This is required because the
  proto field binds to the full matched substring (e.g. `shelves/abc`), so
  a client following the OpenAPI URL must actually send `/shelves/abc`
  rather than just `/abc`. Examples:

  | Proto template                 | OpenAPI URL                         |
  | ------------------------------ | ----------------------------------- |
  | `/v1/{name}`                   | `/v1/{name}`                        |
  | `/v1/{name=shelves/*}`         | `/v1/shelves/{name}`                |
  | `/v1/{name=shelves/*/books/*}` | `/v1/shelves/{name}/books/{name_1}` |
  | `/v1/{name=files/**}`          | `/v1/files/{name}`                  |

  When a single proto field expands into multiple wildcards, the second and
  subsequent parameters are suffixed `_1`, `_2`, ... so the OpenAPI URL
  stays valid. All synthetic parameters point back at the same underlying
  proto field, which the grpc-gateway runtime reconstructs from the full
  matched substring at request time.

- Fields that are neither path parameters nor part of the request body
  become `in: query` parameters. This also applies to nested fields: with
  `/v1/{id.value}`, `id.value` is only a path parameter, while the other
  fields of `id` are still flattened into query parameters.
- `body="*"` synthesises an inline object schema that includes every request
  field **except** path parameters.
- `body="field"` uses that single field's type as the request body.

### Schemas

- Messages become component schemas under `#/components/schemas/`.
- Enums become string-valued component schemas.
- `repeated` fields produce `type: array`.
- Map fields produce `type: object` with `additionalProperties`.
- 64-bit integer fields are emitted as JSON strings, matching protojson.
- Well-known types are inlined, not referenced (see below).
- Field descriptions are populated from leading proto comments.
- `google.api.field_behavior` maps to `required`, `readOnly`, and
  `writeOnly` on the parent schema.
- `deprecated = true` on a field sets `deprecated: true` on the property.

### Oneofs

Every field inside a `oneof` appears as a normal property on the component
schema, and each `oneof` group contributes an "at most one set" constraint
on top of those properties. The constraint is expressed as a JSON Schema
`oneOf` whose options are:

1. a "none of the fields are set" guard of the form
   `{"not": {"anyOf": [{"required": ["fieldA"]}, {"required": ["fieldB"]}, ...]}}`;
2. one `{"required": ["fieldN"]}` option per field in the group.

Because `oneOf` matches exactly one sub-schema:

- zero fields set → only option 1 matches → passes,
- exactly one field set → only that field's `required` option matches → passes,
- two or more set → multiple `required` options match → fails validation.

This matches proto3 `oneof` semantics, which allow either zero or one
member to be set.

Messages with a single `oneof` group hoist the constraint directly onto
the component schema's `oneOf`. Messages with multiple groups wrap their
group constraints in `allOf` so each group is enforced independently.

Single-field `oneof` groups produce a trivially-true constraint and are
skipped for output hygiene. Synthetic proto3-optional oneofs are treated
as regular optional fields (the proto compiler models `optional string
foo = 1;` as a one-element synthetic oneof).

### Well-known types

Well-known types are **inlined** as their protojson representation:

| WKT                           | Schema                          |
| ----------------------------- | ------------------------------- |
| `google.protobuf.Timestamp`   | `string`, `format: date-time`   |
| `google.protobuf.Duration`    | `string`                        |
| `google.protobuf.FieldMask`   | `string`                        |
| `google.protobuf.StringValue` | `string`                        |
| `google.protobuf.BytesValue`  | `string`, `format: byte`        |
| `google.protobuf.Int32Value`  | `integer`, `format: int32`      |
| `google.protobuf.UInt32Value` | `integer`, `format: int64`      |
| `google.protobuf.Int64Value`  | `string`, `format: int64`       |
| `google.protobuf.UInt64Value` | `string`, `format: uint64`      |
| `google.protobuf.FloatValue`  | `number`, `format: float`       |
| `google.protobuf.DoubleValue` | `number`, `format: double`      |
| `google.protobuf.BoolValue`   | `boolean`                       |
| `google.protobuf.Empty`       | `object`                        |
| `google.protobuf.Struct`      | `object`                        |
| `google.protobuf.Value`       | unconstrained                   |
| `google.protobuf.ListValue`   | `array` of unconstrained        |
| `google.protobuf.NullValue`   | `null`                          |
| `google.protobuf.Any`         | `object` with `@type` plus open |

**Wrapper types are intentionally not marked nullable.** The strictly-correct
JSON Schema 2020-12 form for `google.protobuf.StringValue` would be
`type: ["string", "null"]`, but no Go OpenAPI generator in the ecosystem
handles that form today: `openapi-generator-cli`'s Go target produces
unbuildable code, and `oapi-codegen` (including its experimental 3.1 fork)
errors with `unhandled Schema type: &[string null]` on request bodies.
Until tooling catches up, the generator describes wrappers as their
underlying primitive. The grpc-gateway runtime still accepts a JSON `null`
on the wire regardless, because `protojson` treats wrappers as optional.

RPCs returning `google.protobuf.Empty` emit a `200` with an `object` schema
body (`{}`), matching what the `grpc-gateway` runtime actually writes on
the wire. The HTTP-conventional `204 No Content` would be more idiomatic
but conflicts with runtime behaviour, so generated clients would reject
valid responses.

### Error responses

Every operation automatically gets a `default` response keyed to a
component schema named `google.rpc.Status` with the standard `code`,
`message`, and `details[]` fields. This matches what `grpc-gateway` returns
on error paths. Use the `disable_default_errors` plugin option to suppress
this behaviour when using a custom error handler.

## Security schemes

Security schemes are declared once in the file-level `openapiv3_document`
annotation, under `components.security_schemes`, and referenced by name from
`security` requirements. A document-level `security` list applies to every
operation in the file; an operation-level `security` list replaces it for that
operation. Each entry in a `security` list is an alternative, and all schemes
named within one entry must be satisfied together.

The fields map to the OpenAPI
[Security Scheme Object](https://spec.openapis.org/oas/v3.1.0#security-scheme-object)
and [Security Requirement Object](https://spec.openapis.org/oas/v3.1.0#security-requirement-object).
Generation fails if a scheme is missing a field the spec requires for its type,
or if a requirement names a scheme that isn't declared in the same file.

```protobuf
import "protoc-gen-openapiv3/options/annotations.proto";

option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_document) = {
  components: {
    security_schemes: {
      key: "BearerAuth"
      value: {
        type: TYPE_HTTP
        scheme: "bearer"
        bearer_format: "JWT"
      }
    }
    security_schemes: {
      key: "ApiKeyAuth"
      value: {
        type: TYPE_API_KEY
        name: "X-API-Key"
        in: IN_HEADER
      }
    }
    security_schemes: {
      key: "OAuth2"
      value: {
        type: TYPE_OAUTH2
        flows: {
          authorization_code: {
            authorization_url: "https://example.com/oauth/authorize"
            token_url: "https://example.com/oauth/token"
            scopes: {
              key: "read"
              value: "Read access"
            }
            scopes: {
              key: "write"
              value: "Write access"
            }
          }
        }
      }
    }
  }
  // Every operation requires a bearer token unless it says otherwise.
  security: {
    schemes: {
      key: "BearerAuth"
      value: {}
    }
  }
};
```

An operation can require different schemes, ask for OAuth2 scopes, or accept
any of several alternatives:

```protobuf
rpc UpdateBook(UpdateBookRequest) returns (Book) {
  option (google.api.http) = {
    patch: "/v1/books/{book.id}"
    body: "book"
  };
  // Either an OAuth2 token with the "write" scope, or an API key.
  option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_operation) = {
    security: {
      schemes: {
        key: "OAuth2"
        value: {scopes: "write"}
      }
    }
    security: {
      schemes: {
        key: "ApiKeyAuth"
        value: {}
      }
    }
  };
}
```

To make authentication optional for an operation, add an empty requirement.
It renders as `{}` in the operation's `security` list:

```protobuf
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
  option (google.api.http) = {get: "/v1/books"};
  option (grpc.gateway.protoc_gen_openapiv3.options.openapiv3_operation) = {
    security: {}
  };
}
```

Mutual TLS (`TYPE_MUTUAL_TLS`) needs no other fields, and OpenID Connect
(`TYPE_OPEN_ID_CONNECT`) needs `open_id_connect_url`.

## Example

Given:

```protobuf
syntax = "proto3";

package example.v1;

import "google/api/annotations.proto";

service EchoService {
  rpc Echo(EchoRequest) returns (EchoResponse) {
    option (google.api.http) = {
      post: "/v1/echo"
      body: "*"
    };
  }
}

message EchoRequest  { string message = 1; }
message EchoResponse { string message = 1; }
```

The generator emits `echo.openapi.json` with one `POST /v1/echo` operation,
an `EchoResponse` component schema, and the auto-injected
`google.rpc.Status` default error response. See
[`protoc-gen-openapiv3/internal/genopenapi/testdata/simple_echo.openapi.json`](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/protoc-gen-openapiv3/internal/genopenapi/testdata/simple_echo.openapi.json)
for the exact output.

## Consuming the output

The generated spec validates as OpenAPI 3.1.0 and can be fed to any 3.1-aware
tool, including [`openapi-generator-cli`](https://github.com/OpenAPITools/openapi-generator)
for client generation. An end-to-end example that runs a real grpc-gateway
behind a generated Go client lives at
[`examples/internal/integration/openapiv3`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/integration/openapiv3).

---

### Docs Mapping Openapi V3 Merge (`docs/docs/mapping/openapi_v3_merge.md`)

---
layout: default
title: Merging OpenAPI 3.1 Output
nav_order: 8
parent: Mapping
---

# Merging OpenAPI 3.1 Output

{: .note }
This page describes `openapiv3-merge`, the post-processing tool that
combines `protoc-gen-openapiv3` output into a single OpenAPI document. The
generator itself is documented under
[OpenAPI 3.1 Output](./openapi_v3.md).

[`protoc-gen-openapiv3`](./openapi_v3.md) emits **one OpenAPI document per
proto file**, matching the protobuf convention of 1:1 input-to-output
files. Many OpenAPI consumers — UI viewers, client generators, gateway
configurations — expect a single document instead. `openapiv3-merge` is the
post-processing step that combines the per-file outputs into one.

## Installation

```sh
go install github.com/grpc-ecosystem/grpc-gateway/v2/openapiv3-merge@latest
```

## Usage

```sh
openapiv3-merge FILE [FILE ...] > merged.openapi.json
```

The merged document is written to stdout. Errors go to stderr and the
process exits with a non-zero status. Input order matters: the first
input's `info`, `servers`, and `externalDocs` are kept in the merged
document, so put the file with the broadest scope (the one carrying any
shared [`openapiv3_document`](./openapi_v3.md#example) annotation) first.

### With buf

Generate per-proto-file documents the usual way, then merge them:

```sh
#!/usr/bin/env bash
set -euo pipefail

buf generate

# Put the file with the shared openapiv3_document annotation first so
# its info/servers/externalDocs are kept, then everything else in
# sorted order for determinism.
root=gen/api/v1/api.openapi.json
mapfile -t rest < <(find gen -name '*.openapi.json' ! -path "$root" | sort)
openapiv3-merge "$root" "${rest[@]}" > gen/api.openapi.json
```

If you don't have a designated root file, just sort all inputs and accept
whichever sorts first — but set the `openapiv3_document` annotation on
that proto so the merged output has a sensible `title`, `version`, and
`servers`.

### With protoc

```sh
#!/usr/bin/env bash
set -euo pipefail

protoc -I. \
  --openapiv3_out=./gen \
  $(find . -name '*.proto')

root=gen/api/v1/api.openapi.json
mapfile -t rest < <(find gen -name '*.openapi.json' ! -path "$root" | sort)
openapiv3-merge "$root" "${rest[@]}" > gen/api.openapi.json
```

### One-shot

For trivial trees where any input may go first:

```sh
openapiv3-merge $(find . -name '*.openapi.json' | sort) > api.openapi.json
```

## What gets merged, and how

| Field | Rule |
| --- | --- |
| `openapi` | Must match across all inputs. |
| `info`, `servers`, `externalDocs` | Taken from the first input. Later inputs' values are dropped. |
| `paths`, `webhooks` | Unioned in input order. Path collisions with non-identical content are errors. |
| `components/*` | Unioned with sorted keys. Same name with non-identical content is an error. |
| `tags` | Deduplicated by `name`. Same name with non-identical metadata is an error. |
| `security` | First input to declare a non-empty array wins. Later inputs that declare a different non-empty array are an error. |
| Unknown top-level keys (extensions, `x-*`) | Taken from the first input. |

"Non-identical content" is determined by canonical comparison: two values
that differ only in key order compare equal. Since `protoc-gen-openapiv3`
names component schemas with their fully qualified proto name (e.g.
`example.v1.User`), the same message reused across packages contributes a
single, identical component to every output, and the merger combines them
cleanly.

The first input controls the merged document's `info` block. If you want a
shared title, version, contact, license, or set of `servers` across all
merged output, set them with an
[`openapiv3_document`](./openapi_v3.md#example) annotation on the
proto file that appears first in your merge invocation.

## Output

- Top-level fields are emitted in OpenAPI 3.1.0 declaration order
  (`openapi`, `info`, `servers`, `paths`, `webhooks`, `components`,
  `security`, `tags`, `externalDocs`, then any extensions).
- `paths` and `webhooks` are emitted in input order.
- `components/*` sub-maps are sorted lexicographically, matching what
  `protoc-gen-openapiv3` itself emits per file.
- `tags` are emitted in first-occurrence order across inputs.

## Example merge errors

When a merge fails, the error message identifies the conflicting field:

```
openapiv3-merge: paths."/v1/echo": echo.openapi.json redefines an entry with a different value
```

Common causes:

- **Conflicting path definitions.** Two protos declared the same HTTP path
  with different bindings. Decide which one is authoritative.
- **Conflicting component definitions.** Two messages with the same fully
  qualified proto name but different shapes — usually means a duplicate
  `package` + message declaration somewhere in your proto tree.
- **Conflicting tag metadata.** Two `openapiv3_document.tags` annotations
  described the same tag with different descriptions. Make them match or
  move the metadata to one place.
- **Mismatched OpenAPI versions.** All inputs must declare the same
  `openapi` value.

## See also

- [OpenAPI 3.1 Output](./openapi_v3.md) — the generator that produces the
  per-file inputs to `openapiv3-merge`.
- [openapiv3-merge README](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/openapiv3-merge) — quick reference and source.

---

### Docs Mapping Patch Feature (`docs/docs/mapping/patch_feature.md`)

---
layout: default
title: Patch feature
nav_order: 2
parent: Mapping
---

# Patch feature

The HTTP PATCH method allows a resource to be partially updated.

If a binding is mapped to patch and the request message has exactly one FieldMask message in it, additional code is rendered for the gateway handler that will populate the FieldMask based on the request body. FieldMask is treated as a regular field by the gateway if the request method is not PATCH, or if the HttpRule body is `"*"`

There are two scenarios:

- The FieldMask is hidden from the REST request as per the
  [Google API design guide](https://cloud.google.com/apis/design/standard_methods#update) (as in the first additional binding in the
  [UpdateV2](https://github.com/grpc-ecosystem/grpc-gateway/blob/370d869f65d1ffb3d07187fb0db238eca2371ce3/examples/internal/proto/examplepb/a_bit_of_everything.proto#L428-L431) example). In this case, the FieldMask is updated from the request body and set in the gRPC request message. 
  - By default this feature is enabled, if you need to disable it, you can use the plugin option `allow_patch_feature=false`. 
  - Note: The same option is supported by the `protoc-gen-openapiv2` plugin.
- The FieldMask is exposed to the REST request (as in the second additional binding in the [UpdateV2](https://github.com/grpc-ecosystem/grpc-gateway/blob/370d869f65d1ffb3d07187fb0db238eca2371ce3/examples/internal/proto/examplepb/a_bit_of_everything.proto#L432-L435) example). For this case, the field mask is left untouched by the gateway.

## Example Usage

1. Create a PATCH request.

   The PATCH request needs to include the message and the update mask.

   ```protobuf
   // UpdateV2Request request for update includes the message and the update mask
   message UpdateV2Request {
    ABitOfEverything abe = 1;
    google.protobuf.FieldMask update_mask = 2;
   }
   ```

2. Define your service in gRPC

   If you want to use PATCH with fieldmask hidden from REST request only include the request message in the body.

   ```protobuf
   rpc UpdateV2(UpdateV2Request) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      put: "/v2/example/a_bit_of_everything/{abe.uuid}"
      body: "abe"
      additional_bindings {
        patch: "/v2/example/a_bit_of_everything/{abe.uuid}"
        body: "abe"
      }
    };
   }
   ```

   If you want to use PATCH with fieldmask exposed to the REST request then include the entire request message.

   ```protobuf
   rpc UpdateV2(UpdateV2Request) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      patch: "/v2a/example/a_bit_of_everything/{abe.uuid}"
      body: "*"
    };
   }
   ```

3. Generate gRPC and reverse-proxy stubs and implement your service.

## cURL examples

In the example below, we will partially update our ABitOfEverything resource by passing only the field we want to change. Since we are using the endpoint with field mask hidden we only need to pass the field we want to change ("string_value") and it will keep everything else in our resource the same.

```sh
$ curl \
  --data '{"stringValue": "strprefix/foo"}' \
  -X PATCH \
  http://address:port/v2/example/a_bit_of_everything/1
```

If we know what fields we want to update then we can use PATCH with field mask approach. For this, we need to pass the resource and the update_mask. Below only the "single_nested" will get updated because that is what we specify in the field_mask.

```sh
$ curl \
  --data '{"abe":{"singleNested":{"amount":457},"stringValue":"some value that will not get updated because not in the field mask"},"updateMask":"singleNested"}}' \
  -X PATCH \
  http://address:port/v2a/example/a_bit_of_everything/1
```

---

### Docs Mapping Using Ref With Responses (`docs/docs/mapping/using_ref_with_responses.md`)

# Using arbitrary messages in response description

Assuming a protobuf file of the structure

```protobuf
syntax = "proto3";

package example.service.v1;

import "protoc-gen-openapiv2/options/annotations.proto";

service GenericService {
  rpc GenericRPC(GenericRPCRequest) returns (GenericRPCResponse);
}

message GenericRPCRequest {
  string id = 1;
}

message GenericRPCResponse {
  string result = 1;
}
```

If you want your OpenAPI document to include a custom response for all RPCs defined in this protobuf file, you can add the following:

```protobuf
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  responses: {
    key: "400"
    value: {
      description: "Returned when the request is malformed."
      schema: {
        json_schema: {ref: ".example.service.v1.GenericResponse"} // Must match the fully qualified name of the message
      }
    }
  }
};

message GenericResponse {
  repeated string resources = 1;
  repeated string errors = 2;
}
```

When generating, you will see the following response included in your OpenAPI document:

```json
"400": {
  "description": "Returned when the request is malformed.",
  "schema": {
    "$ref": "#/definitions/v1GenericResponse"
  }
},
```

The annotation can also be specified per-rpc.

---

### Docs Operations Annotated Context (`docs/docs/operations/annotated_context.md`)

---
layout: default
title: Extracting the HTTP path pattern for a request
nav_order: 4
parent: Operations
---

# Extracting the HTTP path pattern for a request

It is often interesting to know what [HTTP path pattern](https://github.com/googleapis/googleapis/blob/869d32e2f0af2748ab530646053b23a2b80d9ca5/google/api/http.proto#L61-L87) was matched for a specific request, for example for metrics. This article explains how to extract the HTTP path pattern from the request context.

## Get HTTP Path pattern
1. Define the HTTP path in the proto annotation. For example:

```proto
syntax = "proto3";
option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/examples/internal/proto/examplepb";
package grpc.gateway.examples.internal.proto.examplepb;

import "google/api/annotations.proto";

service LoginService {
  rpc Login (LoginRequest) returns (LoginReply) {
    option (google.api.http) = {
        post: "/v1/example/login"
        body: "*"
    };
  }
}

message LoginRequest {}

message LoginReply {}
```

2. At runtime, get the HTTP path pattern from the annotated context, for example using the `WithMetadata` function.
You can pass data to your backend by adding them to the gRPC metadata or push them to a metrics server.

```go
mux := runtime.NewServeMux(
	runtime.WithMetadata(func(ctx context.Context, r *http.Request) metadata.MD {
		md := make(map[string]string)
		if method, ok := runtime.RPCMethod(ctx); ok {
			md["method"] = method // /grpc.gateway.examples.internal.proto.examplepb.LoginService/Login
		}
		if pattern, ok := runtime.HTTPPathPattern(ctx); ok {
			md["pattern"] = pattern // /v1/example/login
		}
		return metadata.New(md)
	}),
)
```

---

### Docs Operations Aws Gateway Integration (`docs/docs/operations/aws_gateway_integration.md`)

---
layout: default
title: AWS gateway integration
nav_order: 3
parent: Operations
---

# AWS gateway integration

## Import OpenAPI documentation into AWS API Gateway

The AWS API Gateway service allows importing of an OpenAPI specification to create a REST API. The process is very straightforward and can be found [here](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-import-api.html).

Here are some tips to consider when importing the documentation:

1. Remove any circular dependencies (these aren't supported by the parser).
2. Remove security-related annotations (These annotations aren't well supported by the parser).
3. Max length of fields are reviewed by the parser but the errors aren't self-explanatory. Review the [specification](https://swagger.io/specification/v2/) to verify that the requirements are met.
4. API gateway errors aren't great, but you can use this [page](https://apidevtools.org/swagger-parser/online/) for structure validation.

---

### Docs Operations Health Check (`docs/docs/operations/health_check.md`)

---
layout: default
title: Health check
nav_order: 1
parent: Operations
---

# Health check

## With the [gRPC Health Checking Protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md)

To use the gRPC health checking protocol you must add the two health checking methods, `Watch` and `Check`.

## Registering the health server

1. Add `google.golang.org/grpc/health/grpc_health_v1` to your imports
2. Register the health server with `grpc_health_v1.RegisterHealthServer(grpcServer, yourService)`

## Adding the health check methods

1. Check method

```go
func (s *serviceServer) Check(ctx context.Context, in *health.HealthCheckRequest) (*health.HealthCheckResponse, error) {
	return &health.HealthCheckResponse{Status: health.HealthCheckResponse_SERVING}, nil
}
```

2. Watch method

```go
func (s *serviceServer) Watch(in *health.HealthCheckRequest, _ health.Health_WatchServer) error {
    // Example of how to register both methods but only implement the Check method.
	return status.Error(codes.Unimplemented, "unimplemented")
}
```

3. You can test the functionality with [GRPC health probe](https://github.com/grpc-ecosystem/grpc-health-probe).

## Adding `/healthz` endpoint to runtime.ServeMux

To automatically register a `/healthz` endpoint in your `ServeMux` you can use
the `ServeMuxOption` `WithHealthzEndpoint`
which takes in a connection to your registered gRPC server.

This endpoint will forward a request to the `Check` method described above to really check the health of the
whole system, not only the gateway itself. If your server doesn't implement the health checking protocol each request
to `/healthz` will result in the following:

```json
{"code":12,"message":"unknown service grpc.health.v1.Health","details":[]}
```

If you've implemented multiple services in your server you can target specific services with the `?service=<service>`
query parameter. This will then be added to the `health.HealthCheckRequest` in the `Service` property. With that you can
write your own logic to handle that in the health checking methods.

Analogously, to register an `{/endpoint/path}` endpoint in your `ServeMux` with a user-defined endpoint path, you can use
the `ServeMuxOption` `WithHealthEndpointAt`, which accepts a connection to your registered gRPC server
together with a custom `endpointPath string` parameter.

---

### Docs Operations Inject Router (`docs/docs/operations/inject_router.md`)

---
layout: default
title: Adding custom routes to the mux
nav_order: 0
parent: Operations
---

# Adding custom routes to the mux

The gRPC-Gateway allows you to add custom routes to the serve mux, for example, if you want to support a use case that isn't supported by the gRPC-Gateway, like file uploads.

## Example

```go
package main

import (
	"context"
	"net/http"

	pb "github.com/grpc-ecosystem/grpc-gateway/v2/examples/internal/helloworld"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
)

func main() {
	ctx := context.TODO()
	mux := runtime.NewServeMux()
	// Register generated routes to mux
	err := pb.RegisterGreeterHandlerServer(ctx, mux, &GreeterServer{})
	if err != nil {
		panic(err)
	}
	// Register custom route for  GET /hello/{name}
	err = mux.HandlePath("GET", "/hello/{name}", func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
		w.Write([]byte("hello " + pathParams["name"]))
	})
	if err != nil {
		panic(err)
	}
	http.ListenAndServe(":8080", mux)
}

// GreeterServer is the server API for Greeter service.
type GreeterServer struct {

}

// SayHello implement to say hello
func (h *GreeterServer) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{
		Message: "hello " + req.Name,
	}, nil
}
```

---

### Docs Operations Logging (`docs/docs/operations/logging.md`)

---
layout: default
title: Logging the request body pattern for a request
nav_order: 5
parent: Operations
---

# Logging the request body pattern for a request

If you want to log the request body of incoming requests, you will need to buffer the body before it reaches the gateway. To log the request body, you can use a middleware `http.Handler` to buffer the request body before it's consumed.

1. Create a `http.Handler` middleware. The `logRequestBody` example middleware logs the request body when the response status code is not 200.

```go
type logResponseWriter struct {
	http.ResponseWriter
	statusCode int
}

func (rsp *logResponseWriter) WriteHeader(code int) {
	rsp.statusCode = code
	rsp.ResponseWriter.WriteHeader(code)
}

// Unwrap returns the original http.ResponseWriter. This is necessary
// to expose Flush() and Push() on the underlying response writer.
func (rsp *logResponseWriter) Unwrap() http.ResponseWriter {
	return rsp.ResponseWriter
}

func newLogResponseWriter(w http.ResponseWriter) *logResponseWriter {
	return &logResponseWriter{w, http.StatusOK}
}

// logRequestBody logs the request body when the response status code is not 200.
func logRequestBody(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		lw := newLogResponseWriter(w)

		// Note that buffering the entire request body could consume a lot of memory.
		body, err := io.ReadAll(r.Body)
		if err != nil {
			http.Error(w, fmt.Sprintf("failed to read body: %v", err), http.StatusBadRequest)
			return
		}
		clonedR := r.Clone(r.Context())
		clonedR.Body = io.NopCloser(bytes.NewReader(body))

		h.ServeHTTP(lw, clonedR)

		if lw.statusCode != http.StatusOK {
			grpclog.Errorf("http error %+v request body %+v", lw.statusCode, string(body))
		}
	})
}
```

2. Wrap the gateway serve mux with the `logRequestBody` middleware:

```go
    mux := runtime.NewServeMux()
    // Register generated gateway handlers

    s := &http.Server{
        Handler: logRequestBody(mux),
    }
```

---

### Docs Operations Security Considerations (`docs/docs/operations/security_considerations.md`)

---
layout: default
title: Security considerations
nav_order: 6
parent: Operations
---

# Security considerations

Things worth knowing about the defaults before you put a gateway in front of a
service that matters.

## Unknown JSON fields are dropped, and nothing says so

By default the gateway unmarshals JSON with `protojson` configured as
`DiscardUnknown: true`. A field that the target message does not define is
removed during transcoding and the request continues as if it had never been
sent.

Given this service:

```proto
message Command {
  string action = 1;
  int32  amount = 2;
}

service Gateway {
  rpc Send(Command) returns (Ack) {
    option (google.api.http) = {
      post: "/v1/send"
      body: "*"
    };
  }
}
```

a request carrying a third field:

```
POST /v1/send  {"action":"transfer","amount":1,"auth":"..."}
```

reaches the backend as `action` and `amount` only. The `auth` field is gone,
the backend sees a well formed message, and the client gets `200 OK`. Neither
end is told that anything was removed.

This is the behaviour the proto3 JSON mapping describes, and other JSON to gRPC
transcoders default the same way, so a client that works against one of them
will behave the same here. It is worth stating plainly because it is more
lenient than the `protojson` library the gateway wraps, which rejects unknown
fields by default.

### When this matters

The case to watch for is a client that puts something in the request expecting
the server to act on it, where the field is not in the schema. A token added by
an intermediary, a tenant identifier, a signature over the body, a flag a newer
client sends to an older backend. All of these disappear quietly, and the
request still succeeds, so the failure does not look like a failure.

It also matters when the schema changes. Removing or renaming a field does not
break clients that still send it. That is often the point, but it means a
rename can silently stop delivering data that the backend used to receive.

### Rejecting unknown fields instead

Set `DiscardUnknown` to false on the marshaler:

```go
mux := runtime.NewServeMux(
	runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{
		MarshalOptions: protojson.MarshalOptions{
			UseProtoNames: true,
		},
		UnmarshalOptions: protojson.UnmarshalOptions{
			DiscardUnknown: false,
		},
	}),
)
```

The same request now returns `400` with `unknown field "auth"`.

This is a good default for an internal API where every client is yours and a
stray field means someone made a mistake. It is a poor default for a public API
where clients you do not control may send extra fields for reasons of their
own, since it turns forward compatibility into an error.

### Noticing without rejecting

If rejecting is too strict but silence is too quiet, you can unmarshal twice and
log the difference: once with `DiscardUnknown: false` to see whether the strict
parse would have failed, then with the permissive setting for the request that
actually proceeds. That costs an extra parse per request, so it suits a
canary or a sampled fraction of traffic rather than everything.

## See also

- [Customizing your gateway](../mapping/customizing_your_gateway.md), which shows
  where the marshaler options go.
- [Custom marshalers](../mapping/custom_marshalers.md).

---

### Docs Operations Tracing (`docs/docs/operations/tracing.md`)

---
layout: default
title: Tracing
nav_order: 2
parent: Operations
---

# Tracing

If you are starting a new project, jump to the [OpenTelemetry](#opentelemetry)
section below. OpenTelemetry is the current standard for tracing in the Go
ecosystem and, when combined with `otelhttp` and `otelgrpc`, propagates spans
through the gateway with **no custom middleware**. The
[OpenCensus](#with-opencensusio-and-aws-x-ray) and
[OpenTracing](#opentracing-support-legacy) sections below are kept for existing
integrations and are considered legacy.

## With [OpenCensus.io](https://opencensus.io/) and [AWS X-ray](https://aws.amazon.com/xray/)

> **Legacy:** OpenCensus is deprecated in favor of OpenTelemetry. See the
> [OpenTelemetry](#opentelemetry) section for the current approach.

### Adding tracing using AWS-Xray as the exporter

This example uses the AWS-Xray exporter with a global trace setting. Note that AWS X-ray exporter does not handle any metrics only tracing.

1. Add the following imports

```go
xray "contrib.go.opencensus.io/exporter/aws"
"go.opencensus.io/plugin/ocgrpc"
"go.opencensus.io/plugin/ochttp"
"go.opencensus.io/trace"
```

2. Register the AWS X-ray exporter for the GRPC server

```go
xrayExporter, err := xray.NewExporter(
    xray.WithVersion("latest"),
    // Add your AWS region.
    xray.WithRegion("ap-southeast-1"),
)
if err != nil {
    // Handle any error.
}
// Do not forget to call Flush() before the application terminates.
defer xrayExporter.Flush()

// Register the trace exporter.
trace.RegisterExporter(xrayExporter)
```

3. Add a global tracing configuration

```go
// Always trace in this example.
// In production this can be set to a trace.ProbabilitySampler.
trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
```

4. Add `ocgrpc.ClientHandler` for tracing the gRPC client calls

```go
conn, err := grpc.NewClient(
    // Other options goes here.
    // Add ocgrpc.ClientHandler for tracing the grpc client calls.
    grpc.WithStatsHandler(&ocgrpc.ClientHandler{}),
)
```

5. Wrap the gateway mux with the OpenCensus HTTP handler

```go
gwmux := runtime.NewServeMux()

openCensusHandler := &ochttp.Handler{
		Handler: gwmux,
}

gwServer := &http.Server{
    Addr: "0.0.0.0:10000",
    Handler: openCensusHandler,
    }),
}
```

### Without a global configuration

In this example we have added the [gRPC Health Checking Protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md) and we do not wish to trace any health checks.

1. Follow step `1`, `2` and `4` from the previous section.

2. Since we are not using a global configuration we can decide what paths we want to trace.

```go
gwmux := runtime.NewServeMux()

openCensusHandler := &ochttp.Handler{
    Handler: gwmux,
    GetStartOptions: func(r *http.Request) trace.StartOptions {
        startOptions := trace.StartOptions{}
        if strings.HasPrefix(r.URL.Path, "/api") {
            // This example will always trace anything starting with /api.
            startOptions.Sampler = trace.AlwaysSample()
        }
        return startOptions
    },
}
```

4. No global configuration means we have to use the [per span sampler](https://opencensus.io/tracing/sampling/#per-span-sampler).

#### A method we want to trace

```go
func (s *service) Name(ctx context.Context, req *pb.Request) (*pb.Response, error) {
    // Here we add the span ourselves.
    ctx, span := trace.StartSpan(ctx, "name.to.use.in.trace", trace.
    // Select a sampler that fits your implementation.
    WithSampler(trace.AlwaysSample()))
    defer span.End()
    /// Other stuff goes here.
}
```

#### A method we do not wish to trace

```go
func (s *service) Check(ctx context.Context, in *health.HealthCheckRequest) (*health.HealthCheckResponse, error) {
    // Note no span here.
    return &health.HealthCheckResponse{Status: health.HealthCheckResponse_SERVING}, nil
}
```

## OpenTracing Support (legacy)

> **Legacy:** OpenTracing is deprecated in favor of OpenTelemetry. The custom
> `tracingWrapper` middleware below is **only** needed for OpenTracing. With
> OpenTelemetry's `otelhttp` and `otelgrpc` no such wrapper is required — see the
> [OpenTelemetry](#opentelemetry) section.

If your project uses [OpenTracing](https://github.com/opentracing/opentracing-go) and you'd like spans to propagate through the gateway, you can add some middleware which parses the incoming HTTP headers to create a new span correctly.

```go
import (
	"github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
)

var grpcGatewayTag = opentracing.Tag{Key: string(ext.Component), Value: "grpc-gateway"}

func tracingWrapper(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		parentSpanContext, err := opentracing.GlobalTracer().Extract(
			opentracing.HTTPHeaders,
			opentracing.HTTPHeadersCarrier(r.Header))
		if err == nil || err == opentracing.ErrSpanContextNotFound {
			serverSpan := opentracing.GlobalTracer().StartSpan(
				"ServeHTTP",
				// this is magical, it attaches the new span to the parent parentSpanContext, and creates an unparented one if empty.
				ext.RPCServerOption(parentSpanContext),
				grpcGatewayTag,
			)
			r = r.WithContext(opentracing.ContextWithSpan(r.Context(), serverSpan))
			defer serverSpan.Finish()
		}
		h.ServeHTTP(w, r)
	})
}

// Then just wrap the mux returned by runtime.NewServeMux() like this
if err := http.ListenAndServe(":8080", tracingWrapper(mux)); err != nil {
	log.Fatalf("failed to start gateway server on 8080: %v", err)
}
```

Finally, don't forget to add a tracing interceptor when registering
the services. E.g.

```go
import (
	"google.golang.org/grpc"
	"github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
)

opts := []grpc.DialOption{
	grpc.WithUnaryInterceptor(
		grpc_opentracing.UnaryClientInterceptor(
			grpc_opentracing.WithTracer(opentracing.GlobalTracer()),
		),
	),
}
if err := pb.RegisterMyServiceHandlerFromEndpoint(ctx, mux, serviceEndpoint, opts); err != nil {
	log.Fatalf("could not register HTTP service: %v", err)
}
```

## OpenTelemetry

[OpenTelemetry](https://opentelemetry.io/) is the recommended way to trace
requests through the gateway. **You do not need a custom `tracingWrapper` (as in
the legacy OpenTracing section above).** The official instrumentation libraries
already do the work:

- [`otelhttp`](https://pkg.go.dev/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp)
  wraps the gateway `http.Handler`, extracts the incoming
  [W3C Trace Context](https://www.w3.org/TR/trace-context/) from the request
  headers, and starts the **HTTP server span**.
- [`otelgrpc`](https://pkg.go.dev/go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc)
  stats handlers start the **gRPC client span** for the gateway's outgoing call
  (injecting the trace context into the gRPC metadata) and the **gRPC server
  span** on the backend.

An incoming HTTP request therefore produces three connected parent/child spans
that share a single trace ID:

```
HTTP server span (otelhttp)  ->  gRPC client span (otelgrpc)  ->  gRPC server span (otelgrpc)
```

### Runnable example

A complete, self-contained example lives at
[`examples/internal/cmd/example-otel-tracing`](https://github.com/grpc-ecosystem/grpc-gateway/tree/main/examples/internal/cmd/example-otel-tracing).
In a single process it wires up a stdout span exporter, an instrumented
in-process gRPC backend, and the gateway. Run it with:

```shell
go run ./examples/internal/cmd/example-otel-tracing
# then, in another terminal:
curl http://localhost:8081/say/OpenTelemetry
```

### Wiring

Install a `TracerProvider` and a propagator once at startup:

```go
import (
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
	"go.opentelemetry.io/otel/propagation"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
)

exporter, err := stdouttrace.New(stdouttrace.WithPrettyPrint())
if err != nil {
	// Handle any error.
}
tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exporter))
defer tp.Shutdown(context.Background())

otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
	propagation.TraceContext{},
	propagation.Baggage{},
))
```

Instrument the gRPC backend with the server stats handler:

```go
import "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"

s := grpc.NewServer(grpc.StatsHandler(otelgrpc.NewServerHandler()))
```

Dial the backend with the client stats handler so the gateway's outgoing call is
traced and the trace context is propagated:

```go
conn, err := grpc.NewClient(
	"localhost:9091",
	grpc.WithTransportCredentials(insecure.NewCredentials()),
	grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
)
```

Finally, wrap the gateway mux with `otelhttp` — this replaces the custom
`tracingWrapper` entirely:

```go
import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"

mux := runtime.NewServeMux()
if err := pb.RegisterGreeterHandler(ctx, mux, conn); err != nil {
	// Handle any error.
}

handler := otelhttp.NewHandler(mux, "grpc-gateway")
if err := http.ListenAndServe(":8081", handler); err != nil {
	log.Fatalf("failed to start gateway server: %v", err)
}
```

### Sample output

Issuing `curl http://localhost:8081/say/OpenTelemetry` prints three spans that
all share the same `TraceID`, confirming the trace propagates through the
gateway. Trimmed for brevity:

```jsonc
// 1. HTTP server span (otelhttp) — the root span.
{
	"Name": "GET",
	"SpanContext": { "TraceID": "6952...4aa5", "SpanID": "3b9c...fd0e" },
	"Parent":      { "TraceID": "0000...0000", "SpanID": "0000...0000" },
	"SpanKind": 2, // server
	"InstrumentationScope": { "Name": ".../net/http/otelhttp" }
}
// 2. gRPC client span (otelgrpc) — child of the HTTP span.
{
	"Name": "grpc.gateway.examples.internal.helloworld.Greeter/SayHello",
	"SpanContext": { "TraceID": "6952...4aa5", "SpanID": "1224...75ca" },
	"Parent":      { "TraceID": "6952...4aa5", "SpanID": "3b9c...fd0e" },
	"SpanKind": 3, // client
	"InstrumentationScope": { "Name": ".../grpc/otelgrpc" }
}
// 3. gRPC server span (otelgrpc) — child of the client span, context received over the wire.
{
	"Name": "grpc.gateway.examples.internal.helloworld.Greeter/SayHello",
	"SpanContext": { "TraceID": "6952...4aa5", "SpanID": "950f...d85e" },
	"Parent":      { "TraceID": "6952...4aa5", "SpanID": "1224...75ca", "Remote": true },
	"SpanKind": 2, // server
	"InstrumentationScope": { "Name": ".../grpc/otelgrpc" }
}
```

---

### Docs Overview Background (`docs/docs/overview/background.md`)

---
layout: default
title: Background
nav_order: 0
parent: Overview
---

# Background

gRPC is great -- it generates API clients and server stubs in many programming languages, it is fast, easy-to-use, bandwidth-efficient and its design is combat-proven by Google. However, you might still want to provide a traditional RESTful API as well. Reasons can range from maintaining backwards-compatibility, supporting languages or clients not well supported by gRPC to simply maintaining the aesthetics and tooling involved with a RESTful architecture.

This project aims to provide that HTTP+JSON interface to your gRPC service. A small amount of configuration in your service to attach HTTP semantics is all that's needed to generate a reverse-proxy with this library.

---

### Docs Overview Usage (`docs/docs/overview/usage.md`)

---
layout: default
title: How do I use this?
nav_order: 1
parent: Overview
---

# How do I use this?

Follow the [instructions](https://github.com/grpc-ecosystem/grpc-gateway#usage) in the [README](https://github.com/grpc-ecosystem/grpc-gateway#readme).

---

### Docs Tutorials Adding Annotations (`docs/docs/tutorials/adding_annotations.md`)

---
layout: default
title: Adding gRPC-Gateway annotations to an existing proto file
nav_order: 4
parent: Tutorials
---

# Adding gRPC-Gateway annotations to an existing proto file

Now that we've got a working Go gRPC server, we need to add the gRPC-Gateway annotations.

The annotations define how gRPC services map to the JSON request and response. When using protocol buffers, each RPC must define the HTTP method and path using the `google.api.http` annotation.

So we will need to add the `google/api/http.proto` import to the proto file. We also need to add the HTTP->gRPC mapping we want. In this case, we're mapping `POST /v1/example/echo` to our `SayHello` RPC.

```protobuf
syntax = "proto3";

package helloworld;

import "google/api/annotations.proto";

// Here is the overall greeting service definition where we define all our endpoints
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      post: "/v1/example/echo"
      body: "*"
    };
  }
}

// The request message containing the user's name
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
```

See [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/main/examples/internal/proto/examplepb/a_bit_of_everything.proto) for examples of more annotations you can add to customize gateway behavior.

## Generating the gRPC-Gateway stubs

Now that we've got the gRPC-Gateway annotations added to the proto file, we need to use the gRPC-Gateway generator to generate the stubs.

### Using buf

We'll need to add the gRPC-Gateway generator to the generation configuration:

```yaml
version: v1
plugins:
  - plugin: go
    out: proto
    opt: paths=source_relative
  - plugin: go-grpc
    out: proto
    opt: paths=source_relative,require_unimplemented_servers=false
  - plugin: grpc-gateway
    out: proto
    opt: paths=source_relative
```

We'll also need to add the `googleapis` dependency to our `buf.yaml` file:

```yaml
version: v1
name: buf.build/myuser/myrepo
deps:
  - buf.build/googleapis/googleapis
```

Then we need to run `buf mod update` to select a version of the dependency to use.

And that's it! Now if you run:

```sh
$ buf generate
```

It should produce a `*.gw.pb.go` file.

### Using `protoc`

Before we can generate the stubs with `protoc`, we need to copy some dependencies into our proto file structure. Copy a subset of the `googleapis`
from the [official repository](https://github.com/googleapis/googleapis) to your local proto file structure. It should look like this afterwards:

```
proto
├── google
│   └── api
│       ├── annotations.proto
│       └── http.proto
└── helloworld
    └── hello_world.proto
```

Now we need to add the gRPC-Gateway generator to the `protoc` invocation:

```sh
$ protoc -I ./proto \
  --go_out ./proto --go_opt paths=source_relative \
  --go-grpc_out ./proto --go-grpc_opt paths=source_relative \
  --grpc-gateway_out ./proto --grpc-gateway_opt paths=source_relative \
  ./proto/helloworld/hello_world.proto
```

This should generate a `*.gw.pb.go` file.

We also need to add and serve the gRPC-Gateway mux in our `main.go` file.

```
/* Detailed source-code truncated for AI context efficiency. */
```

For more examples, please refer to [our boilerplate repository](https://github.com/johanbrandhorst/grpc-gateway-boilerplate).

## Testing the gRPC-Gateway

Now we can start the server:

```sh
$ go run main.go
```

Then we use cURL to send HTTP requests:

```sh
$ curl -X POST -k http://localhost:8090/v1/example/echo -d '{"name": " hello"}'
```

```
{"message":"hello world"}
```

Hopefully, that gives a bit of understanding of how to use the gRPC-Gateway.

Full source code of hello world program can be found here [helloworld-grpc-gateway](https://github.com/iamrajiv/helloworld-grpc-gateway).

[Next](learn_more.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }

---

### Docs Tutorials Creating Main.Go (`docs/docs/tutorials/creating_main.go.md`)

---
layout: default
title: Creating main.go
nav_order: 3
parent: Tutorials
---

# Creating main.go

Before creating `main.go` file we are assuming that the user has created a `go.mod` with the name `github.com/myuser/myrepo`, if not please refer to [Creating go.mod file](introduction.md#creating-gomod-file). The import here is using the path to the generated files in `proto/helloworld` relative to the root of the repository.

```go
package main

import (
	"context"
	"log"
	"net"

	"google.golang.org/grpc"

	helloworldpb "github.com/myuser/myrepo/proto/helloworld"
)

type server struct{
	helloworldpb.UnimplementedGreeterServer
}

func NewServer() *server {
	return &server{}
}

func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) {
	return &helloworldpb.HelloReply{Message: in.Name + " world"}, nil
}

func main() {
	// Create a listener on TCP port
	lis, err := net.Listen("tcp", ":8080")
	if err != nil {
		log.Fatalln("Failed to listen:", err)
	}

	// Create a gRPC server object
	s := grpc.NewServer()
	// Attach the Greeter service to the server
	helloworldpb.RegisterGreeterServer(s, &server{})
	// Serve gRPC Server
	log.Println("Serving gRPC on 0.0.0.0:8080")
	log.Fatal(s.Serve(lis))
}
```

## Read More

For more refer to gRPC docs [https://grpc.io/docs/languages/go/](https://grpc.io/docs/languages/go/).

[Next](adding_annotations.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }

---

### Docs Tutorials Introduction (`docs/docs/tutorials/introduction.md`)

---
layout: default
title: Introduction to the gRPC-Gateway
nav_order: 0
parent: Tutorials
---

# Introduction to the gRPC-Gateway

We all know that gRPC is not a tool for everything. There are cases where we still want to provide a traditional HTTP/JSON API. The reasons can range from maintaining backward-compatibility to supporting programming languages or clients not well supported by gRPC. But writing another service just to expose an HTTP/JSON API is quite a time consuming and tedious task.

So is there any way to code just once, but provide APIs in both gRPC and HTTP/JSON at the same time?

The answer is Yes.

The gRPC-Gateway is a plugin of the Google protocol buffers compiler [protoc](https://github.com/protocolbuffers/protobuf). It reads protobuf service definitions and generates a reverse-proxy server which translates a RESTful HTTP API into gRPC. This server is generated according to the [`google.api.http`](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto#L46) annotations in your service definitions.

This helps you provide your APIs in both gRPC and HTTP/JSON format at the same time.

<div align="center">
<img src="../../../assets/images/architecture_introduction_diagram.svg" />
</div>

## Prerequisites

Before we start coding, we have to install some tools.

We will be using a Go gRPC server in the examples, so please install Go first from [https://golang.org/dl/](https://golang.org/dl/).

After installing Go, use `go install` to download and build the following binaries:

```sh
$ go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
```

This installs the `protoc` generator plugins we need to generate the stubs. Make sure to add `$GOPATH/bin` to your `$PATH` so that executables installed via `go get` are available on your `$PATH`.

We will be working in a new module for this tutorial, so go ahead and create that in a folder of your choosing now:

### Creating go.mod file

Start your module using the [go mod init command](https://golang.org/cmd/go/#hdr-Initialize_new_module_in_current_directory) to create a go.mod file.

Run the `go mod init` command, giving it the path of the module your code will be in. Here, use github.com/myuser/myrepo for the module path -- in production code, this would be the URL from which your module can be downloaded.

```sh
$ go mod init github.com/myuser/myrepo
go: creating new go.mod: module github.com/myuser/myrepo
```

The `go mod init` command creates a go.mod file that identifies your code as a module that might be used from other code. The file you just created includes only the name of your module and the Go version your code supports. But as you add dependencies -- meaning packages from other modules -- the go.mod file will list the specific module versions to use. This keeps builds reproducible and gives you direct control over which module versions to use.

[Next](simple_hello_world.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }

---

### Docs Tutorials Learn More (`docs/docs/tutorials/learn_more.md`)

---
layout: default
title: Learn More
nav_order: 5
parent: Tutorials
---

# Learn More

## How it works

When the HTTP request arrives at the gRPC-Gateway, it parses the JSON data into a protobuf message. It then makes a normal Go gRPC client request using the parsed protobuf message. The Go gRPC client encodes the protobuf structure into the protobuf binary format and sends it to the gRPC server. The gRPC Server handles the request and returns the response in the protobuf binary format. The Go gRPC client parses it into a protobuf message and returns it to the gRPC-Gateway, which encodes the protobuf message to JSON and returns it to the original client.

## google.api.http

Read more about `google.api.http` in [the source file documentation](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto).

## HTTP and gRPC Transcoding

Read more about HTTP and gRPC Transcoding on [AIP 127](https://google.aip.dev/127).

---

### Docs Tutorials Simple Hello World (`docs/docs/tutorials/simple_hello_world.md`)

---
layout: default
title: Creating a simple hello world with gRPC
nav_order: 1
parent: Tutorials
---

# Creating a simple hello world with gRPC

To understand the gRPC-Gateway we are going to first make a hello world gRPC service.

## Defining your gRPC service using protocol buffers

Before we create a gRPC service, we should create a proto file to define what we need, here we create a file named `hello_world.proto` in the directory `proto/helloworld/hello_world.proto`.

The gRPC service is defined using [Google Protocol Buffers](https://developers.google.com/protocol-buffers). To learn more about how to define a service in a `.proto` file see their [Basics tutorial](https://grpc.io/docs/languages/go/basics/). For now, all you need to know is that both the server and the client stub have a `SayHello()` RPC method that takes a `HelloRequest` parameter from the client and returns a `HelloReply` from the server, and that the method is defined like this:

```protobuf
syntax = "proto3";

package helloworld;

// The greeting service definition
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}
```

[Next](generating_stubs/index.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }

---

### Docs Tutorials Generating Stubs Using Buf (`docs/docs/tutorials/generating_stubs/using_buf.md`)

---
layout: default
title: Generating stubs using buf
nav_order: 0
parent: Generating stubs
grand_parent: Tutorials
---

# Generating stubs using buf

[Buf](https://github.com/bufbuild/buf) is a tool that provides various protobuf utilities such as linting, breaking change detection and generation. Please find installation instructions on [https://docs.buf.build/installation/](https://docs.buf.build/installation/).

It is configured through a `buf.yaml` file that should be checked in to the root of your Protobuf file hierarchy. Buf will automatically read this file if present. Configuration can also be provided via the command-line flag `--config`, which accepts a path to a `.json` or `.yaml` file, or direct JSON or YAML data. As opposed to `protoc`, where all `.proto` files are manually specified on the command-line, buf operates by recursively discovering all `.proto` files under configuration and building them.

The following is an example of a valid configuration, and you would put it in the root of your Protobuf file hierarchy, e.g. in `proto/buf.yaml` relative to the root of your repository.

```yaml
version: v1
name: buf.build/myuser/myrepo
```

To generate type and gRPC stubs for Go, create the file `buf.gen.yaml`:

```yaml
version: v1
plugins:
  - plugin: go
    out: proto
    opt: paths=source_relative
  - plugin: go-grpc
    out: proto
    opt: paths=source_relative
```

We use the `go` and `go-grpc` plugins to generate Go types and gRPC service definitions. We're outputting the generated files relative to the `proto` folder, and we're using the `paths=source_relative` option, which means that the generated files will appear in the same directory as the source `.proto` file.

Then run

```sh
$ buf generate
```

This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for each protobuf package in our `proto` file hierarchy.

[Next](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }

---

### Docs Tutorials Generating Stubs Using Protoc (`docs/docs/tutorials/generating_stubs/using_protoc.md`)

---
layout: default
title: Generating stubs using protoc
nav_order: 1
parent: Generating stubs
grand_parent: Tutorials
---

# Generating stubs using protoc

Here's an example of what a `protoc` command might look like to generate Go stubs, assuming that you're at the root of your repository and you have your proto files in a directory called `proto`:

```sh
$ protoc -I ./proto \
   --go_out ./proto --go_opt paths=source_relative \
   --go-grpc_out ./proto --go-grpc_opt paths=source_relative \
   ./proto/helloworld/hello_world.proto
```

We use the `go` and `go-grpc` plugins to generate Go types and gRPC service definitions. We're outputting the generated files relative to the `proto` folder, and we're using the `paths=source_relative` option, which means that the generated files will appear in the same directory as the source `.proto` file.

This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for `proto/helloworld/hello_world.proto`.

[Next](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }

---

--- METRICS ---
- Files Extracted: 48
- Estimated Token Budget: ~50218 tokens
- Canonical Reference: https://codewiki.google/github.com/grpc-ecosystem/grpc-gateway
