Skip to content

Commit 806c563

Browse files
authored
[GSoD] Added tutorials directory on gRPC-Gateway (#1829)
* added tutorials directory on grpc-gateway * refactored badges and links * added requested changes * updated tutorials directory on grpc-gateway * updated tutorials directory on grpc-gateway * updated tutorials directory on grpc-gateway * updated tutorials * updated tutorials * updated tutorials * updated tutorials * updated headings and added next button for tutorials * updated next buttons * updated tutorials * updated tutorials * updated tutorials * updated tutorials * updated tutorials * updated tutorials * added helloworld link
1 parent 0096364 commit 806c563

File tree

11 files changed

+460
-4
lines changed

11 files changed

+460
-4
lines changed

docs/docs/faq.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
layout: default
33
title: FAQ
4-
nav_order: 7
4+
nav_order: 8
55
---
66

77
# FAQ
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
---
2+
layout: default
3+
title: Adding the grpc-gateway annotations to an existing protobuf file
4+
parent: Tutorials
5+
nav_order: 5
6+
---
7+
8+
# Adding the grpc-gateway annotations to an existing protobuf file
9+
10+
Now that we've got a working Go gRPC server, we need to add the grpc-gateway annotations.
11+
12+
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.
13+
14+
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.
15+
16+
```proto
17+
syntax = "proto3";
18+
19+
package helloworld;
20+
21+
import "google/api/annotations.proto";
22+
23+
// Here is the overall greeting service definition where we define all our endpoints
24+
service Greeter {
25+
// Sends a greeting
26+
rpc SayHello (HelloRequest) returns (HelloReply) {
27+
option (google.api.http) = {
28+
post: "/v1/example/echo"
29+
body: "*"
30+
};
31+
}
32+
}
33+
34+
// The request message containing the user's name
35+
message HelloRequest {
36+
string name = 1;
37+
}
38+
39+
// The response message containing the greetings
40+
message HelloReply {
41+
string message = 1;
42+
}
43+
```
44+
45+
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.
46+
47+
## Generating the grpc-gateway stubs
48+
49+
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.
50+
51+
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:
52+
53+
```
54+
proto
55+
├── google
56+
│ └── api
57+
│ ├── annotations.proto
58+
│ └── http.proto
59+
└── helloworld
60+
└── hello_world.proto
61+
```
62+
63+
### Using buf
64+
65+
We'll need to add the grpc-gateway generator to the generation configuration:
66+
67+
```yml
68+
version: v1beta1
69+
plugins:
70+
- name: go
71+
out: proto
72+
opt: paths=source_relative
73+
- name: go-grpc
74+
out: proto
75+
opt: paths=source_relative,require_unimplemented_servers=false
76+
- name: grpc-gateway
77+
out: proto
78+
opt: paths=source_relative
79+
```
80+
81+
And that's it! Now if you run:
82+
83+
```sh
84+
$ buf generate
85+
```
86+
87+
It should produce a `*.gw.pb.go` file.
88+
89+
### Using protoc
90+
91+
Now we need to add the grpc-gateway generator to the protoc invocation:
92+
93+
```sh
94+
$ protoc -I ./proto \
95+
--go_out ./proto --go_opt paths=source_relative \
96+
--go-grpc_out ./proto --go-grpc_opt paths=source_relative \
97+
--grpc-gateway_out ./proto --grpc-gateway_opt paths=source_relative \
98+
./proto/helloworld/hello_world.proto
99+
```
100+
101+
This should generate a `*.gw.pb.go` file.
102+
103+
We also need to add and serve the gRPC-gateway mux in our `main.go` file.
104+
105+
```go
106+
package main
107+
108+
import (
109+
"context"
110+
"log"
111+
"net"
112+
"net/http"
113+
114+
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
115+
"google.golang.org/grpc"
116+
117+
helloworldpb "github.com/myuser/myrepo/proto/helloworld"
118+
)
119+
120+
type server struct{}
121+
122+
func NewServer() *server {
123+
return &server{}
124+
}
125+
126+
func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) {
127+
return &helloworldpb.HelloReply{Message: in.Name + " World"}, nil
128+
}
129+
130+
func main() {
131+
// Create a listener on TCP port
132+
lis, err := net.Listen("tcp", ":8080")
133+
if err != nil {
134+
log.Fatalln("Failed to listen:", err)
135+
}
136+
137+
// Create a gRPC server object
138+
s := grpc.NewServer()
139+
// Attach the Greeter service to the server
140+
helloworldpb.RegisterGreeterServer(s, &server{})
141+
// Serve gRPC Server
142+
log.Println("Serving gRPC on 0.0.0.0:8080")
143+
go func() {
144+
log.Fatalln(s.Serve(lis))
145+
}()
146+
147+
// Create a client connection to the gRPC Server we just started
148+
// This is where the gRPC-Gateway proxies the requests
149+
conn, err := grpc.DialContext(
150+
context.Background(),
151+
"0.0.0.0:8080",
152+
grpc.WithBlock(),
153+
grpc.WithInsecure(),
154+
)
155+
if err != nil {
156+
log.Fatalln("Failed to dial server:", err)
157+
}
158+
159+
gwmux := runtime.NewServeMux()
160+
// Register Greeter
161+
err = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn)
162+
if err != nil {
163+
log.Fatalln("Failed to register gateway:", err)
164+
}
165+
166+
gwServer := &http.Server{
167+
Addr: ":8090",
168+
Handler: gwmux,
169+
}
170+
171+
log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")
172+
log.Fatalln(gwServer.ListenAndServe())
173+
}
174+
```
175+
176+
For more examples, please refer to [our boilerplate repository](https://github.com/johanbrandhorst/grpc-gateway-boilerplate).
177+
178+
## Testing the gRPC-Gateway
179+
180+
Now we can start the server:
181+
182+
```sh
183+
$ go run main.go
184+
```
185+
186+
Then we use cURL to send HTTP requests:
187+
188+
```sh
189+
$ curl -X POST -k http://localhost:8090/v1/example/echo -d '{"name": " Hello"}'
190+
```
191+
192+
```
193+
{"message":"Hello World"}
194+
```
195+
196+
Hopefully, that gives a bit of understanding of how to use the gRPC-Gateway.
197+
198+
Full source code of hello world can be found here [helloworld-grpc-gateway](https://github.com/iamrajiv/helloworld-grpc-gateway)
199+
200+
[Next](learn_more.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
layout: default
3+
title: Creating main.go
4+
parent: Tutorials
5+
nav_order: 4
6+
---
7+
8+
# Creating main.go
9+
10+
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.
11+
12+
```go
13+
package main
14+
15+
import (
16+
"context"
17+
"log"
18+
"net"
19+
20+
"google.golang.org/grpc"
21+
22+
helloworldpb "github.com/myuser/myrepo/proto/helloworld"
23+
)
24+
25+
type server struct{}
26+
27+
func NewServer() *server {
28+
return &server{}
29+
}
30+
31+
func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) {
32+
return &helloworldpb.HelloReply{Message: in.Name + " World"}, nil
33+
}
34+
35+
func main() {
36+
// Create a listener on TCP port
37+
lis, err := net.Listen("tcp", ":8080")
38+
if err != nil {
39+
log.Fatalln("Failed to listen:", err)
40+
}
41+
42+
// Create a gRPC server object
43+
s := grpc.NewServer()
44+
// Attach the Greeter service to the server
45+
helloworldpb.RegisterGreeterServer(s, &server{})
46+
// Serve gRPC Server
47+
log.Println("Serving gRPC on 0.0.0.0:8080")
48+
log.Fatal(s.Serve(lis))
49+
}
50+
```
51+
52+
## Read More
53+
54+
For more refer to gRPC docs [https://grpc.io/docs/languages/go/](https://grpc.io/docs/languages/go/).
55+
56+
[Next](adding_annotations.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
layout: default
3+
title: Generating stubs
4+
parent: Tutorials
5+
nav_order: 3
6+
has_children: true
7+
---
8+
9+
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.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
layout: default
3+
title: Generating stubs using buf
4+
parent: Generating stubs
5+
grand_parent: Tutorials
6+
nav_order: 1
7+
---
8+
9+
# Generating stubs using buf
10+
11+
[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/).
12+
13+
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.
14+
15+
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.
16+
17+
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.
18+
19+
```yml
20+
version: v1beta1
21+
build:
22+
roots:
23+
- proto
24+
```
25+
26+
To generate type and gRPC stubs for Go, create the file `buf.gen.yaml` at the root of the repository:
27+
28+
```yml
29+
version: v1beta1
30+
plugins:
31+
- name: go
32+
out: proto
33+
opt: paths=source_relative
34+
- name: go-grpc
35+
out: proto
36+
opt: paths=source_relative
37+
```
38+
39+
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.
40+
41+
Then run
42+
43+
```sh
44+
$ buf generate
45+
```
46+
47+
This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for each protobuf package in our `proto` file hierarchy.
48+
49+
[Next](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
layout: default
3+
title: Generating stubs using protoc
4+
parent: Generating stubs
5+
grand_parent: Tutorials
6+
nav_order: 2
7+
---
8+
9+
# Generating stubs using protoc
10+
11+
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`:
12+
13+
```sh
14+
$ protoc -I ./proto \
15+
--go_out ./proto --go_opt paths=source_relative \
16+
--go-grpc_out ./proto --go-grpc_opt paths=source_relative \
17+
./proto/helloworld/hello_world.proto
18+
```
19+
20+
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.
21+
22+
This will have generated a `*.pb.go` and a `*_grpc.pb.go` file for `proto/helloworld/hello_world.proto`.
23+
24+
[Next](../creating_main.go.md){: .btn .btn-primary .fs-5 .mb-4 .mb-md-0 .mr-2 }

docs/docs/tutorials/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
layout: default
3+
title: Tutorials
4+
nav_order: 7
5+
has_children: true
6+
---

0 commit comments

Comments
 (0)