From d57714349ebc7d35611ad092ed9622893a07f824 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Fri, 20 Nov 2020 00:20:40 +0530 Subject: [PATCH 01/19] added tutorials directory on grpc-gateway --- docs/docs/faq.md | 2 +- docs/docs/tutorials/Generating stubs/index.md | 7 + .../tutorials/Generating stubs/using_buf.md | 42 ++++ .../Generating stubs/using_protoc.md | 39 ++++ .../tutorials/basic_arithmetic_grpc_server.md | 91 ++++++++ docs/docs/tutorials/basic_protos.md | 110 ++++++++++ docs/docs/tutorials/index.md | 6 + docs/docs/tutorials/simple_hello_world.md | 198 ++++++++++++++++++ 8 files changed, 494 insertions(+), 1 deletion(-) create mode 100644 docs/docs/tutorials/Generating stubs/index.md create mode 100644 docs/docs/tutorials/Generating stubs/using_buf.md create mode 100644 docs/docs/tutorials/Generating stubs/using_protoc.md create mode 100644 docs/docs/tutorials/basic_arithmetic_grpc_server.md create mode 100644 docs/docs/tutorials/basic_protos.md create mode 100644 docs/docs/tutorials/index.md create mode 100644 docs/docs/tutorials/simple_hello_world.md diff --git a/docs/docs/faq.md b/docs/docs/faq.md index 5457f350e04..875f28a1985 100644 --- a/docs/docs/faq.md +++ b/docs/docs/faq.md @@ -1,7 +1,7 @@ --- layout: default title: FAQ -nav_order: 7 +nav_order: 8 --- # FAQ diff --git a/docs/docs/tutorials/Generating stubs/index.md b/docs/docs/tutorials/Generating stubs/index.md new file mode 100644 index 00000000000..80bed9822d2 --- /dev/null +++ b/docs/docs/tutorials/Generating stubs/index.md @@ -0,0 +1,7 @@ +--- +layout: default +title: Generating stubs +parent: Tutorials +nav_order: 1 +has_children: true +--- diff --git a/docs/docs/tutorials/Generating stubs/using_buf.md b/docs/docs/tutorials/Generating stubs/using_buf.md new file mode 100644 index 00000000000..64b2da89183 --- /dev/null +++ b/docs/docs/tutorials/Generating stubs/using_buf.md @@ -0,0 +1,42 @@ +--- +layout: default +title: Generating stubs using buf +parent: Generating stubs +grand_parent: Tutorials +nav_order: 1 +--- + +## Generating stubs using buf + +Buf is configured through a `buf.yaml` file that should be checked in to the root of your repository. 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. + +All Buf operations that use your local `.proto` files as input rely on a valid build configuration. This configuration tells Buf where to search for `.proto` files, and how to handle imports. 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 all configuration options for the build. + +```yml +version: v1beta1 +build: + roots: + - proto + - vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis + excludes: + - proto/foo/bar +``` + +To generate stubs for for multiple languages. Create the file `buf.gen.yaml` at the root of the repository: + +```yml +version: v1beta1 +plugins: + - name: java + out: java + - name: cpp + out: cpp +``` + +Then run + +```sh +buf generate --file ./proto/example.proto +``` diff --git a/docs/docs/tutorials/Generating stubs/using_protoc.md b/docs/docs/tutorials/Generating stubs/using_protoc.md new file mode 100644 index 00000000000..3d81387b65b --- /dev/null +++ b/docs/docs/tutorials/Generating stubs/using_protoc.md @@ -0,0 +1,39 @@ +--- +layout: default +title: Generating stubs using protoc +parent: Generating stubs +grand_parent: Tutorials +nav_order: 2 +--- + +## Generating stubs using protoc + +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 of what a `protoc` command might look like to generate Go stubs: + + ```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 + ``` diff --git a/docs/docs/tutorials/basic_arithmetic_grpc_server.md b/docs/docs/tutorials/basic_arithmetic_grpc_server.md new file mode 100644 index 00000000000..937ab334c23 --- /dev/null +++ b/docs/docs/tutorials/basic_arithmetic_grpc_server.md @@ -0,0 +1,91 @@ +--- +layout: default +title: Creating a Basic Arithmetic gRPC Server +parent: Tutorials +nav_order: 3 +--- + +## Creating a Basic Arithmetic gRPC Server + +First look at the `main.go` file of Arithmetic server that will serve on a given port and listening at the endpoint we defined in proto files. + +At the top of the file, we define the handlers for our gRPC methods. + +Handlers are: + +```go +// This is the struct that we will implement all the handlers on +type Server struct { + a *pbExample.Request + b *pbExample.Request + Result *pbExample.Response +} + +// This is where you implement the handler for the Add method +func (s *Server) Add(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { + a, b := request.GetA(), request.GetB() + + result := a + b + + return &pbExample.Response{Result: result}, nil +} + +// This is where you implement the handler for the Divide method +func (s *Server) Divide(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { + a, b := request.GetA(), request.GetB() + + result := a / b + + return &pbExample.Response{Result: result}, nil +} + +// This is where you implement the handler for the Multiply method +func (s *Server) Multiply(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { + a, b := request.GetA(), request.GetB() + + result := a * b + + return &pbExample.Response{Result: result}, nil +} + +// This is where you implement the handler for the Subtract method +func (s *Server) Subtract(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { + a, b := request.GetA(), request.GetB() + + result := a - b + + return &pbExample.Response{Result: result}, nil +} +``` + +Now rest fo `main.go` file are: + +```go +func main() { + + // Adds gRPC internal logs. This is quite verbose, so adjust as desired! + log := grpclog.NewLoggerV2(os.Stdout, ioutil.Discard, ioutil.Discard) + grpclog.SetLoggerV2(log) + + addr := "0.0.0.0:10000" + lis, err := net.Listen("tcp", addr) + if err != nil { + log.Fatalln("Failed to listen:", err) + } + + s := grpc.NewServer( + // TODO: Replace with your own certificate! + grpc.Creds(credentials.NewServerTLSFromCert(&insecure.Cert)), + ) + pbExample.RegisterArithmeticServiceServer(s, &Server{}) + + // Serve gRPC Server + log.Info("Serving gRPC on https://", addr) + go func() { + log.Fatal(s.Serve(lis)) + }() + + err = gateway.Run("dns:///" + addr) + log.Fatalln(err) +} +``` diff --git a/docs/docs/tutorials/basic_protos.md b/docs/docs/tutorials/basic_protos.md new file mode 100644 index 00000000000..55be63b8e2c --- /dev/null +++ b/docs/docs/tutorials/basic_protos.md @@ -0,0 +1,110 @@ +--- +layout: default +title: Creating a basic protos with HTTP annotations +parent: Tutorials +nav_order: 2 +--- + +## Creating a basic protos with HTTP annotations + +### Annotating your gRPC .proto file with HTTP bindings and routes + +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 you will need to add `import "google/api/annotations.proto";` to the gRPC proto file. + +To make a Basic Arithmetic service first we have to define our services in proto files. + +```proto +syntax="proto3"; + +package example; + +import "google/api/annotations.proto"; +import "protoc-gen-openapiv2/options/annotations.proto"; + +// Defines the import path that should be used to import the generated package, +// and the package name. +option go_package = "github.com/iamrajiv/Basic-Arithmetic-gRPC-Server/proto;example"; + +// These annotations are used when generating the OpenAPI file. +option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { + info: { + version: "1.0"; + }; + external_docs: { + url: "https://github.com/iamrajiv/Basic-Arithmetic-gRPC-Server"; + description: "Basic-Arithmetic-gRPC-Server"; + } + schemes: HTTPS; +}; + +// This will be our request +message Request { +// First integer in the body of the request + int64 a = 1; +// Second integer in the body of the request + int64 b = 2; +} + +// This will be our response +message Response { +// A integer in the body of the response + int64 result = 1; +} + +// Here is the overall service where we define all our endpoints +service ArithmeticService { +// Here is our Add method to use as an service + rpc Add(Request) returns (Response){ + option (google.api.http) = { + post: "/api/v1/arithmetic/add" + body: "*" + }; + }; + // Here is our Divide method to use as an service + rpc Divide(Request) returns (Response){ + option (google.api.http) = { + post: "/api/v1/arithmetic/div" + body: "*" + }; + }; + // Here is our Multiply method to use as an service + rpc Multiply(Request) returns (Response){ + option (google.api.http) = { + post: "/api/v1/arithmetic/mul" + body: "*" + }; + }; +// Here is our Subtract method to use as an service + rpc Subtract(Request) returns (Response){ + option (google.api.http) = { + post: "/api/v1/arithmetic/sub" + body: "*" + }; + }; +} +``` + +### HTTP method and path + +- The first key (`post` in this service) corresponds to the HTTP method. RPCs **may** use `get`, `post`, `patch`, or `delete`. + - RPCs **must** use the prescribed HTTP verb for each standard method, as discussed in [AIP-131](https://google.aip.dev/131), [AIP-132](https://google.aip.dev/132), [AIP-133](https://google.aip.dev/133), [AIP-134](https://google.aip.dev/134), and [AIP-135](https://google.aip.dev/135) + - RPCs **should** use the prescribed HTTP verb for custom methods, as discussed in [AIP-136](https://google.aip.dev/136). + - RPCs **should not** use `put` or `custom`. +- The corresponding value represents the URI. + - URIs **must** use the `{foo=bar/*}` syntax to represent a variable that should be populated in the request proto. When extracting a [resource name](https://google.aip.dev/122), the variable **must** include the entire resource name, not just the ID component. + - URIs **must** use the `` character to represent ID components, which matches all URI-safe characters except for `/`. URIs **may** use `*` as the final segment of a URI if matching `/` is required. +- The `body` key defines which field in the request will be sent as the HTTP body. If the body is ``, then this indicates that the request object itself is the HTTP body. The request body is encoded as JSON as defined by protocol buffers' canonical [JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json). + - RPCs **must not** define a `body` at all for RPCs that use the `GET` or `DELETE` HTTP verbs. + - RPCs **must** use the prescribed `body` for Create ([AIP-133](https://google.aip.dev/133)) and Update ([AIP-134](https://google.aip.dev/134)) requests. + - RPCs **should** use the prescribed `body` for custom methods ([AIP-136](https://google.aip.dev/136)). + - Fields **should not** use the `json_name` annotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons. + +You’ll see some atypical fields in the .proto that are leveraged by grpc-gateway. One of the most important of these fields is the option (google.api.http) where we define what HTTP URL(s) will be used to handle our request. + +We also specify POST as the HTTP method we will accept. + +Finally, if you have a request body that you expect (typical for POST requests and others), you must use the body field. If you don’t, then the request won’t be passed along to the handler. + +Read more about HTTP and gRPC Transcoding on https://google.aip.dev/127. diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md new file mode 100644 index 00000000000..af5856ec9e3 --- /dev/null +++ b/docs/docs/tutorials/index.md @@ -0,0 +1,6 @@ +--- +layout: default +title: Tutorials +nav_order: 7 +has_children: true +--- diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md new file mode 100644 index 00000000000..37fabe393eb --- /dev/null +++ b/docs/docs/tutorials/simple_hello_world.md @@ -0,0 +1,198 @@ +--- +layout: default +title: Creating a simple hello world with gRPC-Gateway +parent: Tutorials +nav_order: 4 +--- + +### Creating a simple hello world with gRPC-Gateway + +### gRPC-Gateway + +We all know that gRPC is not a tool for everything. There are cases where we still want to provide a traditional RESTful JSON API. The reasons can range from maintaining backwards-compatibility to supporting programming languages or clients not well supported by gRPC. But coding another API for REST is quite a time consuming and tedious. + +So is there any way to code just once, but can provide APIs in both gRPC and REST at the same time? + +The answer is Yes. + +### Usage + +One way to achieve that is to use gRPC gateway. gRPC gateway is a plugin of the protocol buffer compiler. It reads the protobuf service definitions and generates a proxy server, which translates a RESTful HTTP call into gRPC request. + +All we need to do is a small amount of configuration +in the service. Before start coding, we have to install some +tools. + +Use `go get -u` to download 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 +``` + +### Define and Generate proto files + +Before we create a gRPC service, we should create a proto file to define what we need, here we create a file named `hello.proto` to show. + +```proto +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.helloworld"; +option java_outer_classname = "HelloWorldProto"; + +package helloworld; + +import "google/api/annotations.proto"; + +// The greeting service definition. +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; +} +``` + +Then we should generate gRPC stub via protoc + +```sh +protoc -I/usr/local/include -I. \ +-I$GOPATH/src \ +-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ +--go_out=Mgoogle/api/annotations.proto=github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api,plugins=grpc:. \ +helloworld/helloworld.proto +``` + +The `helloworld.pb.go` file will be generated. So `helloworld.pb.go` is required by the server service. + +Next we need to use protoc to generate the go files needed by the gateway. + +```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:. \ +helloworld/helloworld.proto +``` + +The `helloworld.pb.gw.go` file will be generated. This file is the protocol file used by gateway for protocol conversion between grpc and http. + +After the protocol file is processed, the gateway code is needed. + +### Implementation + +The gateway code is as follows: + +```go +package main + +import ( + "flag" + "net/http" + + "github.com/golang/glog" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "golang.org/x/net/context" + "google.golang.org/grpc" + + gw "grpc-helloworld-gateway/helloworld" +) + +var ( + echoEndpoint = flag.String("echo_endpoint", "localhost:50051", "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.RegisterGreeterHandlerFromEndpoint(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) + } +} +``` + +First echoEndpoint stores the server information that needs to be connected, and then registers and binds the new server with RegisterGreeter Handler FromEndpoint in `gw.go`. Then the lower level will connect to the remote server address provided by echoEndpoint, so the gateway establishes the connection as the client and remote server, and then starts the new server with http, gateway. It serves as a server to provide HTTP services to the outside world. + +This is the end of the code. Let's test it. + +Start the greeter_server service first, and then start the gateway. Then gateway connects to greeter_server and establishes http monitoring. + +Then we use curl to send http requests: + +```sh +curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " world"} +``` + +``` +{"message":"Hello world"} +``` + +The process is as follows: + +curl sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and json returns to the front end. + +In this way, the transformation process from http json to internal grpc is completed through grpc-gateway. + +### More + +#### google.api.http + +GRPC transcoding is a conversion function between the gRPC method and one or more HTTP REST endpoints. This allows developers to create a single API service that supports both the gRPC API and the REST API. Many systems, including the API Google, Cloud Endpoints, gRPC Gateway, and the Envoy proxy server support this feature and use it for large-scale production services. + +The grcp-gateway the server is created according to the `google.api.http` annotations in your service definitions. + +HttpRule defines the gRPC / REST mapping scheme. The mapping defines how different parts of a gRPC request message are mapped to the URL path, URL request parameters, and HTTP request body. It also controls how the gRPC response message is displayed in the HTTP response body. HttpRule is usually specified as a `google.api.http` annotation in the gRPC method. + +Each mapping defines a URL path template and an HTTP method. A path template can refer to one or more fields in a gRPC request message if each field is a non-repeating field with a primitive type. The path template controls how the request message fields are mapped to the URL path. + +```proto +import "google/api/annotations.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +message StatusResponse { + google.protobuf.Timestamp current_time = 1; +} +service MyService { + rpc Status(google.protobuf.Empty) + returns (StatusResponse) { + option (google.api.http) = { + get: "/status" + }; + } + } +} +``` + +You will need to provide the necessary third-party `protobuf` files to the `protoc` compiler. They have included in the `grpc-gateway` repository in the `[third_party/googleapis](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis)` folder, and we recommend copying them to the project file structure. + +You will need to provide the necessary third-party `protobuf` files to the `protoc` compiler. They are included in the `[grpc-gateway` repository](https://github.com/grpc-ecosystem/grpc-gateway/) in the `[third_party/googleapis](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis)` folder and we recommend copying them to the project file structure. From 01793846694433472179eca1a7ff721ef7252631 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Fri, 20 Nov 2020 00:22:27 +0530 Subject: [PATCH 02/19] refactored badges and links --- docs/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index 397dd66dedb..0f702c8e09a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -19,13 +19,13 @@ This server is generated according to [custom options](https://cloud.google.com/ --- -## About +## Getting started [![circleci](https://img.shields.io/circleci/build/github/grpc-ecosystem/grpc-gateway?color=379c9c&logo=circleci&logoColor=ffffff&style=flat-square)](https://circleci.com/gh/grpc-ecosystem/grpc-gateway) [![codecov](https://img.shields.io/codecov/c/github/grpc-ecosystem/grpc-gateway?color=379c9c&logo=codecov&logoColor=ffffff&style=flat-square)](https://codecov.io/gh/grpc-ecosystem/grpc-gateway) -[![forks](https://img.shields.io/github/forks/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square)](https://github.com/grpc-ecosystem/grpc-gateway/network/members) -[![issues](https://img.shields.io/github/issues/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square)](https://github.com/grpc-ecosystem/grpc-gateway/issues) +[![slack](https://img.shields.io/badge/slack-grpc--gateway-379c9c?logo=slack&logoColor=ffffff&style=flat-square)](https://app.slack.com/client/T029RQSE6/CBATURP1D) [![license](https://img.shields.io/github/license/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square)](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/LICENSE.txt) +[![release](https://img.shields.io/github/v/release/grpc-ecosystem/grpc-gateway?color=379c9c&logoColor=ffffff&style=flat-square)](https://github.com/grpc-ecosystem/grpc-gateway/releases) [![stars](https://img.shields.io/github/stars/grpc-ecosystem/grpc-gateway?color=379c9c&style=flat-square)](https://github.com/grpc-ecosystem/grpc-gateway/stargazers) grpc-gateway is a plugin of [protoc](https://github.com/protocolbuffers/protobuf). From 0d16f4d6c6ec2d47ab9eeb9e6dc39ad9133665c6 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Fri, 20 Nov 2020 20:57:48 +0530 Subject: [PATCH 03/19] added requested changes --- docs/docs/tutorials/Generating stubs/index.md | 2 +- .../tutorials/Generating stubs/using_buf.md | 30 ++-- .../Generating stubs/using_protoc.md | 35 ++--- docs/docs/tutorials/adding_annotations.md | 26 ++++ .../tutorials/basic_arithmetic_grpc_server.md | 67 +++------ docs/docs/tutorials/basic_protos.md | 31 +--- docs/docs/tutorials/learn_more.md | 40 ++++++ docs/docs/tutorials/prerequisites.md | 28 ++++ docs/docs/tutorials/simple_hello_world.md | 134 +----------------- 9 files changed, 152 insertions(+), 241 deletions(-) create mode 100644 docs/docs/tutorials/adding_annotations.md create mode 100644 docs/docs/tutorials/learn_more.md create mode 100644 docs/docs/tutorials/prerequisites.md diff --git a/docs/docs/tutorials/Generating stubs/index.md b/docs/docs/tutorials/Generating stubs/index.md index 80bed9822d2..1f927046d68 100644 --- a/docs/docs/tutorials/Generating stubs/index.md +++ b/docs/docs/tutorials/Generating stubs/index.md @@ -2,6 +2,6 @@ layout: default title: Generating stubs parent: Tutorials -nav_order: 1 +nav_order: 2 has_children: true --- diff --git a/docs/docs/tutorials/Generating stubs/using_buf.md b/docs/docs/tutorials/Generating stubs/using_buf.md index 64b2da89183..f2cacffecfd 100644 --- a/docs/docs/tutorials/Generating stubs/using_buf.md +++ b/docs/docs/tutorials/Generating stubs/using_buf.md @@ -8,35 +8,41 @@ nav_order: 1 ## Generating stubs using buf -Buf is configured through a `buf.yaml` file that should be checked in to the root of your repository. 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. +[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://github.com/bufbuild/buf. + +It is configured through a `buf.yaml` file that should be checked in to the root of your repository. 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. All Buf operations that use your local `.proto` files as input rely on a valid build configuration. This configuration tells Buf where to search for `.proto` files, and how to handle imports. 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 all configuration options for the build. +The following is an example of a valid configuration, assuming you have your `.proto` files rooted in the `proto` folder relative to the root of your repository. ```yml version: v1beta1 build: roots: - proto - - vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis - excludes: - - proto/foo/bar + - third_party/grpc-gateway + - third_party/googleapis ``` -To generate stubs for for multiple languages. Create the file `buf.gen.yaml` at the root of the repository: +To generate type and gRPC stubs for Go, create the file `buf.gen.yaml` at the root of the repository: ```yml -version: v1beta1 plugins: - - name: java - out: java - - name: cpp - out: cpp + - name: go + out: proto + opt: paths=source_relative + - name: 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 --file ./proto/example.proto +buf generate ``` + +This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for each protobuf package in our `proto` file hierarchy. diff --git a/docs/docs/tutorials/Generating stubs/using_protoc.md b/docs/docs/tutorials/Generating stubs/using_protoc.md index 3d81387b65b..0f3d40b54c9 100644 --- a/docs/docs/tutorials/Generating stubs/using_protoc.md +++ b/docs/docs/tutorials/Generating stubs/using_protoc.md @@ -8,32 +8,15 @@ nav_order: 2 ## Generating stubs using protoc -1. Define your [gRPC](https://grpc.io/docs/) service using protocol buffers +Generate gRPC stubs: - `your_service.proto`: +This step generates the gRPC stubs that you can use to implement the service and consume from clients. - ```protobuf - syntax = "proto3"; - package your.service.v1; - option go_package = "github.com/yourorg/yourprotos/gen/go/your/service/v1"; - message StringMessage { - string value = 1; - } +Here's an example of what a `protoc` command might look like to generate Go stubs: - 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 of what a `protoc` command might look like to generate Go stubs: - - ```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 - ``` +```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 +``` diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md new file mode 100644 index 00000000000..d8ce53001ad --- /dev/null +++ b/docs/docs/tutorials/adding_annotations.md @@ -0,0 +1,26 @@ +--- +layout: default +title: Adding the grpc-gateway annotations to an existing protobuf file +parent: Tutorials +nav_order: 6 +--- + +## Adding the grpc-gateway annotations to an existing protobuf file + +Start the greeter_server service first, and then start the gateway. Then gateway connects to greeter_server and establishes http monitoring. + +Then we use curl to send http requests: + +```sh +curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " world"} +``` + +``` +{"message":"Hello world"} +``` + +The process is as follows: + +curl sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and json returns to the front end. + +In this way, the transformation process from http json to internal grpc is completed through grpc-gateway. diff --git a/docs/docs/tutorials/basic_arithmetic_grpc_server.md b/docs/docs/tutorials/basic_arithmetic_grpc_server.md index 937ab334c23..d3e32d8542c 100644 --- a/docs/docs/tutorials/basic_arithmetic_grpc_server.md +++ b/docs/docs/tutorials/basic_arithmetic_grpc_server.md @@ -2,12 +2,12 @@ layout: default title: Creating a Basic Arithmetic gRPC Server parent: Tutorials -nav_order: 3 +nav_order: 4 --- ## Creating a Basic Arithmetic gRPC Server -First look at the `main.go` file of Arithmetic server that will serve on a given port and listening at the endpoint we defined in proto files. +Before we make `main.go` file first we have to make `server.go` file in a separate folder. At the top of the file, we define the handlers for our gRPC methods. @@ -16,76 +16,47 @@ Handlers are: ```go // This is the struct that we will implement all the handlers on type Server struct { - a *pbExample.Request - b *pbExample.Request - Result *pbExample.Response + a *pbExample.Request + b *pbExample.Request + Result *pbExample.Response } // This is where you implement the handler for the Add method func (s *Server) Add(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() + a, b := request.GetA(), request.GetB() - result := a + b + result := a + b - return &pbExample.Response{Result: result}, nil + return &pbExample.Response{Result: result}, nil } // This is where you implement the handler for the Divide method func (s *Server) Divide(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() + a, b := request.GetA(), request.GetB() - result := a / b + result := a / b - return &pbExample.Response{Result: result}, nil + return &pbExample.Response{Result: result}, nil } // This is where you implement the handler for the Multiply method func (s *Server) Multiply(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() + a, b := request.GetA(), request.GetB() - result := a * b + result := a * b - return &pbExample.Response{Result: result}, nil + return &pbExample.Response{Result: result}, nil } // This is where you implement the handler for the Subtract method func (s *Server) Subtract(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() + a, b := request.GetA(), request.GetB() - result := a - b + result := a - b - return &pbExample.Response{Result: result}, nil + return &pbExample.Response{Result: result}, nil } ``` -Now rest fo `main.go` file are: - -```go -func main() { - - // Adds gRPC internal logs. This is quite verbose, so adjust as desired! - log := grpclog.NewLoggerV2(os.Stdout, ioutil.Discard, ioutil.Discard) - grpclog.SetLoggerV2(log) - - addr := "0.0.0.0:10000" - lis, err := net.Listen("tcp", addr) - if err != nil { - log.Fatalln("Failed to listen:", err) - } - - s := grpc.NewServer( - // TODO: Replace with your own certificate! - grpc.Creds(credentials.NewServerTLSFromCert(&insecure.Cert)), - ) - pbExample.RegisterArithmeticServiceServer(s, &Server{}) - - // Serve gRPC Server - log.Info("Serving gRPC on https://", addr) - go func() { - log.Fatal(s.Serve(lis)) - }() - - err = gateway.Run("dns:///" + addr) - log.Fatalln(err) -} -``` +For `main.go` file of Arithmetic server that will serve on a given port and listening at the endpoint, we defined in proto files we can refer to the boilerplate repository [grpc-gateway-boilerplate +Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). diff --git a/docs/docs/tutorials/basic_protos.md b/docs/docs/tutorials/basic_protos.md index 55be63b8e2c..a2e59d057d4 100644 --- a/docs/docs/tutorials/basic_protos.md +++ b/docs/docs/tutorials/basic_protos.md @@ -2,7 +2,7 @@ layout: default title: Creating a basic protos with HTTP annotations parent: Tutorials -nav_order: 2 +nav_order: 3 --- ## Creating a basic protos with HTTP annotations @@ -11,7 +11,7 @@ nav_order: 2 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 you will need to add `import "google/api/annotations.proto";` to the gRPC proto file. +So you will need to add `import "google/api/hello_world.proto";` to the gRPC proto file. To make a Basic Arithmetic service first we have to define our services in proto files. @@ -20,8 +20,8 @@ syntax="proto3"; package example; -import "google/api/annotations.proto"; -import "protoc-gen-openapiv2/options/annotations.proto"; +import "google/api/hello_world.proto"; +import "protoc-gen-openapiv2/options/hello_world.proto"; // Defines the import path that should be used to import the generated package, // and the package name. @@ -85,26 +85,3 @@ service ArithmeticService { }; } ``` - -### HTTP method and path - -- The first key (`post` in this service) corresponds to the HTTP method. RPCs **may** use `get`, `post`, `patch`, or `delete`. - - RPCs **must** use the prescribed HTTP verb for each standard method, as discussed in [AIP-131](https://google.aip.dev/131), [AIP-132](https://google.aip.dev/132), [AIP-133](https://google.aip.dev/133), [AIP-134](https://google.aip.dev/134), and [AIP-135](https://google.aip.dev/135) - - RPCs **should** use the prescribed HTTP verb for custom methods, as discussed in [AIP-136](https://google.aip.dev/136). - - RPCs **should not** use `put` or `custom`. -- The corresponding value represents the URI. - - URIs **must** use the `{foo=bar/*}` syntax to represent a variable that should be populated in the request proto. When extracting a [resource name](https://google.aip.dev/122), the variable **must** include the entire resource name, not just the ID component. - - URIs **must** use the `` character to represent ID components, which matches all URI-safe characters except for `/`. URIs **may** use `*` as the final segment of a URI if matching `/` is required. -- The `body` key defines which field in the request will be sent as the HTTP body. If the body is ``, then this indicates that the request object itself is the HTTP body. The request body is encoded as JSON as defined by protocol buffers' canonical [JSON encoding](https://developers.google.com/protocol-buffers/docs/proto3#json). - - RPCs **must not** define a `body` at all for RPCs that use the `GET` or `DELETE` HTTP verbs. - - RPCs **must** use the prescribed `body` for Create ([AIP-133](https://google.aip.dev/133)) and Update ([AIP-134](https://google.aip.dev/134)) requests. - - RPCs **should** use the prescribed `body` for custom methods ([AIP-136](https://google.aip.dev/136)). - - Fields **should not** use the `json_name` annotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons. - -You’ll see some atypical fields in the .proto that are leveraged by grpc-gateway. One of the most important of these fields is the option (google.api.http) where we define what HTTP URL(s) will be used to handle our request. - -We also specify POST as the HTTP method we will accept. - -Finally, if you have a request body that you expect (typical for POST requests and others), you must use the body field. If you don’t, then the request won’t be passed along to the handler. - -Read more about HTTP and gRPC Transcoding on https://google.aip.dev/127. diff --git a/docs/docs/tutorials/learn_more.md b/docs/docs/tutorials/learn_more.md new file mode 100644 index 00000000000..332f018e316 --- /dev/null +++ b/docs/docs/tutorials/learn_more.md @@ -0,0 +1,40 @@ +--- +layout: default +title: Learn More +parent: Tutorials +nav_order: 7 +--- + +## Learn More + +#### google.api.http + +GRPC transcoding is a conversion function between the gRPC method and one or more HTTP REST endpoints. This allows developers to create a single API service that supports both the gRPC API and the REST API. Many systems, including the API Google, Cloud Endpoints, gRPC Gateway, and the Envoy proxy server support this feature and use it for large-scale production services. + +The grcp-gateway the server is created according to the `google.api.http` annotations in your service definitions. + +HttpRule defines the gRPC / REST mapping scheme. The mapping defines how different parts of a gRPC request message are mapped to the URL path, URL request parameters, and HTTP request body. It also controls how the gRPC response message is displayed in the HTTP response body. HttpRule is usually specified as a `google.api.http` annotation in the gRPC method. + +Each mapping defines a URL path template and an HTTP method. A path template can refer to one or more fields in a gRPC request message if each field is a non-repeating field with a primitive type. The path template controls how the request message fields are mapped to the URL path. + +```proto +import "google/api/annotations.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/timestamp.proto"; +message StatusResponse { + google.protobuf.Timestamp current_time = 1; +} +service MyService { + rpc Status(google.protobuf.Empty) + returns (StatusResponse) { + option (google.api.http) = { + get: "/status" + }; + } + } +} +``` + +You will need to provide the necessary third-party `protobuf` files to the `protoc` compiler. They have included in the `grpc-gateway` repository in the `[third_party/googleapis](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis)` folder, and we recommend copying them to the project file structure. + +Read more about HTTP and gRPC Transcoding on https://google.aip.dev/127. diff --git a/docs/docs/tutorials/prerequisites.md b/docs/docs/tutorials/prerequisites.md new file mode 100644 index 00000000000..984580d8ae2 --- /dev/null +++ b/docs/docs/tutorials/prerequisites.md @@ -0,0 +1,28 @@ +--- +layout: default +title: Prerequisites +parent: Tutorials +nav_order: 1 +--- + +## Prerequisites + +One way to achieve that is to use gRPC gateway. gRPC gateway is a plugin of the protocol buffer compiler. It reads the protobuf service definitions and generates a proxy server, which translates a RESTful HTTP call into gRPC request. + +All we need to do is a small amount of configuration +in the service. Before 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 get` to download the following packages: + +```sh +go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway +go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 +go get google.golang.org/protobuf/cmd/protoc-gen-go +go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger +go get -u github.com/golang/protobuf/protoc-gen-go +``` + +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`. diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 37fabe393eb..ecffed41f28 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -2,7 +2,7 @@ layout: default title: Creating a simple hello world with gRPC-Gateway parent: Tutorials -nav_order: 4 +nav_order: 5 --- ### Creating a simple hello world with gRPC-Gateway @@ -15,22 +15,6 @@ So is there any way to code just once, but can provide APIs in both gRPC and RES The answer is Yes. -### Usage - -One way to achieve that is to use gRPC gateway. gRPC gateway is a plugin of the protocol buffer compiler. It reads the protobuf service definitions and generates a proxy server, which translates a RESTful HTTP call into gRPC request. - -All we need to do is a small amount of configuration -in the service. Before start coding, we have to install some -tools. - -Use `go get -u` to download 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 -``` - ### Define and Generate proto files Before we create a gRPC service, we should create a proto file to define what we need, here we create a file named `hello.proto` to show. @@ -38,10 +22,6 @@ Before we create a gRPC service, we should create a proto file to define what we ```proto syntax = "proto3"; -option java_multiple_files = true; -option java_package = "io.grpc.examples.helloworld"; -option java_outer_classname = "HelloWorldProto"; - package helloworld; import "google/api/annotations.proto"; @@ -71,11 +51,10 @@ message HelloReply { Then we should generate gRPC stub via protoc ```sh -protoc -I/usr/local/include -I. \ --I$GOPATH/src \ --I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \ ---go_out=Mgoogle/api/annotations.proto=github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api,plugins=grpc:. \ -helloworld/helloworld.proto +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/hello_world.proto ``` The `helloworld.pb.go` file will be generated. So `helloworld.pb.go` is required by the server service. @@ -95,104 +74,5 @@ After the protocol file is processed, the gateway code is needed. ### Implementation -The gateway code is as follows: - -```go -package main - -import ( - "flag" - "net/http" - - "github.com/golang/glog" - "github.com/grpc-ecosystem/grpc-gateway/runtime" - "golang.org/x/net/context" - "google.golang.org/grpc" - - gw "grpc-helloworld-gateway/helloworld" -) - -var ( - echoEndpoint = flag.String("echo_endpoint", "localhost:50051", "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.RegisterGreeterHandlerFromEndpoint(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) - } -} -``` - -First echoEndpoint stores the server information that needs to be connected, and then registers and binds the new server with RegisterGreeter Handler FromEndpoint in `gw.go`. Then the lower level will connect to the remote server address provided by echoEndpoint, so the gateway establishes the connection as the client and remote server, and then starts the new server with http, gateway. It serves as a server to provide HTTP services to the outside world. - -This is the end of the code. Let's test it. - -Start the greeter_server service first, and then start the gateway. Then gateway connects to greeter_server and establishes http monitoring. - -Then we use curl to send http requests: - -```sh -curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " world"} -``` - -``` -{"message":"Hello world"} -``` - -The process is as follows: - -curl sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and json returns to the front end. - -In this way, the transformation process from http json to internal grpc is completed through grpc-gateway. - -### More - -#### google.api.http - -GRPC transcoding is a conversion function between the gRPC method and one or more HTTP REST endpoints. This allows developers to create a single API service that supports both the gRPC API and the REST API. Many systems, including the API Google, Cloud Endpoints, gRPC Gateway, and the Envoy proxy server support this feature and use it for large-scale production services. - -The grcp-gateway the server is created according to the `google.api.http` annotations in your service definitions. - -HttpRule defines the gRPC / REST mapping scheme. The mapping defines how different parts of a gRPC request message are mapped to the URL path, URL request parameters, and HTTP request body. It also controls how the gRPC response message is displayed in the HTTP response body. HttpRule is usually specified as a `google.api.http` annotation in the gRPC method. - -Each mapping defines a URL path template and an HTTP method. A path template can refer to one or more fields in a gRPC request message if each field is a non-repeating field with a primitive type. The path template controls how the request message fields are mapped to the URL path. - -```proto -import "google/api/annotations.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/timestamp.proto"; -message StatusResponse { - google.protobuf.Timestamp current_time = 1; -} -service MyService { - rpc Status(google.protobuf.Empty) - returns (StatusResponse) { - option (google.api.http) = { - get: "/status" - }; - } - } -} -``` - -You will need to provide the necessary third-party `protobuf` files to the `protoc` compiler. They have included in the `grpc-gateway` repository in the `[third_party/googleapis](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis)` folder, and we recommend copying them to the project file structure. - -You will need to provide the necessary third-party `protobuf` files to the `protoc` compiler. They are included in the `[grpc-gateway` repository](https://github.com/grpc-ecosystem/grpc-gateway/) in the `[third_party/googleapis](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis)` folder and we recommend copying them to the project file structure. +For `main.go` file of hello world we can refer to the boilerplate repository [grpc-gateway-boilerplate +Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). From ed7913b736664b2ce7ccf0ae8f3d44d6cae1a26f Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sat, 21 Nov 2020 20:39:06 +0530 Subject: [PATCH 04/19] updated tutorials directory on grpc-gateway --- .../Generating stubs/using_protoc.md | 22 ----- docs/docs/tutorials/adding_annotations.md | 55 +++++++++++++ .../tutorials/basic_arithmetic_grpc_server.md | 62 -------------- docs/docs/tutorials/basic_protos.md | 80 ++++--------------- docs/docs/tutorials/creating_main.go.md | 10 +++ .../index.md | 2 +- .../using_buf.md | 2 - .../generating_stubs/using_protoc.md | 26 ++++++ docs/docs/tutorials/introduction.md | 45 +++++++++++ docs/docs/tutorials/prerequisites.md | 28 ------- docs/docs/tutorials/simple_hello_world.md | 60 ++------------ 11 files changed, 156 insertions(+), 236 deletions(-) delete mode 100644 docs/docs/tutorials/Generating stubs/using_protoc.md delete mode 100644 docs/docs/tutorials/basic_arithmetic_grpc_server.md create mode 100644 docs/docs/tutorials/creating_main.go.md rename docs/docs/tutorials/{Generating stubs => generating_stubs}/index.md (86%) rename docs/docs/tutorials/{Generating stubs => generating_stubs}/using_buf.md (97%) create mode 100644 docs/docs/tutorials/generating_stubs/using_protoc.md create mode 100644 docs/docs/tutorials/introduction.md delete mode 100644 docs/docs/tutorials/prerequisites.md diff --git a/docs/docs/tutorials/Generating stubs/using_protoc.md b/docs/docs/tutorials/Generating stubs/using_protoc.md deleted file mode 100644 index 0f3d40b54c9..00000000000 --- a/docs/docs/tutorials/Generating stubs/using_protoc.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: default -title: Generating stubs using protoc -parent: Generating stubs -grand_parent: Tutorials -nav_order: 2 ---- - -## Generating stubs using protoc - -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 of what a `protoc` command might look like to generate Go stubs: - -```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 -``` diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index d8ce53001ad..86733169ef2 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -7,6 +7,61 @@ nav_order: 6 ## Adding the grpc-gateway annotations to an existing protobuf file +Now that we've got a working Go gRPC server, we need to add the grpc-gateway annotations: + +```proto +syntax = "proto3"; + +package helloworld; + +import "google/api/annotations.proto"; + +// The greeting service definition. +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; +} +``` + +### 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. + +Before we can do that, we need to copy some dependencies into our protofile structure. Copy the `third_party/googleapis` folder from the grpc-gateway repository to your local protofile structure. It should look like this afterwards: + +''' (backticks) +proto/ +helloworld/ +hello_world.proto +google/ +api/ +http.proto +annotations.proto +''' (backticks) + +#### Using buf + +[Using buf](generating_stubs/using_buf.md) + +#### Using protoc + +[Using protoc](generating_stubs/using_protoc.md) + Start the greeter_server service first, and then start the gateway. Then gateway connects to greeter_server and establishes http monitoring. Then we use curl to send http requests: diff --git a/docs/docs/tutorials/basic_arithmetic_grpc_server.md b/docs/docs/tutorials/basic_arithmetic_grpc_server.md deleted file mode 100644 index d3e32d8542c..00000000000 --- a/docs/docs/tutorials/basic_arithmetic_grpc_server.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -layout: default -title: Creating a Basic Arithmetic gRPC Server -parent: Tutorials -nav_order: 4 ---- - -## Creating a Basic Arithmetic gRPC Server - -Before we make `main.go` file first we have to make `server.go` file in a separate folder. - -At the top of the file, we define the handlers for our gRPC methods. - -Handlers are: - -```go -// This is the struct that we will implement all the handlers on -type Server struct { - a *pbExample.Request - b *pbExample.Request - Result *pbExample.Response -} - -// This is where you implement the handler for the Add method -func (s *Server) Add(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() - - result := a + b - - return &pbExample.Response{Result: result}, nil -} - -// This is where you implement the handler for the Divide method -func (s *Server) Divide(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() - - result := a / b - - return &pbExample.Response{Result: result}, nil -} - -// This is where you implement the handler for the Multiply method -func (s *Server) Multiply(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() - - result := a * b - - return &pbExample.Response{Result: result}, nil -} - -// This is where you implement the handler for the Subtract method -func (s *Server) Subtract(ctx context.Context, request *pbExample.Request) (*pbExample.Response, error) { - a, b := request.GetA(), request.GetB() - - result := a - b - - return &pbExample.Response{Result: result}, nil -} -``` - -For `main.go` file of Arithmetic server that will serve on a given port and listening at the endpoint, we defined in proto files we can refer to the boilerplate repository [grpc-gateway-boilerplate -Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). diff --git a/docs/docs/tutorials/basic_protos.md b/docs/docs/tutorials/basic_protos.md index a2e59d057d4..7e5f77f05c8 100644 --- a/docs/docs/tutorials/basic_protos.md +++ b/docs/docs/tutorials/basic_protos.md @@ -2,7 +2,7 @@ layout: default title: Creating a basic protos with HTTP annotations parent: Tutorials -nav_order: 3 +nav_order: 5 --- ## Creating a basic protos with HTTP annotations @@ -11,77 +11,25 @@ nav_order: 3 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 you will need to add `import "google/api/hello_world.proto";` to the gRPC proto file. +So you will need to add `import "google/api/http.proto";` to the gRPC proto file. -To make a Basic Arithmetic service first we have to define our services in proto files. +Now lets add the HTTP annotations to our proto file. ```proto -syntax="proto3"; +syntax = "proto3"; -package example; +package helloworld; -import "google/api/hello_world.proto"; -import "protoc-gen-openapiv2/options/hello_world.proto"; +import "google/api/annotations.proto"; -// Defines the import path that should be used to import the generated package, -// and the package name. -option go_package = "github.com/iamrajiv/Basic-Arithmetic-gRPC-Server/proto;example"; - -// These annotations are used when generating the OpenAPI file. -option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { - info: { - version: "1.0"; - }; - external_docs: { - url: "https://github.com/iamrajiv/Basic-Arithmetic-gRPC-Server"; - description: "Basic-Arithmetic-gRPC-Server"; - } - schemes: HTTPS; -}; - -// This will be our request -message Request { -// First integer in the body of the request - int64 a = 1; -// Second integer in the body of the request - int64 b = 2; -} - -// This will be our response -message Response { -// A integer in the body of the response - int64 result = 1; -} - -// Here is the overall service where we define all our endpoints -service ArithmeticService { -// Here is our Add method to use as an service - rpc Add(Request) returns (Response){ - option (google.api.http) = { - post: "/api/v1/arithmetic/add" - body: "*" - }; - }; - // Here is our Divide method to use as an service - rpc Divide(Request) returns (Response){ - option (google.api.http) = { - post: "/api/v1/arithmetic/div" - body: "*" - }; - }; - // Here is our Multiply method to use as an service - rpc Multiply(Request) returns (Response){ - option (google.api.http) = { - post: "/api/v1/arithmetic/mul" - body: "*" +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) { + option (google.api.http) = { + post: "/v1/example/echo" + body: "*" }; - }; -// Here is our Subtract method to use as an service - rpc Subtract(Request) returns (Response){ - option (google.api.http) = { - post: "/api/v1/arithmetic/sub" - body: "*" - }; - }; + } } ``` diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md new file mode 100644 index 00000000000..f140f7eb5dd --- /dev/null +++ b/docs/docs/tutorials/creating_main.go.md @@ -0,0 +1,10 @@ +--- +layout: default +title: Creating main.go +parent: Tutorials +nav_order: 4 +--- + +## Creating main.go + +For `main.go` file of hello world we can refer to the boilerplate repository [grpc-gateway-boilerplate Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). diff --git a/docs/docs/tutorials/Generating stubs/index.md b/docs/docs/tutorials/generating_stubs/index.md similarity index 86% rename from docs/docs/tutorials/Generating stubs/index.md rename to docs/docs/tutorials/generating_stubs/index.md index 1f927046d68..16b017c2a3c 100644 --- a/docs/docs/tutorials/Generating stubs/index.md +++ b/docs/docs/tutorials/generating_stubs/index.md @@ -2,6 +2,6 @@ layout: default title: Generating stubs parent: Tutorials -nav_order: 2 +nav_order: 3 has_children: true --- diff --git a/docs/docs/tutorials/Generating stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md similarity index 97% rename from docs/docs/tutorials/Generating stubs/using_buf.md rename to docs/docs/tutorials/generating_stubs/using_buf.md index f2cacffecfd..ea80739dc52 100644 --- a/docs/docs/tutorials/Generating stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -21,8 +21,6 @@ version: v1beta1 build: roots: - proto - - third_party/grpc-gateway - - third_party/googleapis ``` To generate type and gRPC stubs for Go, create the file `buf.gen.yaml` at the root of the repository: diff --git a/docs/docs/tutorials/generating_stubs/using_protoc.md b/docs/docs/tutorials/generating_stubs/using_protoc.md new file mode 100644 index 00000000000..ed9055271c0 --- /dev/null +++ b/docs/docs/tutorials/generating_stubs/using_protoc.md @@ -0,0 +1,26 @@ +--- +layout: default +title: Generating stubs using protoc +parent: Generating stubs +grand_parent: Tutorials +nav_order: 2 +--- + +## Generating stubs using protoc + +Generate Go type and gRPC stubs: + +This step generates the Go types and gRPC stubs that you can use to implement the service and consume from clients. + +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 +''' (backticks) +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 each protobuf package in our `proto` file hierarchy. +``` diff --git a/docs/docs/tutorials/introduction.md b/docs/docs/tutorials/introduction.md new file mode 100644 index 00000000000..16a4eafda5c --- /dev/null +++ b/docs/docs/tutorials/introduction.md @@ -0,0 +1,45 @@ +--- +layout: default +title: Introduction +parent: Tutorials +nav_order: 1 +--- + +## Introduction + +We all know that gRPC is not a tool for everything. There are cases where we still want to provide a traditional RESTful JSON API. The reasons can range from maintaining backwards-compatibility to supporting programming languages or clients not well supported by gRPC. But coding another API for REST is quite a time consuming and tedious. + +So is there any way to code just once, but can provide APIs in both gRPC and REST 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 RESTful style at the same time. + +![architecture introduction diagram](https://docs.google.com/drawings/d/12hp4CPqrNPFhattL_cIoJptFvlAqm5wLQ0ggqI5mkCg/pub?w=749&h=370) + +## Prerequisites + +One way to achieve that is to use gRPC gateway. gRPC gateway is a plugin of the protocol buffer compiler. It reads the protobuf service definitions and generates a proxy server, which translates a RESTful HTTP call into gRPC request. + +All we need to do is a small amount of configuration +in the service. Before 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 get` to download the following packages: + +```sh +go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway +go get google.golang.org/protobuf/cmd/protoc-gen-go +go get google.golang.org/grpc/cmd/protoc-gen-go-grpc +``` + +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`. diff --git a/docs/docs/tutorials/prerequisites.md b/docs/docs/tutorials/prerequisites.md deleted file mode 100644 index 984580d8ae2..00000000000 --- a/docs/docs/tutorials/prerequisites.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -layout: default -title: Prerequisites -parent: Tutorials -nav_order: 1 ---- - -## Prerequisites - -One way to achieve that is to use gRPC gateway. gRPC gateway is a plugin of the protocol buffer compiler. It reads the protobuf service definitions and generates a proxy server, which translates a RESTful HTTP call into gRPC request. - -All we need to do is a small amount of configuration -in the service. Before 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 get` to download the following packages: - -```sh -go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway -go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 -go get google.golang.org/protobuf/cmd/protoc-gen-go -go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger -go get -u github.com/golang/protobuf/protoc-gen-go -``` - -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`. diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index ecffed41f28..0133ea325ff 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -1,42 +1,21 @@ --- layout: default -title: Creating a simple hello world with gRPC-Gateway +title: Creating a simple hello world with gRPC parent: Tutorials -nav_order: 5 +nav_order: 2 --- -### Creating a simple hello world with gRPC-Gateway +### Creating a simple hello world with gRPC -### gRPC-Gateway +### Define your gRPC service using protocol buffers -We all know that gRPC is not a tool for everything. There are cases where we still want to provide a traditional RESTful JSON API. The reasons can range from maintaining backwards-compatibility to supporting programming languages or clients not well supported by gRPC. But coding another API for REST is quite a time consuming and tedious. - -So is there any way to code just once, but can provide APIs in both gRPC and REST at the same time? - -The answer is Yes. - -### Define and Generate proto files - -Before we create a gRPC service, we should create a proto file to define what we need, here we create a file named `hello.proto` to show. +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`. ```proto syntax = "proto3"; package helloworld; -import "google/api/annotations.proto"; - -// The greeting service definition. -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; @@ -47,32 +26,3 @@ message HelloReply { string message = 1; } ``` - -Then we should generate gRPC stub via protoc - -```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/hello_world.proto -``` - -The `helloworld.pb.go` file will be generated. So `helloworld.pb.go` is required by the server service. - -Next we need to use protoc to generate the go files needed by the gateway. - -```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:. \ -helloworld/helloworld.proto -``` - -The `helloworld.pb.gw.go` file will be generated. This file is the protocol file used by gateway for protocol conversion between grpc and http. - -After the protocol file is processed, the gateway code is needed. - -### Implementation - -For `main.go` file of hello world we can refer to the boilerplate repository [grpc-gateway-boilerplate -Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). From 99c437191fb7168ad6a49672a9042730954771f8 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Tue, 24 Nov 2020 10:50:51 +0530 Subject: [PATCH 05/19] updated tutorials directory on grpc-gateway --- docs/docs/tutorials/adding_annotations.md | 67 +++++++++++++++---- docs/docs/tutorials/basic_protos.md | 35 ---------- docs/docs/tutorials/creating_main.go.md | 66 +++++++++++++++++- .../generating_stubs/using_protoc.md | 4 +- docs/docs/tutorials/introduction.md | 17 ++--- docs/docs/tutorials/learn_more.md | 2 +- docs/docs/tutorials/simple_hello_world.md | 33 ++++++++- 7 files changed, 157 insertions(+), 67 deletions(-) delete mode 100644 docs/docs/tutorials/basic_protos.md diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 86733169ef2..42591d194b7 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -2,7 +2,7 @@ layout: default title: Adding the grpc-gateway annotations to an existing protobuf file parent: Tutorials -nav_order: 6 +nav_order: 5 --- ## Adding the grpc-gateway annotations to an existing protobuf file @@ -16,13 +16,13 @@ package helloworld; import "google/api/annotations.proto"; -// The greeting service definition. +// 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: "*" + option (google.api.http) = { + post: "/v1/example/echo" + body: "*" }; } } @@ -38,13 +38,15 @@ message HelloReply { } ``` +Also, See [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/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. + ### 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. Before we can do that, we need to copy some dependencies into our protofile structure. Copy the `third_party/googleapis` folder from the grpc-gateway repository to your local protofile structure. It should look like this afterwards: -''' (backticks) +``` proto/ helloworld/ hello_world.proto @@ -52,30 +54,69 @@ google/ api/ http.proto annotations.proto -''' (backticks) +``` #### Using buf -[Using buf](generating_stubs/using_buf.md) +We'll need to add the grpc-gateway generator to the generation configuration: + +```yml +plugins: + - name: go + out: proto + opt: paths=source_relative + - name: go-grpc + out: proto + opt: paths=source_relative + - name: grpc-gateway + out: proto + opt: paths=source_relative +``` + +And that's it! Now if you run: + +```sh +buf generate +``` + +It should produce a `*.gw.pb.go` file. #### Using protoc -[Using protoc](generating_stubs/using_protoc.md) +Now we need to add the grpc-gateway generator to the protoc invocation: + +``` +protoc -I ./proto \ + ... other plugins ... +--grpc-gateway_out ./proto --grpc-gateway_opt paths=source_relative +./proto/helloworld/hello_world.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 + --grpc-gateway_out ./proto --grpc-gateway_opt paths=source_relative + ./proto/helloworld/hello_world.proto +``` + +This should generate a `*.gw.pb.go` file. -Start the greeter_server service first, and then start the gateway. Then gateway connects to greeter_server and establishes http monitoring. +### Testing the grpc-gateway Then we use curl to send http requests: ```sh -curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " world"} +curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " Hello"}' ``` ``` -{"message":"Hello world"} +{"message":"Hello World"} ``` The process is as follows: -curl sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and json returns to the front end. +`curl` sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and json returns to the front end. In this way, the transformation process from http json to internal grpc is completed through grpc-gateway. diff --git a/docs/docs/tutorials/basic_protos.md b/docs/docs/tutorials/basic_protos.md deleted file mode 100644 index 7e5f77f05c8..00000000000 --- a/docs/docs/tutorials/basic_protos.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -layout: default -title: Creating a basic protos with HTTP annotations -parent: Tutorials -nav_order: 5 ---- - -## Creating a basic protos with HTTP annotations - -### Annotating your gRPC .proto file with HTTP bindings and routes - -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 you will need to add `import "google/api/http.proto";` to the gRPC proto file. - -Now lets add the HTTP annotations to our proto file. - -```proto -syntax = "proto3"; - -package helloworld; - -import "google/api/annotations.proto"; - -// The greeting service definition. -service Greeter { - // Sends a greeting - rpc SayHello (HelloRequest) returns (HelloReply) { - option (google.api.http) = { - post: "/v1/example/echo" - body: "*" - }; - } -} -``` diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index f140f7eb5dd..84bb18b5307 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -7,4 +7,68 @@ nav_order: 4 ## Creating main.go -For `main.go` file of hello world we can refer to the boilerplate repository [grpc-gateway-boilerplate Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). +```go +package main + +import ( + "context" + "io/ioutil" + "log" + "net" + "os" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + "google.golang.org/grpc/grpclog" + + // Static files + + "github.com/hello/hello_world\gateway" + "github.com/hello/hello_world\insecure" + hello "github.com/hello/hello_world\proto" +) + +type server struct{} + +func NewServer() *server { + return &server{} +} + +func (s *server) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) { + + log.Println("request: ", in.Name) + return &hello.HelloReply{Message: in.Name + " World"}, nil +} + +func main() { + + // Adds gRPC internal logs. This is quite verbose, so adjust as desired! + log := grpclog.NewLoggerV2(os.Stdout, ioutil.Discard, ioutil.Discard) + grpclog.SetLoggerV2(log) + + addr := "0.0.0.0:10000" + lis, err := net.Listen("tcp", addr) + if err != nil { + log.Fatalln("Failed to listen:", err) + } + + s := grpc.NewServer( + // TODO: Replace with your own certificate! + grpc.Creds(credentials.NewServerTLSFromCert(&insecure.Cert)), + ) + hello.RegisterGreeterServer(s, &server{}) + + // Serve gRPC Server + log.Info("Serving gRPC on https://", addr) + go func() { + log.Fatal(s.Serve(lis)) + }() + + err = gateway.Run("dns:///" + addr) + log.Fatalln(err) +} +``` + +### Read More + +For more refer to this boilerplate repository [grpc-gateway-boilerplate Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). diff --git a/docs/docs/tutorials/generating_stubs/using_protoc.md b/docs/docs/tutorials/generating_stubs/using_protoc.md index ed9055271c0..eec75e60c98 100644 --- a/docs/docs/tutorials/generating_stubs/using_protoc.md +++ b/docs/docs/tutorials/generating_stubs/using_protoc.md @@ -19,8 +19,8 @@ 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 -''' (backticks) +``` + 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 each protobuf package in our `proto` file hierarchy. -``` diff --git a/docs/docs/tutorials/introduction.md b/docs/docs/tutorials/introduction.md index 16a4eafda5c..57bf7f32767 100644 --- a/docs/docs/tutorials/introduction.md +++ b/docs/docs/tutorials/introduction.md @@ -1,6 +1,6 @@ --- layout: default -title: Introduction +title: Introduction about gRPC-Gateway parent: Tutorials nav_order: 1 --- @@ -13,24 +13,15 @@ So is there any way to code just once, but can provide APIs in both gRPC and RES 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. +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. ![architecture introduction diagram](https://docs.google.com/drawings/d/12hp4CPqrNPFhattL_cIoJptFvlAqm5wLQ0ggqI5mkCg/pub?w=749&h=370) -## Prerequisites +### Prerequisites -One way to achieve that is to use gRPC gateway. gRPC gateway is a plugin of the protocol buffer compiler. It reads the protobuf service definitions and generates a proxy server, which translates a RESTful HTTP call into gRPC request. - -All we need to do is a small amount of configuration -in the service. Before start coding, we have to install some -tools. +Before start coding, we have to install some tools and need to do small amount of configuration in the service. 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/). diff --git a/docs/docs/tutorials/learn_more.md b/docs/docs/tutorials/learn_more.md index 332f018e316..fb749897837 100644 --- a/docs/docs/tutorials/learn_more.md +++ b/docs/docs/tutorials/learn_more.md @@ -2,7 +2,7 @@ layout: default title: Learn More parent: Tutorials -nav_order: 7 +nav_order: 6 --- ## Learn More diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 0133ea325ff..3a0508356c2 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -5,9 +5,38 @@ parent: Tutorials nav_order: 2 --- -### Creating a simple hello world with gRPC +## Creating a simple hello world with gRPC -### Define your gRPC service using protocol buffers +To understand gRPC-Gateway we are going to make hello world gRPC service which uses gRPC-Gateway. + +### Creating a basic protos with HTTP 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 you will need to add `import "google/api/http.proto";` to the gRPC proto file. + +Now, let's add the HTTP annotations to our proto file. + +```proto +syntax = "proto3"; + +package helloworld; + +import "google/api/annotations.proto"; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) { + option (google.api.http) = { + post: "/v1/example/echo" + body: "*" + }; + } +} +``` + +### 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`. From fa4d26430996c130191cc64365d47c4f5f74b766 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Tue, 24 Nov 2020 10:53:03 +0530 Subject: [PATCH 06/19] updated tutorials directory on grpc-gateway --- docs/docs/tutorials/creating_main.go.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index 84bb18b5307..39289bb2f4f 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -23,9 +23,9 @@ import ( // Static files - "github.com/hello/hello_world\gateway" - "github.com/hello/hello_world\insecure" - hello "github.com/hello/hello_world\proto" + "github.com/hello/hello_world/gateway" + "github.com/hello/hello_world/insecure" + hello "github.com/hello/hello_world/proto" ) type server struct{} From 6b545a8992372a957b24d0767c69f5da480d8fd9 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Wed, 25 Nov 2020 18:10:40 +0530 Subject: [PATCH 07/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 49 ++++++++++--------- docs/docs/tutorials/creating_main.go.md | 42 +++++----------- .../generating_stubs/using_protoc.md | 4 -- docs/docs/tutorials/introduction.md | 2 +- docs/docs/tutorials/learn_more.md | 20 -------- docs/docs/tutorials/simple_hello_world.md | 29 +---------- 6 files changed, 39 insertions(+), 107 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 42591d194b7..8659f50f60d 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -7,7 +7,11 @@ nav_order: 5 ## Adding the grpc-gateway annotations to an existing protobuf file -Now that we've got a working Go gRPC server, we need to add the grpc-gateway annotations: +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 you will need to add `import "google/api/http.proto";` to the gRPC proto file. ```proto syntax = "proto3"; @@ -47,13 +51,13 @@ Now that we've got the grpc-gateway annotations added to the proto file, we need Before we can do that, we need to copy some dependencies into our protofile structure. Copy the `third_party/googleapis` folder from the grpc-gateway repository to your local protofile structure. It should look like this afterwards: ``` -proto/ -helloworld/ -hello_world.proto -google/ -api/ -http.proto -annotations.proto +proto +├── google +│ └── api +│ ├── annotations.proto +│ └── http.proto +└── helloworld + └── hello_world.proto ``` #### Using buf @@ -85,27 +89,24 @@ It should produce a `*.gw.pb.go` file. Now we need to add the grpc-gateway generator to the protoc invocation: -``` -protoc -I ./proto \ - ... other plugins ... ---grpc-gateway_out ./proto --grpc-gateway_opt paths=source_relative -./proto/helloworld/hello_world.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 - --grpc-gateway_out ./proto --grpc-gateway_opt paths=source_relative - ./proto/helloworld/hello_world.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. -### Testing the grpc-gateway +Usage examples can be found on this [Usage](https://github.com/grpc-ecosystem/grpc-gateway#usage) + +For more refer to this boilerplate repository [grpc-gateway-boilerplate +](https://github.com/johanbrandhorst/grpc-gateway-boilerplate) + +### Testing the gRPC-Gateway -Then we use curl to send http requests: +Then we use curl to send HTTP requests: ```sh curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " Hello"}' @@ -117,6 +118,6 @@ curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " Hello"}' The process is as follows: -`curl` sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and json returns to the front end. +`curl` sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and JSON returns to the front end. -In this way, the transformation process from http json to internal grpc is completed through grpc-gateway. +In this way, the transformation process from HTTP JSON to internal grpc is completed through gRPC-Gateway. diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index 39289bb2f4f..85137b67343 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -7,25 +7,21 @@ nav_order: 4 ## 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`. Then 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" "io/ioutil" - "log" "net" "os" "google.golang.org/grpc" - "google.golang.org/grpc/credentials" "google.golang.org/grpc/grpclog" - // Static files - - "github.com/hello/hello_world/gateway" - "github.com/hello/hello_world/insecure" - hello "github.com/hello/hello_world/proto" + helloworldpb "github.com/myuser/myrepo/proto/helloworld/" ) type server struct{} @@ -34,41 +30,27 @@ func NewServer() *server { return &server{} } -func (s *server) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloReply, error) { +func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) { - log.Println("request: ", in.Name) - return &hello.HelloReply{Message: in.Name + " World"}, nil + return &helloworldpb.HelloReply{Message: in.Name + " World"}, nil } func main() { - - // Adds gRPC internal logs. This is quite verbose, so adjust as desired! log := grpclog.NewLoggerV2(os.Stdout, ioutil.Discard, ioutil.Discard) grpclog.SetLoggerV2(log) - - addr := "0.0.0.0:10000" - lis, err := net.Listen("tcp", addr) + lis, err := net.Listen("tcp", ":8080") if err != nil { log.Fatalln("Failed to listen:", err) } - - s := grpc.NewServer( - // TODO: Replace with your own certificate! - grpc.Creds(credentials.NewServerTLSFromCert(&insecure.Cert)), - ) - hello.RegisterGreeterServer(s, &server{}) - + s := grpc.NewServer() + helloworldpb.RegisterGreeterServer(s, &server{}) // Serve gRPC Server - log.Info("Serving gRPC on https://", addr) - go func() { - log.Fatal(s.Serve(lis)) - }() - - err = gateway.Run("dns:///" + addr) - log.Fatalln(err) + log.Info("Serving gRPC on 0.0.0.0:8080") + log.Fatal(s.Serve(lis)) } + ``` ### Read More -For more refer to this boilerplate repository [grpc-gateway-boilerplate Template](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). +For more refer to gRPC docs [https://grpc.io/docs/languages/go/](https://grpc.io/docs/languages/go/). diff --git a/docs/docs/tutorials/generating_stubs/using_protoc.md b/docs/docs/tutorials/generating_stubs/using_protoc.md index eec75e60c98..b7f8dd94417 100644 --- a/docs/docs/tutorials/generating_stubs/using_protoc.md +++ b/docs/docs/tutorials/generating_stubs/using_protoc.md @@ -8,10 +8,6 @@ nav_order: 2 ## Generating stubs using protoc -Generate Go type and gRPC stubs: - -This step generates the Go types and gRPC stubs that you can use to implement the service and consume from clients. - 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 diff --git a/docs/docs/tutorials/introduction.md b/docs/docs/tutorials/introduction.md index 57bf7f32767..7b113a33f41 100644 --- a/docs/docs/tutorials/introduction.md +++ b/docs/docs/tutorials/introduction.md @@ -21,7 +21,7 @@ This helps you provide your APIs in both gRPC and RESTful style at the same time ### Prerequisites -Before start coding, we have to install some tools and need to do small amount of configuration in the service. +Before we start coding, we have to install some tools and need to do a small amount of configuration in the service. 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/). diff --git a/docs/docs/tutorials/learn_more.md b/docs/docs/tutorials/learn_more.md index fb749897837..eb7959dc138 100644 --- a/docs/docs/tutorials/learn_more.md +++ b/docs/docs/tutorials/learn_more.md @@ -17,24 +17,4 @@ HttpRule defines the gRPC / REST mapping scheme. The mapping defines how differe Each mapping defines a URL path template and an HTTP method. A path template can refer to one or more fields in a gRPC request message if each field is a non-repeating field with a primitive type. The path template controls how the request message fields are mapped to the URL path. -```proto -import "google/api/annotations.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/timestamp.proto"; -message StatusResponse { - google.protobuf.Timestamp current_time = 1; -} -service MyService { - rpc Status(google.protobuf.Empty) - returns (StatusResponse) { - option (google.api.http) = { - get: "/status" - }; - } - } -} -``` - -You will need to provide the necessary third-party `protobuf` files to the `protoc` compiler. They have included in the `grpc-gateway` repository in the `[third_party/googleapis](https://github.com/grpc-ecosystem/grpc-gateway/tree/master/third_party/googleapis)` folder, and we recommend copying them to the project file structure. - Read more about HTTP and gRPC Transcoding on https://google.aip.dev/127. diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 3a0508356c2..9704a514e50 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -7,34 +7,7 @@ nav_order: 2 ## Creating a simple hello world with gRPC -To understand gRPC-Gateway we are going to make hello world gRPC service which uses gRPC-Gateway. - -### Creating a basic protos with HTTP 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 you will need to add `import "google/api/http.proto";` to the gRPC proto file. - -Now, let's add the HTTP annotations to our proto file. - -```proto -syntax = "proto3"; - -package helloworld; - -import "google/api/annotations.proto"; - -// The greeting service definition. -service Greeter { - // Sends a greeting - rpc SayHello (HelloRequest) returns (HelloReply) { - option (google.api.http) = { - post: "/v1/example/echo" - body: "*" - }; - } -} -``` +To understand the gRPC-Gateway we are going to first make a hello world gRPC service. ### Defining your gRPC service using protocol buffers From 738ebf9d0561e987e04661bd8925578fffd2f8c5 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Fri, 27 Nov 2020 22:52:38 +0530 Subject: [PATCH 08/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 4 +++- docs/docs/tutorials/creating_main.go.md | 5 +---- docs/docs/tutorials/generating_stubs/using_protoc.md | 2 +- docs/docs/tutorials/learn_more.md | 10 +++------- docs/docs/tutorials/simple_hello_world.md | 8 +++++++- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 8659f50f60d..92663c10ddc 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -31,7 +31,7 @@ service Greeter { } } -// The request message containing the user's name. +// The request message containing the user's name message HelloRequest { string name = 1; } @@ -42,6 +42,8 @@ message HelloReply { } ``` +HttpRule is typically specified as an `google.api.http` annotation on the gRPC method. Each mapping specifies a URL path template and an HTTP method. + Also, See [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/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. ### Generating the grpc-gateway stubs diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index 85137b67343..d3c8b82994b 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -21,7 +21,7 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/grpclog" - helloworldpb "github.com/myuser/myrepo/proto/helloworld/" + helloworldpb "github.com/myuser/myrepo/proto/helloworld" ) type server struct{} @@ -31,13 +31,10 @@ func NewServer() *server { } func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) { - return &helloworldpb.HelloReply{Message: in.Name + " World"}, nil } func main() { - log := grpclog.NewLoggerV2(os.Stdout, ioutil.Discard, ioutil.Discard) - grpclog.SetLoggerV2(log) lis, err := net.Listen("tcp", ":8080") if err != nil { log.Fatalln("Failed to listen:", err) diff --git a/docs/docs/tutorials/generating_stubs/using_protoc.md b/docs/docs/tutorials/generating_stubs/using_protoc.md index b7f8dd94417..491c9369ea0 100644 --- a/docs/docs/tutorials/generating_stubs/using_protoc.md +++ b/docs/docs/tutorials/generating_stubs/using_protoc.md @@ -19,4 +19,4 @@ protoc -I ./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 each protobuf package in our `proto` file hierarchy. +This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for `proto/helloworld/hello_world.proto`. diff --git a/docs/docs/tutorials/learn_more.md b/docs/docs/tutorials/learn_more.md index eb7959dc138..b9c26cb35aa 100644 --- a/docs/docs/tutorials/learn_more.md +++ b/docs/docs/tutorials/learn_more.md @@ -9,12 +9,8 @@ nav_order: 6 #### google.api.http -GRPC transcoding is a conversion function between the gRPC method and one or more HTTP REST endpoints. This allows developers to create a single API service that supports both the gRPC API and the REST API. Many systems, including the API Google, Cloud Endpoints, gRPC Gateway, and the Envoy proxy server support this feature and use it for large-scale production services. +Read more about `google.api.http` on [https://github.com/googleapis/googleapis/blob/master/google/api/http.proto](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto) -The grcp-gateway the server is created according to the `google.api.http` annotations in your service definitions. +#### HTTP and gRPC Transcoding -HttpRule defines the gRPC / REST mapping scheme. The mapping defines how different parts of a gRPC request message are mapped to the URL path, URL request parameters, and HTTP request body. It also controls how the gRPC response message is displayed in the HTTP response body. HttpRule is usually specified as a `google.api.http` annotation in the gRPC method. - -Each mapping defines a URL path template and an HTTP method. A path template can refer to one or more fields in a gRPC request message if each field is a non-repeating field with a primitive type. The path template controls how the request message fields are mapped to the URL path. - -Read more about HTTP and gRPC Transcoding on https://google.aip.dev/127. +Read more about HTTP and gRPC Transcoding on [https://google.aip.dev/127](https://google.aip.dev/127) diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 9704a514e50..74ebb5e6f57 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -18,7 +18,13 @@ syntax = "proto3"; package helloworld; -// The request message containing the user's name. +// 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; } From 9ecaff0c55c9a24234350fde2792def8e60a4b19 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sat, 28 Nov 2020 01:19:16 +0530 Subject: [PATCH 09/19] updated tutorials --- docs/docs/tutorials/creating_main.go.md | 1 - docs/docs/tutorials/generating_stubs/using_buf.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index d3c8b82994b..07f9341425a 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -45,7 +45,6 @@ func main() { log.Info("Serving gRPC on 0.0.0.0:8080") log.Fatal(s.Serve(lis)) } - ``` ### Read More diff --git a/docs/docs/tutorials/generating_stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md index ea80739dc52..789e5f3eefe 100644 --- a/docs/docs/tutorials/generating_stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -26,6 +26,7 @@ build: To generate type and gRPC stubs for Go, create the file `buf.gen.yaml` at the root of the repository: ```yml +version: v1beta1 plugins: - name: go out: proto From ccd3c4e246ce71ccede2801c100b2e31862b1ef4 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sat, 28 Nov 2020 04:45:35 +0530 Subject: [PATCH 10/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 3 ++- docs/docs/tutorials/generating_stubs/using_buf.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 92663c10ddc..a9f5a217180 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -67,13 +67,14 @@ proto We'll need to add the grpc-gateway generator to the generation configuration: ```yml +version: v1beta1 plugins: - name: go out: proto opt: paths=source_relative - name: go-grpc out: proto - opt: paths=source_relative + opt: paths=source_relative,require_unimplemented_servers=false - name: grpc-gateway out: proto opt: paths=source_relative diff --git a/docs/docs/tutorials/generating_stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md index 789e5f3eefe..5d0e201f832 100644 --- a/docs/docs/tutorials/generating_stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -8,7 +8,7 @@ nav_order: 1 ## 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://github.com/bufbuild/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 repository. 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. From d873ebe206af386ce61e8de36f65424eca128a02 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sat, 28 Nov 2020 20:54:34 +0530 Subject: [PATCH 11/19] updated headings and added next button for tutorials --- docs/docs/tutorials/adding_annotations.md | 12 ++++++----- docs/docs/tutorials/creating_main.go.md | 6 ++++-- .../tutorials/generating_stubs/using_buf.md | 4 +++- .../generating_stubs/using_protoc.md | 4 +++- docs/docs/tutorials/introduction.md | 21 ++++++++++++------- docs/docs/tutorials/learn_more.md | 6 +++--- docs/docs/tutorials/simple_hello_world.md | 6 ++++-- 7 files changed, 38 insertions(+), 21 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index a9f5a217180..2152fa3a382 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -5,7 +5,7 @@ parent: Tutorials nav_order: 5 --- -## Adding the grpc-gateway annotations to an existing protobuf file +# Adding the grpc-gateway annotations to an existing protobuf file Now that we've got a working Go gRPC server, we need to add the grpc-gateway annotations. @@ -46,7 +46,7 @@ HttpRule is typically specified as an `google.api.http` annotation on the gRPC m Also, See [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/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. -### Generating the grpc-gateway stubs +## 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. @@ -62,7 +62,7 @@ proto └── hello_world.proto ``` -#### Using buf +### Using buf We'll need to add the grpc-gateway generator to the generation configuration: @@ -88,7 +88,7 @@ buf generate It should produce a `*.gw.pb.go` file. -#### Using protoc +### Using protoc Now we need to add the grpc-gateway generator to the protoc invocation: @@ -107,7 +107,7 @@ Usage examples can be found on this [Usage](https://github.com/grpc-ecosystem/gr For more refer to this boilerplate repository [grpc-gateway-boilerplate ](https://github.com/johanbrandhorst/grpc-gateway-boilerplate) -### Testing the gRPC-Gateway +## Testing the gRPC-Gateway Then we use curl to send HTTP requests: @@ -124,3 +124,5 @@ The process is as follows: `curl` sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and JSON returns to the front end. In this way, the transformation process from HTTP JSON to internal grpc is completed through gRPC-Gateway. + +[Next Tutorial](learn_more.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index 07f9341425a..c083625b4da 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -5,7 +5,7 @@ parent: Tutorials nav_order: 4 --- -## Creating main.go +# 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`. Then import here is using the path to the generated files in `proto/helloworld` relative to the root of the repository. @@ -47,6 +47,8 @@ func main() { } ``` -### Read More +## Read More For more refer to gRPC docs [https://grpc.io/docs/languages/go/](https://grpc.io/docs/languages/go/). + +[Next Tutorial](adding_annotations.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/generating_stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md index 5d0e201f832..63247f86ca1 100644 --- a/docs/docs/tutorials/generating_stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -6,7 +6,7 @@ grand_parent: Tutorials nav_order: 1 --- -## Generating stubs using buf +# 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/)]. @@ -45,3 +45,5 @@ 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 Tutorial](using_protoc.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/generating_stubs/using_protoc.md b/docs/docs/tutorials/generating_stubs/using_protoc.md index 491c9369ea0..517c3f5c954 100644 --- a/docs/docs/tutorials/generating_stubs/using_protoc.md +++ b/docs/docs/tutorials/generating_stubs/using_protoc.md @@ -6,7 +6,7 @@ grand_parent: Tutorials nav_order: 2 --- -## Generating stubs using protoc +# 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`: @@ -20,3 +20,5 @@ protoc -I ./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 Tutorial](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/introduction.md b/docs/docs/tutorials/introduction.md index 7b113a33f41..52d3b52d72d 100644 --- a/docs/docs/tutorials/introduction.md +++ b/docs/docs/tutorials/introduction.md @@ -1,27 +1,27 @@ --- layout: default -title: Introduction about gRPC-Gateway +title: Introduction to the gRPC-Gateway parent: Tutorials nav_order: 1 --- -## Introduction +# 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 RESTful JSON API. The reasons can range from maintaining backwards-compatibility to supporting programming languages or clients not well supported by gRPC. But coding another API for REST is quite a time consuming and tedious. +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 can provide APIs in both gRPC and REST at the same time? +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 RESTful style at the same time. +This helps you provide your APIs in both gRPC and HTTP/JSON format at the same time. ![architecture introduction diagram](https://docs.google.com/drawings/d/12hp4CPqrNPFhattL_cIoJptFvlAqm5wLQ0ggqI5mkCg/pub?w=749&h=370) -### Prerequisites +## Prerequisites -Before we start coding, we have to install some tools and need to do a small amount of configuration in the service. +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/). @@ -34,3 +34,10 @@ go get google.golang.org/grpc/cmd/protoc-gen-go-grpc ``` 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: + +```sh +go mod init github.com/myuser/myrepo +``` + +[Next Tutorial](simple_hello_world.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/learn_more.md b/docs/docs/tutorials/learn_more.md index b9c26cb35aa..de6b03674b3 100644 --- a/docs/docs/tutorials/learn_more.md +++ b/docs/docs/tutorials/learn_more.md @@ -5,12 +5,12 @@ parent: Tutorials nav_order: 6 --- -## Learn More +# Learn More -#### google.api.http +## google.api.http Read more about `google.api.http` on [https://github.com/googleapis/googleapis/blob/master/google/api/http.proto](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto) -#### HTTP and gRPC Transcoding +## HTTP and gRPC Transcoding Read more about HTTP and gRPC Transcoding on [https://google.aip.dev/127](https://google.aip.dev/127) diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 74ebb5e6f57..801871b24d6 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -5,11 +5,11 @@ parent: Tutorials nav_order: 2 --- -## Creating a simple hello world with gRPC +# 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 +## 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`. @@ -34,3 +34,5 @@ message HelloReply { string message = 1; } ``` + +[Next Tutorial](generating_stubs/index.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } From 1e1558aaecf2a28da170cb1154754928561229d6 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sat, 28 Nov 2020 21:37:49 +0530 Subject: [PATCH 12/19] updated next buttons --- docs/docs/tutorials/adding_annotations.md | 2 +- docs/docs/tutorials/creating_main.go.md | 2 +- docs/docs/tutorials/generating_stubs/using_buf.md | 2 +- docs/docs/tutorials/generating_stubs/using_protoc.md | 2 +- docs/docs/tutorials/introduction.md | 2 +- docs/docs/tutorials/simple_hello_world.md | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 2152fa3a382..3b96a07c320 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -125,4 +125,4 @@ The process is as follows: In this way, the transformation process from HTTP JSON to internal grpc is completed through gRPC-Gateway. -[Next Tutorial](learn_more.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[Next](learn_more.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index c083625b4da..dc182a96eec 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -51,4 +51,4 @@ func main() { For more refer to gRPC docs [https://grpc.io/docs/languages/go/](https://grpc.io/docs/languages/go/). -[Next Tutorial](adding_annotations.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[Next](adding_annotations.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/generating_stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md index 63247f86ca1..3bb183ed76b 100644 --- a/docs/docs/tutorials/generating_stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -46,4 +46,4 @@ 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 Tutorial](using_protoc.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[Next](using_protoc.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/generating_stubs/using_protoc.md b/docs/docs/tutorials/generating_stubs/using_protoc.md index 517c3f5c954..f06f94c4fde 100644 --- a/docs/docs/tutorials/generating_stubs/using_protoc.md +++ b/docs/docs/tutorials/generating_stubs/using_protoc.md @@ -21,4 +21,4 @@ We use the `go` and `go-grpc` plugins to generate Go types and gRPC service defi This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for `proto/helloworld/hello_world.proto`. -[Next Tutorial](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[Next](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/introduction.md b/docs/docs/tutorials/introduction.md index 52d3b52d72d..27f10843bfc 100644 --- a/docs/docs/tutorials/introduction.md +++ b/docs/docs/tutorials/introduction.md @@ -40,4 +40,4 @@ We will be working in a new module for this tutorial, so go ahead and create tha go mod init github.com/myuser/myrepo ``` -[Next Tutorial](simple_hello_world.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[Next](simple_hello_world.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 801871b24d6..2f3d18f3a8a 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -35,4 +35,4 @@ message HelloReply { } ``` -[Next Tutorial](generating_stubs/index.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[Next](generating_stubs/index.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } From 7005e3ae6adc250647b064bf4e634faf199fc30c Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sun, 29 Nov 2020 12:11:31 +0530 Subject: [PATCH 13/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 6 +++--- docs/docs/tutorials/creating_main.go.md | 2 +- .../tutorials/generating_stubs/using_buf.md | 2 +- .../tutorials/generating_stubs/using_protoc.md | 2 +- docs/docs/tutorials/introduction.md | 17 +++++++++++++---- docs/docs/tutorials/simple_hello_world.md | 2 ++ 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 3b96a07c320..212c9ccf023 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -83,7 +83,7 @@ plugins: And that's it! Now if you run: ```sh -buf generate +$ buf generate ``` It should produce a `*.gw.pb.go` file. @@ -93,7 +93,7 @@ It should produce a `*.gw.pb.go` file. Now we need to add the grpc-gateway generator to the protoc invocation: ```sh -protoc -I ./proto \ +$ 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 \ @@ -112,7 +112,7 @@ For more refer to this boilerplate repository [grpc-gateway-boilerplate Then we use curl to send HTTP requests: ```sh -curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " Hello"}' +$ curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " Hello"}' ``` ``` diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index dc182a96eec..541f1fe260f 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -7,7 +7,7 @@ nav_order: 4 # 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`. Then import here is using the path to the generated files in `proto/helloworld` relative to the root of the repository. +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 refer [Creating go.mod file](introduction.md#creating-gomod-file). Then import here is using the path to the generated files in `proto/helloworld` relative to the root of the repository. ```go package main diff --git a/docs/docs/tutorials/generating_stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md index 3bb183ed76b..8c043e78335 100644 --- a/docs/docs/tutorials/generating_stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -41,7 +41,7 @@ We use the `go` and `go-grpc` plugins to generate Go types and gRPC service defi Then run ```sh -buf generate +$ buf generate ``` This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for each protobuf package in our `proto` file hierarchy. diff --git a/docs/docs/tutorials/generating_stubs/using_protoc.md b/docs/docs/tutorials/generating_stubs/using_protoc.md index f06f94c4fde..240fe0e4689 100644 --- a/docs/docs/tutorials/generating_stubs/using_protoc.md +++ b/docs/docs/tutorials/generating_stubs/using_protoc.md @@ -11,7 +11,7 @@ nav_order: 2 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 \ +$ 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 diff --git a/docs/docs/tutorials/introduction.md b/docs/docs/tutorials/introduction.md index 27f10843bfc..4d838329187 100644 --- a/docs/docs/tutorials/introduction.md +++ b/docs/docs/tutorials/introduction.md @@ -28,16 +28,25 @@ We will be using a Go gRPC server in the examples, so please install Go first fr After installing Go, use `go get` to download the following packages: ```sh -go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway -go get google.golang.org/protobuf/cmd/protoc-gen-go -go get google.golang.org/grpc/cmd/protoc-gen-go-grpc +$ go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway +$ go get google.golang.org/protobuf/cmd/protoc-gen-go +$ go get google.golang.org/grpc/cmd/protoc-gen-go-grpc ``` 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 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 } diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 2f3d18f3a8a..446bb3a8c48 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -13,6 +13,8 @@ To understand the gRPC-Gateway we are going to first make a hello world gRPC ser 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 [protocol buffers][pb]. To learn more about how to define a service in a `.proto` file see [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: + ```proto syntax = "proto3"; From 7411cca6aa69b62e8c48ad131fad33b459af02b9 Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sun, 29 Nov 2020 21:59:41 +0530 Subject: [PATCH 14/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 58 +++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 212c9ccf023..d8aec10cd55 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -104,6 +104,64 @@ This should generate a `*.gw.pb.go` file. Usage examples can be found on this [Usage](https://github.com/grpc-ecosystem/grpc-gateway#usage) +### In addition to the main.go + +```go +package gateway + +import ( + "context" + "fmt" + "net/http" + "os" + "strings" + + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + helloworldpb "github.com/iamrajiv/helloworld/proto/helloworld" + "github.com/prometheus/common/log" + "google.golang.org/grpc" +) + +// Run runs the gRPC-Gateway, dialling the provided address. +func Run(dialAddr string) error { + // Create a client connection to the gRPC Server we just started. + // This is where the gRPC-Gateway proxies the requests. + conn, err := grpc.DialContext( + context.Background(), + dialAddr, + grpc.WithBlock(), + ) + if err != nil { + return fmt.Errorf("failed to dial server: %w", err) + } + + gwmux := runtime.NewServeMux() + err = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn) + if err != nil { + return fmt.Errorf("failed to register gateway: %w", err) + } + + port := os.Getenv("PORT") + if port == "" { + port = "11000" + } + gatewayAddr := "0.0.0.0:" + port + gwServer := &http.Server{ + Addr: gatewayAddr, + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.HasPrefix(r.URL.Path, "") { + gwmux.ServeHTTP(w, r) + return + } + }), + } + log.Info("Serving gRPC-Gateway and OpenAPI Documentation on http://", gatewayAddr) + return fmt.Errorf("serving gRPC-Gateway server: %w", gwServer.ListenAndServe()) +} + + +``` + For more refer to this boilerplate repository [grpc-gateway-boilerplate ](https://github.com/johanbrandhorst/grpc-gateway-boilerplate) From 2bf6b0d4239ceb47f1d1d967914a88204332ce2d Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Sun, 29 Nov 2020 22:00:30 +0530 Subject: [PATCH 15/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index d8aec10cd55..db04d30e701 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -158,8 +158,6 @@ func Run(dialAddr string) error { log.Info("Serving gRPC-Gateway and OpenAPI Documentation on http://", gatewayAddr) return fmt.Errorf("serving gRPC-Gateway server: %w", gwServer.ListenAndServe()) } - - ``` For more refer to this boilerplate repository [grpc-gateway-boilerplate From 340994fe7fd2775043ae415701fb02ac82184c9b Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Tue, 1 Dec 2020 14:50:53 +0530 Subject: [PATCH 16/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 90 +++++++++---------- docs/docs/tutorials/creating_main.go.md | 13 +-- docs/docs/tutorials/generating_stubs/index.md | 2 + .../tutorials/generating_stubs/using_buf.md | 4 +- docs/docs/tutorials/learn_more.md | 6 ++ docs/docs/tutorials/simple_hello_world.md | 2 +- 6 files changed, 60 insertions(+), 57 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index db04d30e701..5dac3ac9886 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -11,7 +11,7 @@ Now that we've got a working Go gRPC server, we need to add the grpc-gateway ann 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 you will need to add `import "google/api/http.proto";` to the gRPC proto file. +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. ```proto syntax = "proto3"; @@ -42,9 +42,7 @@ message HelloReply { } ``` -HttpRule is typically specified as an `google.api.http` annotation on the gRPC method. Each mapping specifies a URL path template and an HTTP method. - -Also, See [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/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. +See [a_bit_of_everything.proto](https://github.com/grpc-ecosystem/grpc-gateway/blob/master/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 @@ -102,73 +100,77 @@ $ protoc -I ./proto \ This should generate a `*.gw.pb.go` file. -Usage examples can be found on this [Usage](https://github.com/grpc-ecosystem/grpc-gateway#usage) - -### In addition to the main.go +We also need to add and serve the gRPC-gateway mux in our `main.go` file. ```go -package gateway - +package main import ( "context" - "fmt" - "net/http" + "io/ioutil" + "net" "os" - "strings" - - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - helloworldpb "github.com/iamrajiv/helloworld/proto/helloworld" - "github.com/prometheus/common/log" + "log" "google.golang.org/grpc" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + helloworldpb "github.com/myuser/myrepo/proto/helloworld" ) - -// Run runs the gRPC-Gateway, dialling the provided address. -func Run(dialAddr string) error { +type server struct{} +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() { + lis, err := net.Listen("tcp", ":8080") + if err != nil { + log.Fatalln("Failed to listen:", err) + } + s := grpc.NewServer() + helloworldpb.RegisterGreeterServer(s, &server{}) + // Serve gRPC Server + log.Println("Serving gRPC on 0.0.0.0:8080") + go func() { + log.Fatalln(s.Serve(lis)) + }() // Create a client connection to the gRPC Server we just started. // This is where the gRPC-Gateway proxies the requests. conn, err := grpc.DialContext( context.Background(), - dialAddr, + "0.0.0.0:8080", grpc.WithBlock(), ) if err != nil { - return fmt.Errorf("failed to dial server: %w", err) + log.Fatalln("Failed to dial server:", err) } - gwmux := runtime.NewServeMux() err = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn) if err != nil { - return fmt.Errorf("failed to register gateway: %w", err) + log.Fatalln("Failed to register gateway:", err) } - - port := os.Getenv("PORT") - if port == "" { - port = "11000" - } - gatewayAddr := "0.0.0.0:" + port gwServer := &http.Server{ - Addr: gatewayAddr, - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if strings.HasPrefix(r.URL.Path, "") { - gwmux.ServeHTTP(w, r) - return - } - }), + Addr: ":8090", + Handler: gwmux, } - log.Info("Serving gRPC-Gateway and OpenAPI Documentation on http://", gatewayAddr) - return fmt.Errorf("serving gRPC-Gateway server: %w", gwServer.ListenAndServe()) + log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090") + log.Fatalln(gwServer.ListenAndServe()) } ``` -For more refer to this boilerplate repository [grpc-gateway-boilerplate -](https://github.com/johanbrandhorst/grpc-gateway-boilerplate) +For more examples, please refer to [our boilerplate repository](https://github.com/johanbrandhorst/grpc-gateway-boilerplate). ## Testing the gRPC-Gateway -Then we use curl to send HTTP requests: +Now we can start the server: ```sh -$ curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " Hello"}' +$ 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"}' ``` ``` @@ -177,8 +179,6 @@ $ curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " Hello"}' The process is as follows: -`curl` sends a request to the gateway with the post, gateway as proxy forwards the request to greeter_server through grpc, greeter_server returns the result through grpc, the gateway receives the result, and JSON returns to the front end. - -In this way, the transformation process from HTTP JSON to internal grpc is completed through gRPC-Gateway. +Hopefully, that gives a bit of understanding of how to use the gRPC-Gateway. [Next](learn_more.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index 541f1fe260f..22c5fcfa96f 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -7,21 +7,18 @@ nav_order: 4 # 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 refer [Creating go.mod file](introduction.md#creating-gomod-file). Then import here is using the path to the generated files in `proto/helloworld` relative to the root of the repository. +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" - "io/ioutil" + "log" "net" - "os" - - "google.golang.org/grpc" - "google.golang.org/grpc/grpclog" helloworldpb "github.com/myuser/myrepo/proto/helloworld" + "google.golang.org/grpc" ) type server struct{} @@ -29,11 +26,9 @@ type server struct{} 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() { lis, err := net.Listen("tcp", ":8080") if err != nil { @@ -42,7 +37,7 @@ func main() { s := grpc.NewServer() helloworldpb.RegisterGreeterServer(s, &server{}) // Serve gRPC Server - log.Info("Serving gRPC on 0.0.0.0:8080") + log.Println("Serving gRPC on 0.0.0.0:8080") log.Fatal(s.Serve(lis)) } ``` diff --git a/docs/docs/tutorials/generating_stubs/index.md b/docs/docs/tutorials/generating_stubs/index.md index 16b017c2a3c..172467df30f 100644 --- a/docs/docs/tutorials/generating_stubs/index.md +++ b/docs/docs/tutorials/generating_stubs/index.md @@ -5,3 +5,5 @@ parent: Tutorials nav_order: 3 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. diff --git a/docs/docs/tutorials/generating_stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md index 8c043e78335..d0d0c48929d 100644 --- a/docs/docs/tutorials/generating_stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -8,11 +8,11 @@ nav_order: 1 # 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/)]. +[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 repository. 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. -All Buf operations that use your local `.proto` files as input rely on a valid build configuration. This configuration tells Buf where to search for `.proto` files, and how to handle imports. 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. +All Buf operations that use your local `.proto` files as input rely on a valid build configuration. This configuration tells Buf where to search for `.proto` files, and how to handle imports. 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, assuming you have your `.proto` files rooted in the `proto` folder relative to the root of your repository. diff --git a/docs/docs/tutorials/learn_more.md b/docs/docs/tutorials/learn_more.md index de6b03674b3..cfd46784468 100644 --- a/docs/docs/tutorials/learn_more.md +++ b/docs/docs/tutorials/learn_more.md @@ -7,6 +7,12 @@ nav_order: 6 # Learn More +## How it works + +After we use cURL to send HTTP requests `curl` sends a request to the gateway with the post, gateway as proxy forwards the request to `GreeterServer` through gRPC, `GreeterServer` returns the result through gRPC, the gateway receives the result, and JSON returns to the front end. + +In this way, the transformation process from HTTP JSON to internal gRPC is completed through gRPC-Gateway. + ## google.api.http Read more about `google.api.http` on [https://github.com/googleapis/googleapis/blob/master/google/api/http.proto](https://github.com/googleapis/googleapis/blob/master/google/api/http.proto) diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 446bb3a8c48..49c63709436 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -13,7 +13,7 @@ To understand the gRPC-Gateway we are going to first make a hello world gRPC ser 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 [protocol buffers][pb]. To learn more about how to define a service in a `.proto` file see [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: +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: ```proto syntax = "proto3"; From 0848bd01bfbb498ba11df279790c6380dc74715a Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Tue, 1 Dec 2020 16:40:15 +0530 Subject: [PATCH 17/19] updated tutorials --- docs/docs/tutorials/adding_annotations.md | 32 ++++++++++++++++------- docs/docs/tutorials/creating_main.go.md | 9 ++++++- docs/docs/tutorials/learn_more.md | 4 +-- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 5dac3ac9886..18ffd756e54 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -104,54 +104,70 @@ We also need to add and serve the gRPC-gateway mux in our `main.go` file. ```go package main + import ( "context" - "io/ioutil" - "net" - "os" "log" - "google.golang.org/grpc" + "net" + "net/http" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "google.golang.org/grpc" + helloworldpb "github.com/myuser/myrepo/proto/helloworld" ) + type server struct{} + 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") go func() { log.Fatalln(s.Serve(lis)) }() - // Create a client connection to the gRPC Server we just started. - // This is where the gRPC-Gateway proxies the requests. + + // Create a client connection to the gRPC Server we just started + // This is where the gRPC-Gateway proxies the requests conn, err := grpc.DialContext( context.Background(), "0.0.0.0:8080", grpc.WithBlock(), + grpc.WithInsecure(), ) if err != nil { log.Fatalln("Failed to dial server:", err) } + gwmux := runtime.NewServeMux() + // Register Greeter err = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn) if err != nil { log.Fatalln("Failed to register gateway:", err) } + gwServer := &http.Server{ - Addr: ":8090", + Addr: ":8090", Handler: gwmux, } + log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090") log.Fatalln(gwServer.ListenAndServe()) } @@ -177,8 +193,6 @@ $ curl -X POST -k http://localhost:8090/v1/example/echo -d '{"name": " Hello"}' {"message":"Hello World"} ``` -The process is as follows: - Hopefully, that gives a bit of understanding of how to use the gRPC-Gateway. [Next](learn_more.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/creating_main.go.md b/docs/docs/tutorials/creating_main.go.md index 22c5fcfa96f..669dfac31e5 100644 --- a/docs/docs/tutorials/creating_main.go.md +++ b/docs/docs/tutorials/creating_main.go.md @@ -17,8 +17,9 @@ import ( "log" "net" - helloworldpb "github.com/myuser/myrepo/proto/helloworld" "google.golang.org/grpc" + + helloworldpb "github.com/myuser/myrepo/proto/helloworld" ) type server struct{} @@ -26,15 +27,21 @@ type server struct{} 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") diff --git a/docs/docs/tutorials/learn_more.md b/docs/docs/tutorials/learn_more.md index cfd46784468..c912c7c1ccc 100644 --- a/docs/docs/tutorials/learn_more.md +++ b/docs/docs/tutorials/learn_more.md @@ -9,9 +9,7 @@ nav_order: 6 ## How it works -After we use cURL to send HTTP requests `curl` sends a request to the gateway with the post, gateway as proxy forwards the request to `GreeterServer` through gRPC, `GreeterServer` returns the result through gRPC, the gateway receives the result, and JSON returns to the front end. - -In this way, the transformation process from HTTP JSON to internal gRPC is completed through gRPC-Gateway. +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 From 961f085b5ba6f13893ce594e2ec6dd1a800b26ac Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Tue, 1 Dec 2020 17:27:20 +0530 Subject: [PATCH 18/19] updated tutorials --- docs/docs/tutorials/generating_stubs/using_buf.md | 2 +- docs/docs/tutorials/simple_hello_world.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/docs/tutorials/generating_stubs/using_buf.md b/docs/docs/tutorials/generating_stubs/using_buf.md index d0d0c48929d..392c5470ca2 100644 --- a/docs/docs/tutorials/generating_stubs/using_buf.md +++ b/docs/docs/tutorials/generating_stubs/using_buf.md @@ -46,4 +46,4 @@ $ 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](using_protoc.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } +[Next](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 } diff --git a/docs/docs/tutorials/simple_hello_world.md b/docs/docs/tutorials/simple_hello_world.md index 49c63709436..7347a534687 100644 --- a/docs/docs/tutorials/simple_hello_world.md +++ b/docs/docs/tutorials/simple_hello_world.md @@ -13,7 +13,7 @@ To understand the gRPC-Gateway we are going to first make a hello world gRPC ser 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: +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: ```proto syntax = "proto3"; From 449d3528c5173a5e2171281805c49c07f604748d Mon Sep 17 00:00:00 2001 From: Rajiv Ranjan Singh Date: Tue, 1 Dec 2020 17:40:09 +0530 Subject: [PATCH 19/19] added helloworld link --- docs/docs/tutorials/adding_annotations.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/docs/tutorials/adding_annotations.md b/docs/docs/tutorials/adding_annotations.md index 18ffd756e54..dbf1668edb2 100644 --- a/docs/docs/tutorials/adding_annotations.md +++ b/docs/docs/tutorials/adding_annotations.md @@ -195,4 +195,6 @@ $ curl -X POST -k http://localhost:8090/v1/example/echo -d '{"name": " Hello"}' Hopefully, that gives a bit of understanding of how to use the gRPC-Gateway. +Full source code of hello world 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 }