Skip to content

Commit b0c30a6

Browse files
authored
docs: add grpc-web blog (#857)
1 parent f4e47c4 commit b0c30a6

File tree

3 files changed

+611
-2
lines changed

3 files changed

+611
-2
lines changed
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
---
2+
title: "Integrating Apache APISIX with gRPC-Web"
3+
authors:
4+
- name: "Jinchao Shuai"
5+
title: "Author"
6+
url: "https://github.com/shuaijinchao"
7+
image_url: "https://avatars.githubusercontent.com/u/8529452?v=4"
8+
- name: "Yilin Zeng"
9+
title: "Technical Writer"
10+
url: "https://github.com/yzeng25"
11+
image_url: "https://avatars.githubusercontent.com/u/36651058?v=4"
12+
keywords:
13+
- Apache APISIX
14+
- gRPC
15+
- gRPC-Web
16+
- Ecology
17+
description: Apache APISIX already supports gRPC protocol proxies, as well as HTTP(s) to gRPC Server proxies via the gRPC Transcode plugin. Through active community discussion and contributions, Apache APISIX has broadened the scope of support for the gRPC ecosystem, support for the gRPC Web Protocol Request Proxy.
18+
tags: [Technology,Ecosystem]
19+
---
20+
21+
> Apache APISIX already supports gRPC protocol proxies, as well as HTTP(s) to gRPC Server proxies via the gRPC Transcode plugin. Through active community discussion and contributions, Apache APISIX has broadened the scope of support for the gRPC ecosystem: support for the gRPC Web Protocol Request Proxy.
22+
23+
<!--truncate-->
24+
25+
## gRPC Web Introduction
26+
27+
Originally developed by Google, gRPC is a high-performance remote procedure call framework implemented on HTTP/2. However, because browsers do not directly expose HTTP/2, Web applications cannot use gRPC directly. gRPC Web is a standardized protocol that solves this problem.
28+
29+
The first gRPC-web implementation was released in 2018 as a JavaScript library through which Web applications can communicate directly with the gRPC service. The principle is to create an end-to-end gRPC pipeline compatible with HTTP/1.1 and HTTP/2. The browser then sends a regular HTTP request, and a gRPC-Web proxy located between the browser and the server translates the request and response. Similar to gRPC, gRPC Web uses a predefined contract between the Web client and the back-end gRPC service. protocol Buffers are used to serialize and encode messages.
30+
31+
![how gRPC-web works](https://static.apiseven.com/202108/1643099754071-1f5c3c68-f2bc-4746-95f5-cc083ace554b.png)
32+
33+
With gRPC Web, users can call back-end gRPC applications directly using a browser or Node client. However, there are some limitations to using gRPC-Web on the browser side to call gRPC services.
34+
35+
- Client-side streaming and bi-directional streaming calls are not supported.
36+
- Calling gRPC services across domains requires CORS to be configured on the server side.
37+
- The gRPC server side must be configured to support gRPC-Web, or a third-party service agent must be available to translate the call between the browser and the server.
38+
39+
## Apache APISIX gRPC Web Proxy
40+
41+
Apache APISIX supports the proxy of gRPC Web protocol by means of a plug-in, which completes the protocol conversion and data codec work when gRPC Web communicates with gRPC Server in the `grpc-web` plug-in, and its communication process is as follows.
42+
43+
gRPC Web Client -> Apache APISIX (protocol conversion & data codec) -> gRPC server
44+
45+
The following is a complete example showing how to build a gRPC Web Client and proxy gRPC Web requests through Apache APISIX. In the following example, we will use Go as the gRPC Server server handler and Node as the gRPC Web client requestor.
46+
47+
## Configure Protocol Buffer
48+
49+
The first step is to install the Protocol Buffer compiler and related plug-ins.
50+
51+
1. Install `protoc` and `proto-grpc-*`.
52+
53+
The Protocol Buffer compiler `protoc` and the `protoc-gen-go` and `protoc-gen-grpc-web` plugins for generating Go, JavaScript, and gRPC web interface code for `.proto` need to be installed on your system before writing client and server-side applications.
54+
55+
Please run the following script to install the above components.
56+
57+
```bash
58+
#!/usr/bin/env bash
59+
60+
set -ex
61+
62+
PROTOBUF_VERSION="3.19.0"
63+
wget https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
64+
unzip protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
65+
mv bin/protoc /usr/local/bin/protoc
66+
mv include/google /usr/local/include/
67+
chmod +x /usr/local/bin/protoc
68+
69+
PROTO_GO_PLUGIN_VER="1.2.0"
70+
wget https://github.com/grpc/grpc-go/releases/download/cmd/protoc-gen-go-grpc/v${PROTO_GO_PLUGIN_VER}/protoc-gen-go-grpc.v${PROTO_GO_PLUGIN_VER}.linux.amd64.tar.gz
71+
tar -zxvf protoc-gen-go-grpc.v${PROTO_GO_PLUGIN_VER}.linux.amd64.tar.gz
72+
mv protoc-gen-go-grpc /usr/local/bin/protoc-gen-go
73+
chmod +x /usr/local/bin/protoc-gen-go
74+
75+
PROTO_JS_PLUGIN_VER="1.3.0"
76+
wget https://github.com/grpc/grpc-web/releases/download/${PROTO_JS_PLUGIN_VER}/protoc-gen-grpc-web-${PROTO_JS_PLUGIN_VER}-linux-x86_64
77+
mv protoc-gen-grpc-web-${PROTO_JS_PLUGIN_VER}-linux-x86_64 /usr/local/bin/protoc-gen-grpc-web
78+
chmod +x /usr/local/bin/protoc-gen-grpc-web
79+
```
80+
81+
2. Create the `SayHello` example `proto` file.
82+
83+
```go
84+
// a6/echo.proto
85+
86+
syntax = "proto3";
87+
88+
package a6;
89+
90+
option go_package = "./;a6";
91+
92+
message EchoRequest {
93+
string message = 1;
94+
}
95+
96+
message EchoResponse {
97+
string message = 1;
98+
}
99+
100+
service EchoService {
101+
rpc Echo(EchoRequest) returns (EchoResponse);
102+
}
103+
```
104+
105+
## Configure the server-side application
106+
107+
1. Generate server-side Go raw messages and service/client stubs.
108+
109+
```bash
110+
protoc -I./a6 echo.proto --go_out=plugins=grpc:./a6
111+
```
112+
113+
2. Implement the server-side handler interface.
114+
115+
```go
116+
// a6/echo.impl.go
117+
118+
package a6
119+
120+
import (
121+
"errors"
122+
"golang.org/x/net/context"
123+
)
124+
125+
type EchoServiceImpl struct {
126+
}
127+
128+
func (esi *EchoServiceImpl) Echo(ctx context.Context, in *EchoRequest) (*EchoResponse, error) {
129+
if len(in.Message) <= 0 {
130+
return nil, errors.New("message invalid")
131+
}
132+
return &EchoResponse{Message: "response: " + in.Message}, nil
133+
}
134+
```
135+
136+
3. The server-side application runtime entry file.
137+
138+
```go
139+
// server.go
140+
package main
141+
142+
import (
143+
"fmt"
144+
"log"
145+
"net"
146+
147+
"apisix.apache.org/example/a6"
148+
"google.golang.org/grpc"
149+
)
150+
151+
func main() {
152+
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", 50001))
153+
if err != nil {
154+
log.Fatalf("failed to listen: %v", err)
155+
}
156+
157+
grpcServer := grpc.NewServer()
158+
a6.RegisterEchoServiceServer(grpcServer, &a6.EchoServiceImpl{})
159+
160+
if err = grpcServer.Serve(lis); err != nil {
161+
log.Fatalf("failed to serve: %s", err)
162+
}
163+
}
164+
```
165+
166+
4. Compile and start the server-side service.
167+
168+
```bash
169+
go build -o grpc-server server.go
170+
./grpc-server
171+
```
172+
173+
## Configure client programs
174+
175+
1. Generate client-side `proto` code.
176+
177+
Generate client-side JavaScript raw messages, service/client stubs and interface code for gRPC Web's JavaScript.
178+
179+
The `proto` plugin for gRPC Web provides two modes of code generation.
180+
181+
1. mode=grpcwebtext: The default generated code sends the payload in grpc-web-text format.
182+
183+
- Content-type: application/grpc-web-text
184+
- Payload uses base64 encoding
185+
- Supports monadic and server streaming calls
186+
187+
1. mode=grpcweb: send payload in binary protobuf format.
188+
189+
- Content-type: application/grpc-web+proto
190+
- Payload is in binary protobuf format
191+
- Currently only monadic calls are supported
192+
193+
```bash
194+
$ protoc -I=./a6 echo.proto --js_out=import_style=commonjs:./a6 --grpc-web_out=import_style=commonjs,mode=grpcweb:./a6
195+
```
196+
197+
2. Installing client-side dependencies.
198+
199+
```shell
200+
$ npm i grpc-web
201+
$ npm i google-protobuf
202+
```
203+
204+
3. Execute entry file on client-side.
205+
206+
```shell
207+
// client.js
208+
const {EchoRequest} = require('./a6/echo_pb');
209+
const {EchoServiceClient} = require('./a6/echo_grpc_web_pb');
210+
// connect to the entrance of Apache APISIX
211+
let echoService = new EchoServiceClient('http://127.0.0.1:9080');
212+
213+
let request = new EchoRequest();
214+
request.setMessage("hello")
215+
216+
echoService.echo(request, {}, function (err, response) {
217+
if (err) {
218+
console.log(err.code);
219+
console.log(err.message);
220+
} else {
221+
console.log(response.getMessage());
222+
}
223+
});
224+
```
225+
226+
4. Final project structure
227+
228+
```bash
229+
$ tree .
230+
├── a6
231+
│ ├── echo.impl.go
232+
│ ├── echo.pb.go
233+
│ ├── echo.proto
234+
│ ├── echo_grpc_web_pb.js
235+
│ └── echo_pb.js
236+
├── client.js
237+
├── server.go
238+
├── go.mod
239+
├── go.sum
240+
├── package.json
241+
└── package-lock.json
242+
```
243+
244+
After completing the above steps, you have configured the gRPC Server server application and the gRPC Web client application, and started the server application, which will receive requests on port `50001`.
245+
246+
## Configure Apache APISIX
247+
248+
Next, simply enable the `grpc-web` plugin in the Apache APISIX routing plugin configuration to proxy gRPC web requests.
249+
250+
1. Enable the `grpc-web` proxy plugin.
251+
252+
Routing must use **prefix matching** (e.g., `/* or /grpc/example/*`), because the gRPC web client passes the package name, service interface name, method name, etc. declared in `proto` in the URI (e.g., `/path/a6.EchoService/Echo`), **using absolute match will prevent the plugin from extracting `proto` information from the URI**.
253+
254+
```shell
255+
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
256+
{
257+
"uri":"/*", // prefix matching mode
258+
"plugins":{
259+
"grpc-web":{} // enable gRPC Web plugin
260+
},
261+
"upstream":{
262+
"scheme":"grpc",
263+
"type":"roundrobin",
264+
"nodes":{
265+
"127.0.0.1:50001":1 // gRPC Server Listen 地址和端口
266+
}
267+
}
268+
}'
269+
```
270+
271+
2. Validate gRPC Web Proxy Requests.
272+
273+
The gRPC Web protocol request can be sent to Apache APISIX by executing `client.js` from Node.
274+
275+
The above client-side and server-side processing logic are respectively: the client sends a message to the server with the content `hello`, the server receives the message and responds with `response: hello`, and the execution result is as follows.
276+
277+
```shell
278+
$ node client.js
279+
response: hello
280+
```
281+
282+
3. Disable the `grpc-web` proxy plugin.
283+
284+
Simply remove the grpc-web attribute from the routing plugin configuration.
285+
286+
```shell
287+
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
288+
{
289+
"uri":"/*",
290+
"plugins":{
291+
},
292+
"upstream":{
293+
"scheme":"grpc",
294+
"type":"roundrobin",
295+
"nodes":{
296+
"127.0.0.1:50001":1
297+
}
298+
}
299+
}'
300+
```
301+
302+
## Summary
303+
304+
This article brings you hands-on experience about using `grpc-web` in Apache APISIX.
305+
306+
Feel free to start a discussion in [GitHub Discussions](https://github.com/apache/apisix/discussions) or communicate via the [mailing list](https://apisix.apache.org/zh/docs/general/subscribe-guide).

website/i18n/zh/docusaurus-plugin-content-blog/2022/01/21/apisix-hashicorp-vault-integration.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,7 @@ Apache APISIX `jwt-auth` 插件可以被配置为从 Vault 存储中获取简单
323323
}'
324324
```
325325
326-
The plugin looks up for `public_key` and `private_key` keys inside vault kv path (`<vault.prefix from conf.yaml>/consumer/jim/jwt-auth`) for `jim` mentioned inside plugin vault configuration. If not found, authentication fails.
327-
该插件在 Vault 键值对 路径(`<vault.prefix from conf.yaml>/consumer/jim/jwt-auth`)中为插件 Vault 配置中提到的用户 `jim` 查找 `public_key``private_key`。如果没有找到,认证失败。
326+
该插件在 Vault 键值对路径(`<vault.prefix from conf.yaml>/consumer/jim/jwt-auth`)中为插件 Vault 配置中提到的用户 `jim` 查找 `public_key``private_key`。如果没有找到,认证失败。
328327
329328
如果你不确定如何将公钥和私钥存储到 Vault 键值对中,请使用这个命令。
330329

0 commit comments

Comments
 (0)