gRPC Basics - Web

This tutorial provides a basic introduction on how to usegRPC-Web from browsers.

By walking through this example you’ll learn how to:

  • Define a service in a .proto file.
  • Generate client code using the protocol buffer compiler.
  • Use the gRPC-Web API to write a simple client for your service.

It assumes a passing familiarity withprotocolbuffers.

Why use gRPC and gRPC-Web?

With gRPC you can define your service once in a .proto file and implementclients and servers in any of gRPC’s supported languages, which in turn can berun in environments ranging from servers inside Google to your own tablet - allthe complexity of communication between different languages and environments ishandled for you by gRPC. You also get all the advantages of working withprotocol buffers, including efficient serialization, a simple IDL, and easyinterface updating. gRPC-Web lets you access gRPC services built in this mannerfrom browsers using an idiomatic API.

Define the Service

The first step when creating a gRPC service is to define the service methodsand their request and response message types using protocol buffers. In thisexample, we define our EchoService in a file calledecho.proto.For more information about protocol buffers and proto3 syntax, please see theprotobuf documentation.

  1. message EchoRequest {
  2. string message = 1;
  3. }
  4. message EchoResponse {
  5. string message = 1;
  6. }
  7. service EchoService {
  8. rpc Echo(EchoRequest) returns (EchoResponse);
  9. }

Implement gRPC Backend Server

Next, we implement our EchoService interface using Node in the backend gRPCEchoServer. This will handle requests from clients. See the filenode-server/server.jsfor details.

You can implement the server in any language supported by gRPC. Please seethemain page for more details.

  1. function doEcho(call, callback) {
  2. callback(null, {message: call.request.message});
  3. }

Configure the Envoy Proxy

In this example, we will use theEnvoyproxy to forward the gRPC browser request to the backend server. You can seethe complete config file inenvoy.yaml

To forward the gRPC requests to the backend server, we need a block likethis:

  1. listeners:
  2. - name: listener_0
  3. address:
  4. socket_address: { address: 0.0.0.0, port_value: 8080 }
  5. filter_chains:
  6. - filters:
  7. - name: envoy.http_connection_manager
  8. config:
  9. codec_type: auto
  10. stat_prefix: ingress_http
  11. route_config:
  12. name: local_route
  13. virtual_hosts:
  14. - name: local_service
  15. domains: ["*"]
  16. routes:
  17. - match: { prefix: "/" }
  18. route: { cluster: echo_service }
  19. http_filters:
  20. - name: envoy.grpc_web
  21. - name: envoy.router
  22. clusters:
  23. - name: echo_service
  24. connect_timeout: 0.25s
  25. type: logical_dns
  26. http2_protocol_options: {}
  27. lb_policy: round_robin
  28. hosts: [{ socket_address: { address: node-server, port_value: 9090 }}]

You may also need to add some CORS setup to make sure the browser can requestcross-origin content.

In this simple example, the browser makes gRPC requests to port :8080. Envoyforwards the request to the backend gRPC server listening on port :9090.

Generate Protobuf Messages and Service Client Stub

To generate the protobuf message classes from our echo.proto, run thefollowing command:

  1. $ protoc -I=$DIR echo.proto \
  2. --js_out=import_style=commonjs:$OUT_DIR

The import_style option passed to the —js_out flag makes sure thegenerated files will have CommonJS style require() statements.

To generate the gRPC-Web service client stub, first you need the gRPC-Webprotoc plugin. To compile the plugin protoc-gen-grpc-web, you need to runthis from the repo’s root directory:

  1. $ cd grpc-web
  2. $ sudo make install-plugin

To generate the service client stub file, run this command:

  1. $ protoc -I=$DIR echo.proto \
  2. --grpc-web_out=import_style=commonjs,mode=grpcwebtext:$OUT_DIR

In the —grpc-web_out param above:

  • mode can be grpcwebtext (default) or grpcweb
  • import_style can be closure (default) or commonjs

Our command generates the client stub, by default, to the fileecho_grpc_web_pb.js.

Write JS Client Code

Now you are ready to write some JS client code. Put this in a client.js file.

  1. const {EchoRequest, EchoResponse} = require('./echo_pb.js');
  2. const {EchoServiceClient} = require('./echo_grpc_web_pb.js');
  3. var echoService = new EchoServiceClient('http://localhost:8080');
  4. var request = new EchoRequest();
  5. request.setMessage('Hello World!');
  6. echoService.echo(request, {}, function(err, response) {
  7. // ...
  8. });

You will need a package.json file

  1. {
  2. "name": "grpc-web-commonjs-example",
  3. "dependencies": {
  4. "google-protobuf": "^3.6.1",
  5. "grpc-web": "^0.4.0"
  6. },
  7. "devDependencies": {
  8. "browserify": "^16.2.2",
  9. "webpack": "^4.16.5",
  10. "webpack-cli": "^3.1.0"
  11. }
  12. }

Compile the JS Library

Finally, putting all these together, we can compile all the relevant JS filesinto one single JS library that can be used in the browser.

  1. $ npm install
  2. $ npx webpack client.js

Now embed dist/main.js into your project and see it in action!