mirror of https://github.com/grpc/grpc.io.git
343 lines
20 KiB
HTML
343 lines
20 KiB
HTML
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
|
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
|
<title>
|
|
gRPC Basics - Web – gRPC
|
|
</title>
|
|
|
|
|
|
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
|
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
|
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
|
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
|
<link rel="manifest" href="/favicons/manifest.json">
|
|
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
|
<meta name="msapplication-TileColor" content="#ffffff">
|
|
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
|
|
|
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
|
|
gtag('config', 'UA-60127042-1');
|
|
</script>
|
|
|
|
</head>
|
|
<body>
|
|
<div id="landing-content">
|
|
<div class="row">
|
|
<div class="topbannersub">
|
|
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
|
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
|
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
|
</a>
|
|
|
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
|
|
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
|
<ul class="navbar-nav ml-auto">
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
|
</li>
|
|
<li class="nav-item dropdown active">
|
|
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
Docs
|
|
</a>
|
|
|
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
|
|
|
|
|
<a class="dropdown-item" href="/docs">
|
|
Overview
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/quickstart/">
|
|
Quick Start
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/guides/">
|
|
Guides
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/tutorials/">
|
|
Tutorials
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/reference/">
|
|
Reference
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/samples/">
|
|
Samples
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/talks">
|
|
Presentations
|
|
</a>
|
|
|
|
</div>
|
|
</li>
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="/blog">
|
|
Blog
|
|
</a>
|
|
</li>
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="/community">Community</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="https://packages.grpc.io/">
|
|
Packages
|
|
</a>
|
|
</li>
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
|
|
<div class="headertext">Documentation</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="subnav d-none d-md-block">
|
|
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
|
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
|
| <a href="https://cjyabraham.github.io/docs/guides/" >Guides</a>
|
|
| <a href="https://cjyabraham.github.io/docs/tutorials/" class="active">Tutorials</a>
|
|
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
|
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
|
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
|
</div>
|
|
|
|
|
|
<div class="quickstartcols">
|
|
|
|
<div class="quickstartcol1">
|
|
|
|
<h8>Tutorials</h8>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/async/helloasync-cpp/" >Async - C++</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/auth/oauth2-objective-c/" >Auth - Objective C</a>
|
|
<h8>Basic</h8>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/c/" >C++</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/csharp/" >C#</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/dart/" >Dart</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/go/" >Go</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/java/" >Java</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/android/" >Android Java</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/node/" >Node</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/objective-c/" >Objective-C</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/php/" >PHP</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/python/" >Python</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/ruby/" >Ruby</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/web/" class="active">Web</a>
|
|
|
|
</div>
|
|
|
|
<div class="quickstartcol2" style="margin-top:4%">
|
|
<h3 style="margin-top:0px;">gRPC Basics - Web</h3>
|
|
|
|
|
|
|
|
<p>This tutorial provides a basic introduction on how to use
|
|
gRPC-Web from browsers.</p>
|
|
|
|
<p>By walking through this example you’ll learn how to:</p>
|
|
|
|
<ul>
|
|
<li>Define a service in a .proto file.</li>
|
|
<li>Generate client code using the protocol buffer compiler.</li>
|
|
<li>Use the gRPC-Web API to write a simple client for your service.</li>
|
|
</ul>
|
|
|
|
<p>It assumes a passing familiarity with <a href="https://developers.google.com/protocol-buffers/docs/overview">protocol
|
|
buffers</a>.</p>
|
|
|
|
<div id="toc"></div>
|
|
|
|
<p><a name="why-grpc"></a></p>
|
|
|
|
<h3 id="why-use-grpc-and-grpc-web">Why use gRPC and gRPC-Web?</h3>
|
|
|
|
<p>With gRPC you can define your service once in a .proto file and implement
|
|
clients and servers in any of gRPC’s supported languages, which in turn can be
|
|
run in environments ranging from servers inside Google to your own tablet - all
|
|
the complexity of communication between different languages and environments is
|
|
handled for you by gRPC. You also get all the advantages of working with
|
|
protocol buffers, including efficient serialization, a simple IDL, and easy
|
|
interface updating. gRPC-Web lets you access gRPC services built in this manner
|
|
from browsers using an idiomatic API.</p>
|
|
|
|
<p><a name="setup"></a></p>
|
|
|
|
<h3 id="define-the-service">Define the Service</h3>
|
|
|
|
<p>The first step when creating a gRPC service is to define the service methods
|
|
and their request and response message types using protocol buffers. In this
|
|
example, we define our <code>EchoService</code> in a file called
|
|
<a href="https://github.com/grpc/grpc-web/blob/0.4.0/net/grpc/gateway/examples/echo/echo.proto"><code>echo.proto</code></a>.
|
|
For more information about protocol buffers and proto3 syntax, please see the
|
|
<a href="https://developers.google.com/protocol-buffers/">protobuf documentation</a>.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-protobuf" data-lang="protobuf"><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">EchoRequest</span> {<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> <span style="color:#66d9ef">message</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">EchoResponse</span> {<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">string</span> <span style="color:#66d9ef">message</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span>}<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">service</span> EchoService {<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">rpc</span> Echo(EchoRequest) <span style="color:#66d9ef">returns</span> (EchoResponse);<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
|
<h3 id="implement-grpc-backend-server">Implement gRPC Backend Server</h3>
|
|
|
|
<p>Next, we implement our EchoService interface using Node in the backend gRPC
|
|
<code>EchoServer</code>. This will handle requests from clients. See the file
|
|
<a href="https://github.com/grpc/grpc-web/blob/master/net/grpc/gateway/examples/echo/node-server/server.js"><code>node-server/server.js</code></a>
|
|
for details.</p>
|
|
|
|
<p>You can implement the server in any language supported by gRPC. Please see
|
|
the <a href="/docs/">main page</a> for more details.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">function</span> <span style="color:#a6e22e">doEcho</span>(<span style="color:#a6e22e">call</span>, <span style="color:#a6e22e">callback</span>) {
|
|
<span style="color:#a6e22e">callback</span>(<span style="color:#66d9ef">null</span>, {<span style="color:#a6e22e">message</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">call</span>.<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">message</span>});
|
|
}
|
|
</code></pre></div>
|
|
<h3 id="configure-the-envoy-proxy">Configure the Envoy Proxy</h3>
|
|
|
|
<p>In this example, we will use the <a href="https://www.envoyproxy.io/">Envoy</a>
|
|
proxy to forward the gRPC browser request to the backend server. You can see
|
|
the complete config file in
|
|
<a href="https://github.com/grpc/grpc-web/blob/master/net/grpc/gateway/examples/echo/envoy.yaml">envoy.yaml</a></p>
|
|
|
|
<p>To forward the gRPC requests to the backend server, we need a block like
|
|
this:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"> listeners:
|
|
- name: listener_0
|
|
address:
|
|
socket_address: { address: <span style="color:#ae81ff">0.0</span>.<span style="color:#ae81ff">0.0</span>, port_value: <span style="color:#ae81ff">8080</span> }
|
|
filter_chains:
|
|
- filters:
|
|
- name: envoy.http_connection_manager
|
|
config:
|
|
codec_type: auto
|
|
stat_prefix: ingress_http
|
|
route_config:
|
|
name: local_route
|
|
virtual_hosts:
|
|
- name: local_service
|
|
domains: [<span style="color:#e6db74">"*"</span>]
|
|
routes:
|
|
- match: { prefix: <span style="color:#e6db74">"/"</span> }
|
|
route: { cluster: echo_service }
|
|
http_filters:
|
|
- name: envoy.grpc_web
|
|
- name: envoy.router
|
|
clusters:
|
|
- name: echo_service
|
|
connect_timeout: <span style="color:#ae81ff">0.</span>25s
|
|
type: logical_dns
|
|
http2_protocol_options: {}
|
|
lb_policy: round_robin
|
|
hosts: [{ socket_address: { address: node-server, port_value: <span style="color:#ae81ff">9090</span> }}]</code></pre></div>
|
|
<p>You may also need to add some CORS setup to make sure the browser can request
|
|
cross-origin content.</p>
|
|
|
|
<p>In this simple example, the browser makes gRPC requests to port <code>:8080</code>. Envoy
|
|
forwards the request to the backend gRPC server listening on port <code>:9090</code>.</p>
|
|
|
|
<h3 id="generate-protobuf-messages-and-service-client-stub">Generate Protobuf Messages and Service Client Stub</h3>
|
|
|
|
<p>To generate the protobuf message classes from our <code>echo.proto</code>, run the
|
|
following command:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ protoc -I<span style="color:#f92672">=</span>$DIR echo.proto <span style="color:#ae81ff">\
|
|
</span><span style="color:#ae81ff"></span> --js_out<span style="color:#f92672">=</span>import_style<span style="color:#f92672">=</span>commonjs:$OUT_DIR</code></pre></div>
|
|
<p>The <code>import_style</code> option passed to the <code>--js_out</code> flag makes sure the
|
|
generated files will have CommonJS style <code>require()</code> statements.</p>
|
|
|
|
<p>To generate the gRPC-Web service client stub, first you need the gRPC-Web
|
|
protoc plugin. To compile the plugin <code>protoc-gen-grpc-web</code>, you need to run
|
|
this from the repo’s root directory:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd grpc-web
|
|
$ sudo make install-plugin</code></pre></div>
|
|
<p>To generate the service client stub file, run this command:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ protoc -I<span style="color:#f92672">=</span>$DIR echo.proto <span style="color:#ae81ff">\
|
|
</span><span style="color:#ae81ff"></span> --grpc-web_out<span style="color:#f92672">=</span>import_style<span style="color:#f92672">=</span>commonjs,mode<span style="color:#f92672">=</span>grpcwebtext:$OUT_DIR</code></pre></div>
|
|
<p>In the <code>--grpc-web_out</code> param above:
|
|
- <code>mode</code> can be <code>grpcwebtext</code> (default) or <code>grpcweb</code>
|
|
- <code>import_style</code> can be <code>closure</code> (default) or <code>commonjs</code></p>
|
|
|
|
<p>Our command generates the client stub, by default, to the file
|
|
<code>echo_grpc_web_pb.js</code>.</p>
|
|
|
|
<h3 id="write-js-client-code">Write JS Client Code</h3>
|
|
|
|
<p>Now you are ready to write some JS client code. Put this in a <code>client.js</code> file.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-js" data-lang="js"><span style="color:#66d9ef">const</span> {<span style="color:#a6e22e">EchoRequest</span>, <span style="color:#a6e22e">EchoResponse</span>} <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">'./echo_pb.js'</span>);
|
|
<span style="color:#66d9ef">const</span> {<span style="color:#a6e22e">EchoServiceClient</span>} <span style="color:#f92672">=</span> <span style="color:#a6e22e">require</span>(<span style="color:#e6db74">'./echo_grpc_web_pb.js'</span>);
|
|
|
|
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">echoService</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">EchoServiceClient</span>(<span style="color:#e6db74">'http://localhost:8080'</span>);
|
|
|
|
<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">request</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">EchoRequest</span>();
|
|
<span style="color:#a6e22e">request</span>.<span style="color:#a6e22e">setMessage</span>(<span style="color:#e6db74">'Hello World!'</span>);
|
|
|
|
<span style="color:#a6e22e">echoService</span>.<span style="color:#a6e22e">echo</span>(<span style="color:#a6e22e">request</span>, {}, <span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">err</span>, <span style="color:#a6e22e">response</span>) {
|
|
<span style="color:#75715e">// ...
|
|
</span><span style="color:#75715e"></span>});
|
|
</code></pre></div>
|
|
<p>You will need a <code>package.json</code> file</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json">{
|
|
<span style="color:#f92672">"name"</span>: <span style="color:#e6db74">"grpc-web-commonjs-example"</span>,
|
|
<span style="color:#f92672">"dependencies"</span>: {
|
|
<span style="color:#f92672">"google-protobuf"</span>: <span style="color:#e6db74">"^3.6.1"</span>,
|
|
<span style="color:#f92672">"grpc-web"</span>: <span style="color:#e6db74">"^0.4.0"</span>
|
|
},
|
|
<span style="color:#f92672">"devDependencies"</span>: {
|
|
<span style="color:#f92672">"browserify"</span>: <span style="color:#e6db74">"^16.2.2"</span>,
|
|
<span style="color:#f92672">"webpack"</span>: <span style="color:#e6db74">"^4.16.5"</span>,
|
|
<span style="color:#f92672">"webpack-cli"</span>: <span style="color:#e6db74">"^3.1.0"</span>
|
|
}
|
|
}</code></pre></div>
|
|
<h3 id="compile-the-js-library">Compile the JS Library</h3>
|
|
|
|
<p>Finally, putting all these together, we can compile all the relevant JS files
|
|
into one single JS library that can be used in the browser.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ npm install
|
|
$ npx webpack client.js</code></pre></div>
|
|
<p>Now embed <code>dist/main.js</code> into your project and see it in action!</p>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
|
|
|
</body>
|
|
</html>
|