281 lines
11 KiB
Markdown
281 lines
11 KiB
Markdown
# grpc-gateway
|
|
|
|
[](https://github.com/grpc-ecosystem/grpc-gateway/releases) [](https://circleci.com/gh/grpc-ecosystem/grpc-gateway) [](https://codecov.io/gh/grpc-ecosystem/grpc-gateway) [](LICENSE.txt)
|
|
|
|
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 JSON 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.
|
|
|
|
It helps you provide your APIs in both gRPC and RESTful style at the same time.
|
|
|
|

|
|
|
|
## Check out our [documentation](https://grpc-ecosystem.github.io/grpc-gateway/)!
|
|
|
|
## 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
|
|
backwards-compatibility, supporting languages or clients 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
|
|
|
|
The grpc-gateway requires a local installation of the Google protocol buffers
|
|
compiler `protoc` v3.0.0 or above. Please install this via your local package
|
|
manager or by downloading one of the releases from the official repository:
|
|
|
|
https://github.com/protocolbuffers/protobuf/releases
|
|
|
|
|
|
Then, `go get -u` as usual the following packages:
|
|
|
|
```sh
|
|
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
|
|
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger
|
|
go get -u github.com/golang/protobuf/protoc-gen-go
|
|
```
|
|
|
|
This will place three binaries in your `$GOBIN`;
|
|
|
|
* `protoc-gen-grpc-gateway`
|
|
* `protoc-gen-grpc-swagger`
|
|
* `protoc-gen-go`
|
|
|
|
Make sure that your `$GOBIN` is in your `$PATH`.
|
|
|
|
## Usage
|
|
|
|
1. Define your service in gRPC
|
|
|
|
your_service.proto:
|
|
```protobuf
|
|
syntax = "proto3";
|
|
package example;
|
|
message StringMessage {
|
|
string value = 1;
|
|
}
|
|
|
|
service YourService {
|
|
rpc Echo(StringMessage) returns (StringMessage) {}
|
|
}
|
|
```
|
|
2. 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 example;
|
|
+
|
|
+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: "*"
|
|
+ };
|
|
+ }
|
|
}
|
|
```
|
|
|
|
If you do not want to 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/grpcapiconfiguration.html)
|
|
for more information.
|
|
|
|
3. Generate gRPC stub
|
|
|
|
```sh
|
|
protoc -I/usr/local/include -I. \
|
|
-I$GOPATH/src \
|
|
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
|
--go_out=plugins=grpc:. \
|
|
path/to/your_service.proto
|
|
```
|
|
|
|
It will generate a stub file `path/to/your_service.pb.go`.
|
|
4. Implement your service in gRPC as usual
|
|
1. (Optional) Generate gRPC stub in the language you want.
|
|
|
|
e.g.
|
|
```sh
|
|
protoc -I/usr/local/include -I. \
|
|
-I$GOPATH/src \
|
|
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
|
--ruby_out=. \
|
|
path/to/your/service_proto
|
|
|
|
protoc -I/usr/local/include -I. \
|
|
-I$GOPATH/src \
|
|
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
|
--plugin=protoc-gen-grpc=grpc_ruby_plugin \
|
|
--grpc-ruby_out=. \
|
|
path/to/your/service.proto
|
|
```
|
|
2. Add the googleapis-common-protos gem (or your language equivalent) as a dependency to your project.
|
|
3. Implement your service
|
|
|
|
5. Generate reverse-proxy
|
|
|
|
```sh
|
|
protoc -I/usr/local/include -I. \
|
|
-I$GOPATH/src \
|
|
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
|
--grpc-gateway_out=logtostderr=true:. \
|
|
path/to/your_service.proto
|
|
```
|
|
|
|
It will generate a reverse proxy `path/to/your_service.pb.gw.go`.
|
|
|
|
6. Write an entrypoint
|
|
|
|
Now you need to write an entrypoint of the proxy server.
|
|
```go
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"net/http"
|
|
|
|
"github.com/golang/glog"
|
|
"golang.org/x/net/context"
|
|
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
|
"google.golang.org/grpc"
|
|
|
|
gw "path/to/your_service_package"
|
|
)
|
|
|
|
var (
|
|
echoEndpoint = flag.String("echo_endpoint", "localhost:9090", "endpoint of YourService")
|
|
)
|
|
|
|
func run() error {
|
|
ctx := context.Background()
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
defer cancel()
|
|
|
|
mux := runtime.NewServeMux()
|
|
opts := []grpc.DialOption{grpc.WithInsecure()}
|
|
err := gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return http.ListenAndServe(":8080", mux)
|
|
}
|
|
|
|
func main() {
|
|
flag.Parse()
|
|
defer glog.Flush()
|
|
|
|
if err := run(); err != nil {
|
|
glog.Fatal(err)
|
|
}
|
|
}
|
|
```
|
|
|
|
7. (Optional) Generate swagger definitions
|
|
|
|
```sh
|
|
protoc -I/usr/local/include -I. \
|
|
-I$GOPATH/src \
|
|
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
|
|
--swagger_out=logtostderr=true:. \
|
|
path/to/your_service.proto
|
|
```
|
|
|
|
## Parameters and flags
|
|
`protoc-gen-grpc-gateway` supports custom mapping from Protobuf `import` to
|
|
Golang import paths. They are compatible to
|
|
[the parameters with same names in `protoc-gen-go`](https://github.com/golang/protobuf#parameters)
|
|
(except `source_relative`).
|
|
|
|
In addition we also support the `request_context` parameter in order to use the
|
|
`http.Request`'s Context (only for Go 1.7 and above). This parameter can be
|
|
useful to pass request scoped context between the gateway and the gRPC service.
|
|
|
|
`protoc-gen-grpc-gateway` also supports some more command line flags to control
|
|
logging. You can give these flags together with parameters above. Run
|
|
`protoc-gen-grpc-gateway --help` for more details about the flags.
|
|
|
|
## More Examples
|
|
More examples are available under `examples` 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/uannotated_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
|
|
* `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)).
|
|
|
|
## Features
|
|
|
|
### Supported
|
|
|
|
* Generating JSON API handlers.
|
|
* Method parameters in request body.
|
|
* Method parameters in request path.
|
|
* Method parameters in query string.
|
|
* Enum fields in 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/patch.html)
|
|
for more information.
|
|
|
|
### No plan to support
|
|
But patch is 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/master/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
|
|
[jsonpb](https://godoc.org/github.com/golang/protobuf/jsonpb) with
|
|
`OrigName: true`.
|
|
|
|
# Contribution
|
|
See [CONTRIBUTING.md](http://github.com/grpc-ecosystem/grpc-gateway/blob/master/CONTRIBUTING.md).
|
|
|
|
# License
|
|
grpc-gateway is licensed under the BSD 3-Clause License.
|
|
See [LICENSE.txt](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt) for more details.
|