mirror of https://github.com/grpc/grpc.io.git
Quick start and Tutorial cleanup across all languages (#112)
- Closes #87 - Closes #88 - Contributes to #111 - Markdown cleanup - Copyedits in an attempt to bring some uniformity across language Quick Start and Tutorials.
This commit is contained in:
parent
1acb8697ab
commit
07b1440ba3
|
|
@ -7,26 +7,25 @@ description: This guide gets you started with gRPC in Android Java with a simple
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
### Before you begin
|
### Prerequisites
|
||||||
|
|
||||||
#### Prerequisites
|
- JDK version 7 or higher
|
||||||
|
- Android SDK, API level 14 or higher
|
||||||
|
- An android device set up for [USB debugging][] or an
|
||||||
|
[Android Virtual Device][]
|
||||||
|
|
||||||
* JDK: version 7 or higher
|
[Android Virtual Device]: https://developer.android.com/studio/run/managing-avds.html
|
||||||
* Android SDK: API level 14 or higher
|
[USB debugging]: https://developer.android.com/studio/command-line/adb.html#Enabling
|
||||||
* An android device set up for [USB
|
|
||||||
debugging](https://developer.android.com/studio/command-line/adb.html#Enabling)
|
|
||||||
or an [Android Virtual
|
|
||||||
Device](https://developer.android.com/studio/run/managing-avds.html)
|
|
||||||
|
|
||||||
Note: gRPC Java does not support running a server on an Android device. For this
|
> **Note**: gRPC Java does not support running a server on an Android device.
|
||||||
quickstart, the Android client app will connect to a server running on your
|
> For this quick start, the Android client app will connect to a server running
|
||||||
local (non-Android) computer.
|
> on your local (non-Android) computer.
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|
@ -38,19 +37,19 @@ $ cd grpc-java/examples
|
||||||
|
|
||||||
### Run a gRPC application
|
### Run a gRPC application
|
||||||
|
|
||||||
1. Compile the server
|
1. Compile the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./gradlew installDist
|
$ ./gradlew installDist
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Run the server
|
2. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./build/install/examples/bin/hello-world-server
|
$ ./build/install/examples/bin/hello-world-server
|
||||||
```
|
```
|
||||||
|
|
||||||
3. In another terminal, compile and run the client
|
3. From another terminal, compile and run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ cd android/helloworld
|
$ cd android/helloworld
|
||||||
|
|
@ -111,7 +110,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Update and run the application
|
### Update and run the application
|
||||||
|
|
||||||
|
|
@ -125,7 +124,7 @@ parts of our example application.
|
||||||
|
|
||||||
#### Update the server
|
#### Update the server
|
||||||
|
|
||||||
Check out the Java quickstart [here](/docs/quickstart/java/#update-the-server).
|
See the [Java quick start](/docs/quickstart/java/#update-the-server).
|
||||||
|
|
||||||
#### Update the client
|
#### Update the client
|
||||||
|
|
||||||
|
|
@ -134,17 +133,17 @@ In the same directory, open
|
||||||
method like this:
|
method like this:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
try {
|
try {
|
||||||
HelloRequest message = HelloRequest.newBuilder().setName(mMessage).build();
|
HelloRequest message = HelloRequest.newBuilder().setName(mMessage).build();
|
||||||
HelloReply reply = stub.sayHello(message);
|
HelloReply reply = stub.sayHello(message);
|
||||||
reply = stub.sayHelloAgain(message);
|
reply = stub.sayHelloAgain(message);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
e.printStackTrace(pw);
|
e.printStackTrace(pw);
|
||||||
pw.flush();
|
pw.flush();
|
||||||
return "Failed... : " + System.lineSeparator() + sw;
|
return "Failed... : " + System.lineSeparator() + sw;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Run!
|
#### Run!
|
||||||
|
|
@ -157,13 +156,13 @@ Just like we did before, from the `examples` directory:
|
||||||
$ ./gradlew installDist
|
$ ./gradlew installDist
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Run the server
|
2. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./build/install/examples/bin/hello-world-server
|
$ ./build/install/examples/bin/hello-world-server
|
||||||
```
|
```
|
||||||
|
|
||||||
3. In another terminal, compile and install the client to your device
|
3. From another terminal, compile and install the client to your device
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ cd android/helloworld
|
$ cd android/helloworld
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,9 @@ description: This guide gets you started with gRPC in C++ with a simple working
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
### Before you begin
|
### Prerequisites
|
||||||
|
|
||||||
#### Install gRPC
|
#### gRPC
|
||||||
|
|
||||||
To install gRPC on your system, follow the [instructions to install gRPC C++ via make](https://github.com/grpc/grpc/blob/master/src/cpp/README.md#make).
|
To install gRPC on your system, follow the [instructions to install gRPC C++ via make](https://github.com/grpc/grpc/blob/master/src/cpp/README.md#make).
|
||||||
|
|
||||||
|
|
@ -19,7 +19,7 @@ example `Makefile`s try to look up the installed gRPC path using `pkg-config`.
|
||||||
On Debian-based systems like Ubuntu, this can usually be done via
|
On Debian-based systems like Ubuntu, this can usually be done via
|
||||||
`sudo apt-get install pkg-config`.
|
`sudo apt-get install pkg-config`.
|
||||||
|
|
||||||
#### Install Protocol Buffers v3
|
#### Protocol Buffers v3
|
||||||
|
|
||||||
While not mandatory to use gRPC, gRPC applications usually leverage Protocol
|
While not mandatory to use gRPC, gRPC applications usually leverage Protocol
|
||||||
Buffers v3 for service definitions and data serialization, and our example code
|
Buffers v3 for service definitions and data serialization, and our example code
|
||||||
|
|
@ -55,11 +55,13 @@ instructions for details](https://github.com/grpc/grpc/blob/master/src/cpp/READM
|
||||||
|
|
||||||
From the `examples/cpp/helloworld` directory, run the server, which will listen
|
From the `examples/cpp/helloworld` directory, run the server, which will listen
|
||||||
on port 50051:
|
on port 50051:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./greeter_server
|
$ ./greeter_server
|
||||||
```
|
```
|
||||||
|
|
||||||
From a different terminal, run the client:
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./greeter_client
|
$ ./greeter_client
|
||||||
```
|
```
|
||||||
|
|
@ -69,7 +71,6 @@ client side output.
|
||||||
|
|
||||||
Congratulations! You've just run a client-server application with gRPC.
|
Congratulations! You've just run a client-server application with gRPC.
|
||||||
|
|
||||||
|
|
||||||
### Update a gRPC service
|
### Update a gRPC service
|
||||||
|
|
||||||
Now let's look at how to update the application with an extra method on the
|
Now let's look at how to update the application with an extra method on the
|
||||||
|
|
@ -81,7 +82,6 @@ C++](/docs/tutorials/basic/cpp/). For now all you need to know is that both the
|
||||||
the client and returns a `HelloResponse` from the server, and that this method
|
the client and returns a `HelloResponse` from the server, and that this method
|
||||||
is defined like this:
|
is defined like this:
|
||||||
|
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// The greeting service definition.
|
// The greeting service definition.
|
||||||
service Greeter {
|
service Greeter {
|
||||||
|
|
@ -105,7 +105,6 @@ Let's update this so that the `Greeter` service has two methods. Edit
|
||||||
update it with a new `SayHelloAgain` method, with the same request and response
|
update it with a new `SayHelloAgain` method, with the same request and response
|
||||||
types:
|
types:
|
||||||
|
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// The greeting service definition.
|
// The greeting service definition.
|
||||||
service Greeter {
|
service Greeter {
|
||||||
|
|
@ -126,7 +125,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Generate gRPC code
|
### Generate gRPC code
|
||||||
|
|
||||||
|
|
@ -151,7 +150,6 @@ and call the new method in the human-written parts of our example application.
|
||||||
In the same directory, open `greeter_server.cc`. Implement the new method like
|
In the same directory, open `greeter_server.cc`. Implement the new method like
|
||||||
this:
|
this:
|
||||||
|
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
class GreeterServiceImpl final : public Greeter::Service {
|
class GreeterServiceImpl final : public Greeter::Service {
|
||||||
Status SayHello(ServerContext* context, const HelloRequest* request,
|
Status SayHello(ServerContext* context, const HelloRequest* request,
|
||||||
|
|
@ -223,28 +221,27 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
Just like we did before, from the `examples/cpp/helloworld` directory:
|
Just like we did before, from the `examples/cpp/helloworld` directory:
|
||||||
|
|
||||||
1. Build the client and server after having made changes:
|
1. Build the client and server after having made changes:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ make
|
$ make
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Run the server
|
2. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./greeter_server
|
$ ./greeter_server
|
||||||
```
|
```
|
||||||
|
|
||||||
3. On a different terminal, run the client
|
3. On a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./greeter_client
|
$ ./greeter_client
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see the updated output:
|
You'll see the following output:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./greeter_client
|
|
||||||
Greeter received: Hello world
|
Greeter received: Hello world
|
||||||
Greeter received: Hello again world
|
Greeter received: Hello again world
|
||||||
```
|
```
|
||||||
|
|
@ -252,7 +249,7 @@ Just like we did before, from the `examples/cpp/helloworld` directory:
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: C++](/docs/tutorials/basic/cpp/)
|
- Work through a more detailed tutorial in [gRPC Basics: C++](/docs/tutorials/basic/cpp/).
|
||||||
- Explore the gRPC C++ core API in its [reference
|
- Explore the gRPC C++ core API in its [reference
|
||||||
documentation](/grpc/cpp/)
|
documentation](/grpc/cpp/).
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ description: This guide gets you started with gRPC for .NET with a simple workin
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
NOTE: This is a quick start guide for the "grpc-dotnet" implementation of gRPC C#s.
|
> **Note**: This is a quick start guide for the "grpc-dotnet" implementation of
|
||||||
See [gRPC C# Quick Start](/docs/quickstart/csharp) for how to start with the gRPC C# implementation based on native Core library.
|
> gRPC C#s. See [gRPC C# Quick Start](/docs/quickstart/csharp) for how to start
|
||||||
|
> with the gRPC C# implementation based on native Core library.
|
||||||
|
|
||||||
### General project info
|
### General project info
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@ description: This guide gets you started with gRPC in C# with a simple working e
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
NOTE: This is a quick start guide for the gRPC C# implementation based on Core native library.
|
> **Note**: This is a quick start guide for the gRPC C# implementation based on
|
||||||
See [gRPC for .NET Quick Start](/docs/quickstart/csharp-dotnet/) for how to start with the "grpc-dotnet" implementation.
|
> Core native library. See [gRPC for .NET Quick
|
||||||
|
> Start](/docs/quickstart/csharp-dotnet/) for how to start with the
|
||||||
|
> "grpc-dotnet" implementation.
|
||||||
|
|
||||||
### Before you begin
|
### Prerequisites
|
||||||
|
|
||||||
#### Prerequisites
|
|
||||||
|
|
||||||
Whether you're using Windows, OS X, or Linux, you can follow this
|
Whether you're using Windows, OS X, or Linux, you can follow this
|
||||||
example by using either an IDE and its build tools,
|
example by using either an IDE and its build tools,
|
||||||
|
|
@ -24,13 +24,13 @@ You will also need Git to download the sample code.
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # Clone the repository to get the example code:
|
# Clone the repository to get the example code:
|
||||||
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
||||||
$ cd grpc
|
$ cd grpc
|
||||||
```
|
```
|
||||||
|
|
@ -61,14 +61,14 @@ From the `examples/csharp/Helloworld` directory:
|
||||||
|
|
||||||
From the `examples/csharp/Helloworld` directory:
|
From the `examples/csharp/Helloworld` directory:
|
||||||
|
|
||||||
* Run the server
|
* Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
> cd GreeterServer
|
> cd GreeterServer
|
||||||
> dotnet run -f netcoreapp2.1
|
> dotnet run -f netcoreapp2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
* In another terminal, run the client
|
* From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
> cd GreeterClient
|
> cd GreeterClient
|
||||||
|
|
@ -130,7 +130,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Generate gRPC code
|
### Generate gRPC code
|
||||||
|
|
||||||
|
|
@ -220,24 +220,24 @@ example by running `dotnet build Greeter.sln` or by clicking "Build" in Visual S
|
||||||
|
|
||||||
Just like we did before, from the `examples/csharp/Helloworld` directory:
|
Just like we did before, from the `examples/csharp/Helloworld` directory:
|
||||||
|
|
||||||
* Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
> cd GreeterServer
|
> cd GreeterServer
|
||||||
> dotnet run -f netcoreapp2.1
|
> dotnet run -f netcoreapp2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
* In another terminal, run the client
|
2. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
> cd GreeterClient
|
> cd GreeterClient
|
||||||
> dotnet run -f netcoreapp2.1
|
> dotnet run -f netcoreapp2.1
|
||||||
```
|
```
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: C#](/docs/tutorials/basic/csharp/)
|
- Work through a more detailed tutorial in [gRPC Basics: C#](/docs/tutorials/basic/csharp/).
|
||||||
- Explore the gRPC C# core API in its [reference
|
- Explore the gRPC C# core API in its [reference
|
||||||
documentation](/grpc/csharp/api/Grpc.Core.html)
|
documentation](/grpc/csharp/api/Grpc.Core.html).
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ description: This guide gets you started with gRPC in Dart with a simple working
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
#### Dart SDK
|
- Dart SDK version 2.0 or higher.
|
||||||
|
|
||||||
gRPC requires Dart SDK version 2.0 or higher. Dart gRPC supports Flutter and Server platforms.
|
|
||||||
|
|
||||||
For installation instructions, see [Install Dart](https://dart.dev/install).
|
For installation instructions, see [Install Dart](https://dart.dev/install).
|
||||||
|
|
||||||
|
> Note: Dart gRPC supports the Flutter and Server platforms.
|
||||||
|
|
||||||
#### Protocol Buffers v3
|
#### Protocol Buffers v3
|
||||||
|
|
||||||
While not mandatory to use gRPC, gRPC applications usually leverage Protocol
|
While not mandatory to use gRPC, gRPC applications usually leverage Protocol
|
||||||
|
|
@ -44,9 +44,9 @@ $ export PATH=$PATH:$HOME/.pub-cache/bin
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|
@ -66,13 +66,13 @@ From the `example/helloworld` directory:
|
||||||
$ pub get
|
$ pub get
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Run the server
|
2. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ dart bin/server.dart
|
$ dart bin/server.dart
|
||||||
```
|
```
|
||||||
|
|
||||||
3. In another terminal, run the client
|
3. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ dart bin/client.dart
|
$ dart bin/client.dart
|
||||||
|
|
@ -205,25 +205,25 @@ Future<void> main(List<String> args) async {
|
||||||
Run the client and server like you did before. Execute the following commands
|
Run the client and server like you did before. Execute the following commands
|
||||||
from the `example/helloworld` directory:
|
from the `example/helloworld` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ dart bin/server.dart
|
$ dart bin/server.dart
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In another terminal, run the client. This time, add a name as a command-line
|
2. From another terminal, run the client. This time, add a name as a command-line
|
||||||
argument:
|
argument:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ dart bin/client.dart Alice
|
$ dart bin/client.dart Alice
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see the following output in the client terminal:
|
You'll see the following output:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
Greeter client received: Hello, Alice!
|
Greeter client received: Hello, Alice!
|
||||||
Greeter client received: Hello again, Alice!
|
Greeter client received: Hello again, Alice!
|
||||||
```
|
```
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,17 +9,11 @@ description: This guide gets you started with gRPC in Go with a simple working e
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
#### Go version
|
- Go version 1.6 or higher.
|
||||||
|
|
||||||
gRPC requires Go 1.6 or higher.
|
For installation instructions, see Go's [Getting Started](https://golang.org/doc/install) guide.
|
||||||
|
|
||||||
```sh
|
#### gRPC
|
||||||
$ go version
|
|
||||||
```
|
|
||||||
|
|
||||||
For installation instructions, follow this guide: [Getting Started - The Go Programming Language](https://golang.org/doc/install)
|
|
||||||
|
|
||||||
#### Install gRPC
|
|
||||||
|
|
||||||
Use the following command to install gRPC.
|
Use the following command to install gRPC.
|
||||||
|
|
||||||
|
|
@ -27,7 +21,7 @@ Use the following command to install gRPC.
|
||||||
$ go get -u google.golang.org/grpc
|
$ go get -u google.golang.org/grpc
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Install Protocol Buffers v3
|
#### Protocol Buffers v3
|
||||||
|
|
||||||
Install the protoc compiler that is used to generate gRPC service code. The simplest way to do this is to download pre-compiled binaries for your platform(`protoc-<version>-<platform>.zip`) from here: [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases)
|
Install the protoc compiler that is used to generate gRPC service code. The simplest way to do this is to download pre-compiled binaries for your platform(`protoc-<version>-<platform>.zip`) from here: [https://github.com/google/protobuf/releases](https://github.com/google/protobuf/releases)
|
||||||
|
|
||||||
|
|
@ -40,7 +34,9 @@ Next, install the protoc plugin for Go
|
||||||
$ go get -u github.com/golang/protobuf/protoc-gen-go
|
$ go get -u github.com/golang/protobuf/protoc-gen-go
|
||||||
```
|
```
|
||||||
|
|
||||||
The compiler plugin, protoc-gen-go, will be installed in $GOBIN, defaulting to $GOPATH/bin. It must be in your $PATH for the protocol compiler, protoc, to find it.
|
The compiler plugin, `protoc-gen-go`, will be installed in `$GOBIN`, defaulting
|
||||||
|
to `$GOPATH/bin`. It must be in your `PATH` for the protocol compiler, protoc,
|
||||||
|
to find it.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ export PATH=$PATH:$GOPATH/bin
|
$ export PATH=$PATH:$GOPATH/bin
|
||||||
|
|
@ -58,14 +54,19 @@ Change to the example directory
|
||||||
$ cd $GOPATH/src/google.golang.org/grpc/examples/helloworld
|
$ cd $GOPATH/src/google.golang.org/grpc/examples/helloworld
|
||||||
```
|
```
|
||||||
|
|
||||||
gRPC services are defined in a `.proto` file, which is used to generate a corresponding `.pb.go` file. The `.pb.go` file is generated by compiling the `.proto` file using the protocol compiler: `protoc`.
|
gRPC services are defined in a `.proto` file, which is used to generate a
|
||||||
|
corresponding `.pb.go` file. The `.pb.go` file is generated by compiling the
|
||||||
|
`.proto` file using the protocol compiler: `protoc`.
|
||||||
|
|
||||||
For the purpose of this example, the `helloworld.pb.go` file has already been generated (by compiling `helloworld.proto`), and can be found in this directory: `$GOPATH/src/google.golang.org/grpc/examples/helloworld/helloworld`
|
For the purpose of this example, the `helloworld.pb.go` file has already been
|
||||||
|
generated (by compiling `helloworld.proto`), and can be found in this directory:
|
||||||
|
`$GOPATH/src/google.golang.org/grpc/examples/helloworld/helloworld`
|
||||||
|
|
||||||
This `helloworld.pb.go` file contains:
|
This `helloworld.pb.go` file contains:
|
||||||
|
|
||||||
* Generated client and server code.
|
- Generated client and server code.
|
||||||
* Code for populating, serializing, and retrieving our `HelloRequest` and `HelloReply` message types.
|
- Code for populating, serializing, and retrieving our `HelloRequest` and
|
||||||
|
`HelloReply` message types.
|
||||||
|
|
||||||
### Try it!
|
### Try it!
|
||||||
|
|
||||||
|
|
@ -115,10 +116,12 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's update this so that the `Greeter` service has two methods. Make sure you are in the same examples dir as above (`$GOPATH/src/google.golang.org/grpc/examples/helloworld`)
|
Let's update this so that the `Greeter` service has two methods. Make sure you
|
||||||
|
are in the same examples dir as above
|
||||||
|
(`$GOPATH/src/google.golang.org/grpc/examples/helloworld`).
|
||||||
|
|
||||||
Edit `helloworld/helloworld.proto` and update it with a new `SayHelloAgain` method, with the same request and response
|
Edit `helloworld/helloworld.proto` and update it with a new `SayHelloAgain`
|
||||||
types:
|
method, with the same request and response types:
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// The greeting service definition.
|
// The greeting service definition.
|
||||||
|
|
@ -143,7 +146,8 @@ message HelloReply {
|
||||||
### Generate gRPC code
|
### Generate gRPC code
|
||||||
|
|
||||||
Next we need to update the gRPC code used by our application to use the new
|
Next we need to update the gRPC code used by our application to use the new
|
||||||
service definition. From the same examples dir as above (`$GOPATH/src/google.golang.org/grpc/examples/helloworld`)
|
service definition. From the same examples dir as above
|
||||||
|
(`$GOPATH/src/google.golang.org/grpc/examples/helloworld`):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
|
$ protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
|
||||||
|
|
@ -180,30 +184,29 @@ log.Printf("Greeting: %s", r.GetMessage())
|
||||||
|
|
||||||
#### Run!
|
#### Run!
|
||||||
|
|
||||||
Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ go run greeter_server/main.go
|
$ go run greeter_server/main.go
|
||||||
```
|
```
|
||||||
|
|
||||||
On a different terminal, run the client
|
2. On a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ go run greeter_client/main.go
|
$ go run greeter_client/main.go
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see the updated output:
|
You'll see the following output:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ go run greeter_client/main.go
|
Greeting: Hello world
|
||||||
Greeting: Hello world
|
Greeting: Hello again world
|
||||||
Greeting: Hello again world
|
```
|
||||||
```
|
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: Go](/docs/tutorials/basic/go/)
|
- Work through a more detailed tutorial in [gRPC Basics: Go](/docs/tutorials/basic/go/).
|
||||||
- Explore the gRPC Go core API in its [reference
|
- Explore the gRPC Go core API in its [reference
|
||||||
documentation](https://godoc.org/google.golang.org/grpc)
|
documentation](https://godoc.org/google.golang.org/grpc).
|
||||||
|
|
|
||||||
|
|
@ -7,17 +7,15 @@ description: This guide gets you started with gRPC in Java with a simple working
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
### Before you begin
|
### Prerequisites
|
||||||
|
|
||||||
#### Prerequisites
|
- JDK version 7 or higher
|
||||||
|
|
||||||
* JDK: version 7 or higher
|
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
|
@ -37,13 +35,13 @@ From the `examples` directory:
|
||||||
$ ./gradlew installDist
|
$ ./gradlew installDist
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Run the server
|
2. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./build/install/examples/bin/hello-world-server
|
$ ./build/install/examples/bin/hello-world-server
|
||||||
```
|
```
|
||||||
|
|
||||||
3. In another terminal, run the client
|
3. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./build/install/examples/bin/hello-world-client
|
$ ./build/install/examples/bin/hello-world-client
|
||||||
|
|
@ -103,7 +101,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Update and run the application
|
### Update and run the application
|
||||||
|
|
||||||
|
|
@ -172,19 +170,19 @@ public void greet(String name) {
|
||||||
|
|
||||||
Just like we did before, from the `examples` directory:
|
Just like we did before, from the `examples` directory:
|
||||||
|
|
||||||
1. Compile the client and server
|
1. Compile the client and server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./gradlew installDist
|
$ ./gradlew installDist
|
||||||
```
|
```
|
||||||
|
|
||||||
2. Run the server
|
2. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./build/install/examples/bin/hello-world-server
|
$ ./build/install/examples/bin/hello-world-server
|
||||||
```
|
```
|
||||||
|
|
||||||
3. In another terminal, run the client
|
3. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./build/install/examples/bin/hello-world-client
|
$ ./build/install/examples/bin/hello-world-client
|
||||||
|
|
@ -197,4 +195,3 @@ Just like we did before, from the `examples` directory:
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: Java](/docs/tutorials/basic/java/).
|
- Work through a more detailed tutorial in [gRPC Basics: Java](/docs/tutorials/basic/java/).
|
||||||
- Explore the gRPC Java core API in its [reference
|
- Explore the gRPC Java core API in its [reference
|
||||||
documentation](/grpc-java/javadoc/).
|
documentation](/grpc-java/javadoc/).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,25 +7,23 @@ description: This guide gets you started with gRPC in Node with a simple working
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
### Before you begin
|
### Prerequisites
|
||||||
|
|
||||||
#### Prerequisites
|
- Node version 4.0.0 or higher
|
||||||
|
|
||||||
* `node`: version 4.0.0 or higher
|
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # Clone the repository to get the example code
|
# Clone the repository to get the example code
|
||||||
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
||||||
$ # Navigate to the dynamic codegen "hello, world" Node example:
|
# Navigate to the dynamic codegen "hello, world" Node example:
|
||||||
$ cd grpc/examples/node/dynamic_codegen
|
$ cd grpc/examples/node/dynamic_codegen
|
||||||
$ # Install the example's dependencies
|
# Install the example's dependencies
|
||||||
$ npm install
|
$ npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -33,13 +31,13 @@ $ npm install
|
||||||
|
|
||||||
From the `examples/node/dynamic_codegen` directory:
|
From the `examples/node/dynamic_codegen` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ node greeter_server.js
|
$ node greeter_server.js
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In another terminal, run the client
|
2. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ node greeter_client.js
|
$ node greeter_client.js
|
||||||
|
|
@ -100,7 +98,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Update and run the application
|
### Update and run the application
|
||||||
|
|
||||||
|
|
@ -128,7 +126,6 @@ function main() {
|
||||||
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
|
server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
|
||||||
server.start();
|
server.start();
|
||||||
}
|
}
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Update the client
|
#### Update the client
|
||||||
|
|
@ -152,13 +149,13 @@ function main() {
|
||||||
|
|
||||||
Just like we did before, from the `examples/node/dynamic_codegen` directory:
|
Just like we did before, from the `examples/node/dynamic_codegen` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ node greeter_server.js
|
$ node greeter_server.js
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In another terminal, run the client
|
2. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ node greeter_client.js
|
$ node greeter_client.js
|
||||||
|
|
@ -167,8 +164,8 @@ Just like we did before, from the `examples/node/dynamic_codegen` directory:
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: Node](/docs/tutorials/basic/node/)
|
- Work through a more detailed tutorial in [gRPC Basics: Node](/docs/tutorials/basic/node/).
|
||||||
- Explore the gRPC Node core API in its [reference
|
- Explore the gRPC Node core API in its [reference
|
||||||
documentation](/grpc/node/)
|
documentation](/grpc/node/).
|
||||||
- We do have more than one grpc implementation for nodejs. [Learn about the pros and cons of each here](https://github.com/grpc/grpc-node/blob/master/PACKAGE-COMPARISON.md).
|
- We do have more than one grpc implementation for nodejs. [Learn about the pros and cons of each here](https://github.com/grpc/grpc-node/blob/master/PACKAGE-COMPARISON.md).
|
||||||
|
|
|
||||||
|
|
@ -9,43 +9,42 @@ description: This guide gets you started with gRPC on the iOS platform in Object
|
||||||
|
|
||||||
### Before you begin
|
### Before you begin
|
||||||
|
|
||||||
#### System requirement
|
#### System requirements
|
||||||
The minimum deployment iOS version for gRPC is 7.0.
|
|
||||||
|
|
||||||
OS X El Capitan (version 10.11) or above is required to build and run this
|
- macOS version 10.11 (El Capitan) or higher
|
||||||
Quickstart.
|
- iOS version 7.0 or higher
|
||||||
|
|
||||||
#### Prerequisites
|
#### Prerequisites
|
||||||
|
|
||||||
* `CocoaPods`: version 1.0 or higher
|
- CocoaPods version 1.0 or higher
|
||||||
|
|
||||||
* Check status and version of CocoaPods on your system with command `pod
|
Check the status and version of CocoaPods on your system:
|
||||||
--version`.
|
|
||||||
* If CocoaPods is not installed, follow the install instructions on CocoaPods
|
|
||||||
[website](https://cocoapods.org).
|
|
||||||
|
|
||||||
* `Xcode`: version 7.2 or higher
|
```sh
|
||||||
|
$ pod --version
|
||||||
|
```
|
||||||
|
|
||||||
* Check your Xcode version by running Xcode from Lauchpad, then select
|
If CocoaPods is not installed, follow the [CocoaPods install
|
||||||
"Xcode->About Xcode" in the menu.
|
instructions](https://cocoapods.org).
|
||||||
* Make sure the command line developer tools are installed:
|
|
||||||
```sh
|
|
||||||
[sudo] xcode-select --install
|
|
||||||
```
|
|
||||||
|
|
||||||
* `Homebrew`
|
- Xcode version 7.2 or higher
|
||||||
* Check status and version of Homebrew on your system with command `brew
|
|
||||||
--version`.
|
|
||||||
* If Homebrew is not installed, install with:
|
|
||||||
```sh
|
|
||||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
|
||||||
```
|
|
||||||
|
|
||||||
* `autoconf`, `automake`, `libtool`, `pkg-config`
|
Check your Xcode version by running Xcode from Lauchpad, then select
|
||||||
* Install with Homebrew
|
**Xcode > About Xcode** in the menu.
|
||||||
```sh
|
|
||||||
brew install autoconf automake libtool pkg-config
|
Make sure the command line developer tools are installed:
|
||||||
```
|
|
||||||
|
```sh
|
||||||
|
$ xcode-select --install
|
||||||
|
```
|
||||||
|
|
||||||
|
- [Homebrew](https://brew.sh/)
|
||||||
|
|
||||||
|
- `autoconf`, `automake`, `libtool`, `pkg-config`
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ brew install autoconf automake libtool pkg-config
|
||||||
|
```
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
|
|
@ -58,6 +57,7 @@ $ git clone --recursive -b {{< param grpc_release_tag >}} https://github.com/grp
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install gRPC plugins and libraries
|
### Install gRPC plugins and libraries
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ cd grpc
|
$ cd grpc
|
||||||
$ make
|
$ make
|
||||||
|
|
@ -65,12 +65,13 @@ $ [sudo] make install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install protoc compiler
|
### Install protoc compiler
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ brew tap grpc/grpc
|
$ brew tap grpc/grpc
|
||||||
$ brew install protobuf
|
$ brew install protobuf
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run the server
|
### Run the server:
|
||||||
|
|
||||||
For this sample app, we need a gRPC server running on the local machine. gRPC
|
For this sample app, we need a gRPC server running on the local machine. gRPC
|
||||||
Objective-C API supports creating gRPC clients but not gRPC servers. Therefore
|
Objective-C API supports creating gRPC clients but not gRPC servers. Therefore
|
||||||
|
|
@ -82,7 +83,7 @@ $ make
|
||||||
$ ./greeter_server &
|
$ ./greeter_server &
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run the client
|
### Run the client:
|
||||||
|
|
||||||
#### Generate client libraries and dependencies
|
#### Generate client libraries and dependencies
|
||||||
|
|
||||||
|
|
@ -126,7 +127,7 @@ 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
|
RPC method that takes a `HelloRequest` parameter from the client and returns a
|
||||||
`HelloResponse` from the server, and that this method is defined like this:
|
`HelloResponse` from the server, and that this method is defined like this:
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
// The greeting service definition.
|
// The greeting service definition.
|
||||||
service Greeter {
|
service Greeter {
|
||||||
// Sends a greeting
|
// Sends a greeting
|
||||||
|
|
@ -148,7 +149,7 @@ Let's update this so that the `Greeter` service has two methods. Edit
|
||||||
`examples/protos/helloworld.proto` and update it with a new `SayHelloAgain`
|
`examples/protos/helloworld.proto` and update it with a new `SayHelloAgain`
|
||||||
method, with the same request and response types:
|
method, with the same request and response types:
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
// The greeting service definition.
|
// The greeting service definition.
|
||||||
service Greeter {
|
service Greeter {
|
||||||
// Sends a greeting
|
// Sends a greeting
|
||||||
|
|
@ -168,7 +169,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Update the client and server
|
### Update the client and server
|
||||||
|
|
||||||
|
|
@ -258,59 +259,63 @@ above. Open the client Xcode project in Xcode:
|
||||||
```sh
|
```sh
|
||||||
$ open HelloWorld.xcworkspace
|
$ open HelloWorld.xcworkspace
|
||||||
```
|
```
|
||||||
and run the client app. If you look at the console messages, you should see two RPC calls,
|
|
||||||
|
and run the client app. If you look at the console messages, You'll see two RPC calls,
|
||||||
one to SayHello and one to SayHelloAgain.
|
one to SayHello and one to SayHelloAgain.
|
||||||
|
|
||||||
### Troubleshooting
|
### Troubleshooting
|
||||||
|
|
||||||
**When installing CocoaPods, error prompt `activesupport requires Ruby version >= 2.2.2.`**
|
When installing CocoaPods, error `activesupport requires Ruby version >= 2.2.2`
|
||||||
|
|
||||||
Install an older version of `activesupport`, then install CocoaPods:
|
: Install an older version of `activesupport`, then install CocoaPods:
|
||||||
```sh
|
|
||||||
[sudo] gem install activesupport -v 4.2.6
|
|
||||||
[sudo] gem install cocoapods
|
|
||||||
```
|
|
||||||
**When installing dependencies with CocoaPods, error prompt `Unable to find a specification for !ProtoCompiler-gRPCPlugin`**
|
|
||||||
|
|
||||||
Update the local clone of spec repo by running `pod repo update`
|
```sh
|
||||||
|
$ [sudo] gem install activesupport -v 4.2.6
|
||||||
|
$ [sudo] gem install cocoapods
|
||||||
|
```
|
||||||
|
|
||||||
**Compiler error when compiling `objective_c_plugin.cc`**
|
When installing dependencies with CocoaPods, error `Unable to find a specification for !ProtoCompiler-gRPCPlugin`
|
||||||
|
|
||||||
Removing `protobuf` package with Homebrew before building gRPC may solve
|
: Update the local clone of spec repo by running `pod repo update`
|
||||||
this problem. We are working on a more elegant fix.
|
|
||||||
|
|
||||||
**When building HellowWorld, error prompt `ld: unknown option: --no-as-needed`**
|
Compiler error when compiling `objective_c_plugin.cc`
|
||||||
|
|
||||||
This problem is due to linker `ld` in Apple LLVM not supporting the
|
: Removing `protobuf` package with Homebrew before building gRPC may solve this
|
||||||
--no-as-needed option. We are working on a fix right now and will merge the fix
|
problem. We are working on a more elegant fix.
|
||||||
very soon.
|
|
||||||
|
|
||||||
**When building grpc, error prompt `cannot find install-sh install.sh or shtool`**
|
When building HellowWorld, error `ld: unknown option: --no-as-needed`
|
||||||
|
|
||||||
Remove the gRPC directory, clone a new one and try again. It is likely that some
|
: This problem is due to linker `ld` in Apple LLVM not supporting the
|
||||||
auto generated files are corrupt; remove and rebuild may solve the problem.
|
`--no-as-needed` option. We are working on a fix right now and will merge the
|
||||||
|
fix very soon.
|
||||||
|
|
||||||
**When building grpc, error prompt `Can't exec "aclocal"`**
|
When building grpc, error `cannot find install-sh install.sh or shtool`
|
||||||
|
|
||||||
The package `automake` is missing. Install `automake` should solve this problem.
|
: Remove the gRPC directory, clone a new one and try again. It is likely that
|
||||||
|
some auto generated files are corrupt; remove and rebuild may solve the
|
||||||
|
problem.
|
||||||
|
|
||||||
**When building grpc, error prompt `possibly undefined macro: AC_PROG_LIBTOOL`**
|
When building grpc, error `Can't exec "aclocal"`
|
||||||
|
|
||||||
The package `libtool` is missing. Install `libtool` should solve this problem.
|
: The package `automake` is missing. Install `automake` should solve this problem.
|
||||||
|
|
||||||
**When building grpc, error prompt `cannot find install-sh, install.sh, or shtool`**
|
When building grpc, error `possibly undefined macro: AC_PROG_LIBTOOL`
|
||||||
|
|
||||||
Some of the auto generated files are corrupt. Remove the entire gRPC directory,
|
: The package `libtool` is missing. Install `libtool` should solve this problem.
|
||||||
clone from GitHub, and build again.
|
|
||||||
|
|
||||||
**Cannot find `protoc` when building HelloWorld**
|
When building grpc, error `cannot find install-sh, install.sh, or shtool`
|
||||||
|
|
||||||
Run `brew install protobuf` to get `protoc` compiler.
|
: Some of the auto generated files are corrupt. Remove the entire gRPC
|
||||||
|
directory, clone from GitHub, and build again.
|
||||||
|
|
||||||
|
Cannot find `protoc` when building HelloWorld
|
||||||
|
|
||||||
|
: Run `brew install protobuf` to get the `protoc` compiler.
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: Objective-C](/docs/tutorials/basic/objective-c/)
|
- Work through a more detailed tutorial in [gRPC Basics: Objective-C](/docs/tutorials/basic/objective-c/).
|
||||||
- Explore the Objective-C core API in its [reference
|
- Explore the Objective-C core API in its [reference
|
||||||
documentation](http://cocoadocs.org/docsets/gRPC/)
|
documentation](http://cocoadocs.org/docsets/gRPC/).
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,10 @@ description: This guide gets you started with gRPC in PHP with a simple working
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
* `php` 5.5 or above, 7.0 or above
|
- PHP 5.5 or higher, 7.0 or higher
|
||||||
* `pecl`
|
- PECL
|
||||||
* `composer`
|
- Composer
|
||||||
* `phpunit` (optional)
|
- PHPUnit (optional)
|
||||||
|
|
||||||
**Install PHP and PECL on Ubuntu/Debian:**
|
**Install PHP and PECL on Ubuntu/Debian:**
|
||||||
|
|
||||||
|
|
@ -65,9 +65,10 @@ $ sudo mv phpunit-old.phar /usr/bin/phpunit
|
||||||
|
|
||||||
### Install the gRPC PHP extension
|
### Install the gRPC PHP extension
|
||||||
|
|
||||||
There are two ways to install gRPC PHP extension.
|
There are two ways to install gRPC PHP extension:
|
||||||
* `pecl`
|
|
||||||
* `build from source`
|
- `pecl`
|
||||||
|
- `build from source`
|
||||||
|
|
||||||
#### Using PECL
|
#### Using PECL
|
||||||
|
|
||||||
|
|
@ -150,9 +151,9 @@ need the `composer` and `protoc` binaries. You can find out how to get these bel
|
||||||
|
|
||||||
### Install other prerequisites for both Mac OS X and Linux
|
### Install other prerequisites for both Mac OS X and Linux
|
||||||
|
|
||||||
* `protoc: protobuf compiler`
|
- `protoc: protobuf compiler`
|
||||||
* `protobuf.so: protobuf runtime library`
|
- `protobuf.so: protobuf runtime library`
|
||||||
* `grpc_php_plugin: Generates PHP gRPC service interface out of Protobuf IDL`
|
- `grpc_php_plugin: Generates PHP gRPC service interface out of Protobuf IDL`
|
||||||
|
|
||||||
#### Install Protobuf compiler
|
#### Install Protobuf compiler
|
||||||
|
|
||||||
|
|
@ -200,7 +201,7 @@ in terms of APIs offered. The C implementation provides better performance,
|
||||||
while the native implementation is easier to install. Make sure the installed
|
while the native implementation is easier to install. Make sure the installed
|
||||||
protobuf version works with grpc version.
|
protobuf version works with grpc version.
|
||||||
|
|
||||||
##### 1. C implementation (for better performance)
|
##### C implementation (for better performance)
|
||||||
|
|
||||||
``` sh
|
``` sh
|
||||||
$ sudo pecl install protobuf
|
$ sudo pecl install protobuf
|
||||||
|
|
@ -220,7 +221,7 @@ depending on where your PHP installation is.
|
||||||
extension=protobuf.so
|
extension=protobuf.so
|
||||||
```
|
```
|
||||||
|
|
||||||
##### 2. PHP implementation (for easier installation)
|
##### PHP implementation (for easier installation)
|
||||||
|
|
||||||
Add this to your `composer.json` file:
|
Add this to your `composer.json` file:
|
||||||
|
|
||||||
|
|
@ -255,9 +256,9 @@ you build this plugin.
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
Note that currently you can only create clients in PHP for gRPC services -
|
Note that currently you can only create clients in PHP for gRPC services -
|
||||||
|
|
@ -265,11 +266,11 @@ you can find out how to create gRPC servers in our other tutorials,
|
||||||
e.g. [Node.js](/docs/tutorials/basic/node/).
|
e.g. [Node.js](/docs/tutorials/basic/node/).
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # Clone the repository to get the example code:
|
# Clone the repository to get the example code:
|
||||||
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
||||||
$ # Build grpc_php_plugin to generate proto files if not build before
|
# Build grpc_php_plugin to generate proto files if not build before
|
||||||
$ cd grpc && git submodule update --init && make grpc_php_plugin
|
$ cd grpc && git submodule update --init && make grpc_php_plugin
|
||||||
$ # Navigate to the "hello, world" PHP example:
|
# Navigate to the "hello, world" PHP example:
|
||||||
$ cd examples/php
|
$ cd examples/php
|
||||||
$ ./greeter_proto_gen.sh
|
$ ./greeter_proto_gen.sh
|
||||||
$ composer install
|
$ composer install
|
||||||
|
|
@ -279,21 +280,20 @@ $ composer install
|
||||||
|
|
||||||
From the `examples/node` directory:
|
From the `examples/node` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ npm install
|
$ npm install
|
||||||
$ cd dynamic_codegen
|
$ cd dynamic_codegen
|
||||||
$ node greeter_server.js
|
$ node greeter_server.js
|
||||||
```
|
```
|
||||||
|
|
||||||
In another terminal, from the `examples/php` directory:
|
2. From another terminal, from the `examples/php` directory,
|
||||||
|
run the client:
|
||||||
|
|
||||||
1. Run the client
|
```sh
|
||||||
|
$ ./run_greeter_client.sh
|
||||||
```sh
|
```
|
||||||
$ ./run_greeter_client.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Congratulations! You've just run a client-server application with gRPC.
|
Congratulations! You've just run a client-server application with gRPC.
|
||||||
|
|
||||||
|
|
@ -308,7 +308,7 @@ server and the client "stub" have a `SayHello` RPC method that takes a
|
||||||
the server, and that this method is defined like this:
|
the server, and that this method is defined like this:
|
||||||
|
|
||||||
|
|
||||||
```php
|
```protobuf
|
||||||
// The greeting service definition.
|
// The greeting service definition.
|
||||||
service Greeter {
|
service Greeter {
|
||||||
// Sends a greeting
|
// Sends a greeting
|
||||||
|
|
@ -330,7 +330,7 @@ Let's update this so that the `Greeter` service has two methods. Edit
|
||||||
`examples/protos/helloworld.proto` and update it with a new `SayHelloAgain`
|
`examples/protos/helloworld.proto` and update it with a new `SayHelloAgain`
|
||||||
method, with the same request and response types:
|
method, with the same request and response types:
|
||||||
|
|
||||||
```php
|
```protobuf
|
||||||
// The greeting service definition.
|
// The greeting service definition.
|
||||||
service Greeter {
|
service Greeter {
|
||||||
// Sends a greeting
|
// Sends a greeting
|
||||||
|
|
@ -350,7 +350,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Generate gRPC code
|
### Generate gRPC code
|
||||||
|
|
||||||
|
|
@ -410,36 +410,35 @@ function main() {
|
||||||
In the same directory, open `greeter_client.php`. Call the new method like this:
|
In the same directory, open `greeter_client.php`. Call the new method like this:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
$request = new Helloworld\HelloRequest();
|
$request = new Helloworld\HelloRequest();
|
||||||
$request->setName($name);
|
$request->setName($name);
|
||||||
list($reply, $status) = $client->SayHello($request)->wait();
|
list($reply, $status) = $client->SayHello($request)->wait();
|
||||||
$message = $reply->getMessage();
|
$message = $reply->getMessage();
|
||||||
list($reply, $status) = $client->SayHelloAgain($request)->wait();
|
list($reply, $status) = $client->SayHelloAgain($request)->wait();
|
||||||
$message = $reply->getMessage();
|
$message = $reply->getMessage();
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Run!
|
#### Run!
|
||||||
|
|
||||||
Just like we did before, from the `examples/node/dynamic_codegen` directory:
|
Just like we did before, from the `examples/node/dynamic_codegen` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ node greeter_server.js
|
$ node greeter_server.js
|
||||||
```
|
```
|
||||||
|
|
||||||
In another terminal, from the `examples/php` directory:
|
2. From another terminal, from the `examples/php` directory,
|
||||||
|
run the client:
|
||||||
|
|
||||||
2. Run the client
|
```sh
|
||||||
|
$ ./run_greeter_client.sh
|
||||||
```sh
|
```
|
||||||
$ ./run_greeter_client.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: PHP](/docs/tutorials/basic/php/)
|
- Work through a more detailed tutorial in [gRPC Basics: PHP](/docs/tutorials/basic/php/).
|
||||||
- Explore the gRPC PHP core API in its [reference
|
- Explore the gRPC PHP core API in its [reference
|
||||||
documentation](/grpc/php/namespace-Grpc.html)
|
documentation](/grpc/php/namespace-Grpc.html).
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,12 @@ description: This guide gets you started with gRPC in Python with a simple worki
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
### Before you begin
|
### Prerequisites
|
||||||
|
|
||||||
#### Prerequisites
|
- Python 2.7, or Python 3.4 or higher
|
||||||
|
- `pip` version 9.0.1 or higher
|
||||||
|
|
||||||
gRPC Python is supported for use with Python 2.7 or Python 3.4 or higher.
|
If necessary, upgrade your version of `pip`:
|
||||||
|
|
||||||
Ensure you have `pip` version 9.0.1 or higher:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ python -m pip install --upgrade pip
|
$ python -m pip install --upgrade pip
|
||||||
|
|
@ -29,7 +28,7 @@ $ source venv/bin/activate
|
||||||
$ python -m pip install --upgrade pip
|
$ python -m pip install --upgrade pip
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Install gRPC
|
#### gRPC
|
||||||
|
|
||||||
Install gRPC:
|
Install gRPC:
|
||||||
|
|
||||||
|
|
@ -55,14 +54,14 @@ You can work around this using:
|
||||||
$ python -m pip install grpcio --ignore-installed
|
$ python -m pip install grpcio --ignore-installed
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Install gRPC tools
|
#### gRPC tools
|
||||||
|
|
||||||
Python's gRPC tools include the protocol buffer compiler `protoc` and the
|
Python's gRPC tools include the protocol buffer compiler `protoc` and the
|
||||||
special plugin for generating server and client code from `.proto` service
|
special plugin for generating server and client code from `.proto` service
|
||||||
definitions. For the first part of our quickstart example, we've already
|
definitions. For the first part of our quick-start example, we've already
|
||||||
generated the server and client stubs from
|
generated the server and client stubs from
|
||||||
[helloworld.proto](https://github.com/grpc/grpc/tree/{{< param grpc_release_tag >}}/examples/protos/helloworld.proto),
|
[helloworld.proto](https://github.com/grpc/grpc/tree/{{< param grpc_release_tag >}}/examples/protos/helloworld.proto),
|
||||||
but you'll need the tools for the rest of our quickstart, as well as later
|
but you'll need the tools for the rest of our quick start, as well as later
|
||||||
tutorials and your own projects.
|
tutorials and your own projects.
|
||||||
|
|
||||||
To install gRPC tools, run:
|
To install gRPC tools, run:
|
||||||
|
|
@ -73,15 +72,15 @@ $ python -m pip install grpcio-tools
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # Clone the repository to get the example code:
|
# Clone the repository to get the example code:
|
||||||
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
||||||
$ # Navigate to the "hello, world" Python example:
|
# Navigate to the "hello, world" Python example:
|
||||||
$ cd grpc/examples/python/helloworld
|
$ cd grpc/examples/python/helloworld
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -89,13 +88,13 @@ $ cd grpc/examples/python/helloworld
|
||||||
|
|
||||||
From the `examples/python/helloworld` directory:
|
From the `examples/python/helloworld` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ python greeter_server.py
|
$ python greeter_server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In another terminal, run the client
|
2. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ python greeter_client.py
|
$ python greeter_client.py
|
||||||
|
|
@ -156,7 +155,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Generate gRPC code
|
### Generate gRPC code
|
||||||
|
|
||||||
|
|
@ -212,22 +211,22 @@ def run():
|
||||||
|
|
||||||
Just like we did before, from the `examples/python/helloworld` directory:
|
Just like we did before, from the `examples/python/helloworld` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ python greeter_server.py
|
$ python greeter_server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In another terminal, run the client
|
2. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ python greeter_client.py
|
$ python greeter_client.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: Python](/docs/tutorials/basic/python/)
|
- Work through a more detailed tutorial in [gRPC Basics: Python](/docs/tutorials/basic/python/).
|
||||||
- Explore the gRPC Python core API in its [reference
|
- Explore the gRPC Python core API in its [reference
|
||||||
documentation](/grpc/python/)
|
documentation](/grpc/python/).
|
||||||
|
|
|
||||||
|
|
@ -7,45 +7,45 @@ description: This guide gets you started with gRPC in Ruby with a simple working
|
||||||
|
|
||||||
<div id="toc"></div>
|
<div id="toc"></div>
|
||||||
|
|
||||||
### Before you begin
|
### Prerequisites
|
||||||
|
|
||||||
#### Prerequisites
|
- Ruby version 2 or higher
|
||||||
|
|
||||||
* `ruby`: version 2 or higher
|
#### gRPC
|
||||||
|
|
||||||
#### Install gRPC
|
To install gRPC, run the following command:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ gem install grpc
|
$ gem install grpc
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Install gRPC tools
|
#### gRPC tools
|
||||||
|
|
||||||
Ruby's gRPC tools include the protocol buffer compiler `protoc` and the special
|
Ruby's gRPC tools include the protocol buffer compiler `protoc` and the special
|
||||||
plugin for generating server and client code from the `.proto` service
|
plugin for generating server and client code from the `.proto` service
|
||||||
definitions. For the first part of our quickstart example, we've already
|
definitions. For the first part of our quick-start example, we've already
|
||||||
generated the server and client stubs from
|
generated the server and client stubs from
|
||||||
[helloworld.proto](https://github.com/grpc/grpc/tree/{{< param grpc_release_tag >}}/examples/protos/helloworld.proto),
|
[helloworld.proto](https://github.com/grpc/grpc/tree/{{< param grpc_release_tag >}}/examples/protos/helloworld.proto),
|
||||||
but you'll need the tools for the rest of our quickstart, as well as later
|
but you'll need the tools for the rest of our quick start, as well as later
|
||||||
tutorials and your own projects.
|
tutorials and your own projects.
|
||||||
|
|
||||||
To install gRPC tools, run:
|
To install gRPC tools, run the following command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
gem install grpc-tools
|
$ gem install grpc-tools
|
||||||
```
|
```
|
||||||
|
|
||||||
### Download the example
|
### Download the example
|
||||||
|
|
||||||
You'll need a local copy of the example code to work through this quickstart.
|
You'll need a local copy of the example code to work through this quick start.
|
||||||
Download the example code from our GitHub repository (the following command
|
Download the example code from our GitHub repository (the following command
|
||||||
clones the entire repository, but you just need the examples for this quickstart
|
clones the entire repository, but you just need the examples for this quick start
|
||||||
and other tutorials):
|
and other tutorials):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # Clone the repository to get the example code:
|
# Clone the repository to get the example code:
|
||||||
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
$ git clone -b {{< param grpc_release_tag >}} https://github.com/grpc/grpc
|
||||||
$ # Navigate to the "hello, world" Ruby example:
|
# Navigate to the "hello, world" Ruby example:
|
||||||
$ cd grpc/examples/ruby
|
$ cd grpc/examples/ruby
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -53,17 +53,17 @@ $ cd grpc/examples/ruby
|
||||||
|
|
||||||
From the `examples/ruby` directory:
|
From the `examples/ruby` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ruby greeter_server.rb
|
$ ruby greeter_server.rb
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In another terminal, run the client
|
2. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ruby greeter_client.rb
|
$ ruby greeter_client.rb
|
||||||
```
|
```
|
||||||
|
|
||||||
Congratulations! You've just run a client-server application with gRPC.
|
Congratulations! You've just run a client-server application with gRPC.
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@ message HelloReply {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
(Don't forget to save the file!)
|
Remember to save the file!
|
||||||
|
|
||||||
### Generate gRPC code
|
### Generate gRPC code
|
||||||
|
|
||||||
|
|
@ -149,7 +149,6 @@ class GreeterServer < Helloworld::Greeter::Service
|
||||||
Helloworld::HelloReply.new(message: "Hello again, #{hello_req.name}")
|
Helloworld::HelloReply.new(message: "Hello again, #{hello_req.name}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
...
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Update the client
|
#### Update the client
|
||||||
|
|
@ -171,22 +170,22 @@ end
|
||||||
|
|
||||||
Just like we did before, from the `examples/ruby` directory:
|
Just like we did before, from the `examples/ruby` directory:
|
||||||
|
|
||||||
1. Run the server
|
1. Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ruby greeter_server.rb
|
$ ruby greeter_server.rb
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In another terminal, run the client
|
2. From another terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ruby greeter_client.rb
|
$ ruby greeter_client.rb
|
||||||
```
|
```
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
- Read a full explanation of how gRPC works in [What is gRPC?](/docs/guides/)
|
||||||
and [gRPC Concepts](/docs/guides/concepts/)
|
and [gRPC Concepts](/docs/guides/concepts/).
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: Ruby](/docs/tutorials/basic/ruby/)
|
- Work through a more detailed tutorial in [gRPC Basics: Ruby](/docs/tutorials/basic/ruby/).
|
||||||
- Explore the gRPC Ruby core API in its [reference
|
- Explore the gRPC Ruby core API in its [reference
|
||||||
documentation](http://www.rubydoc.info/gems/grpc)
|
documentation](http://www.rubydoc.info/gems/grpc).
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,14 @@ description: This guide gets you started with gRPC-Web with a simple working exa
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
* `docker` and `docker-compose`
|
- `docker`
|
||||||
|
- `docker-compose`
|
||||||
|
|
||||||
This demo requires Docker Compose file
|
This demo requires Docker Compose file
|
||||||
[version 3](https://docs.docker.com/compose/compose-file/). Please refer to
|
[version 3](https://docs.docker.com/compose/compose-file/). Please refer to
|
||||||
[Docker website](https://docs.docker.com/compose/install/#install-compose) on how to install Docker.
|
[Docker website](https://docs.docker.com/compose/install/#install-compose) on how to install Docker.
|
||||||
|
|
||||||
### Run an Echo example from the browser!
|
### Run an Echo example from your browser!
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ git clone https://github.com/grpc/grpc-web
|
$ git clone https://github.com/grpc/grpc-web
|
||||||
|
|
@ -24,35 +25,30 @@ $ docker-compose pull
|
||||||
$ docker-compose up -d node-server envoy commonjs-client
|
$ docker-compose up -d node-server envoy commonjs-client
|
||||||
```
|
```
|
||||||
|
|
||||||
Open a browser tab, and go to:
|
From your browser visit
|
||||||
|
[localhost:8081/echotest.html](http://localhost:8081/echotest.html).
|
||||||
```sh
|
|
||||||
http://localhost:8081/echotest.html
|
|
||||||
```
|
|
||||||
|
|
||||||
To shutdown, run `docker-compose down`.
|
To shutdown, run `docker-compose down`.
|
||||||
|
|
||||||
|
|
||||||
### What is Happening?
|
### What is happening?
|
||||||
|
|
||||||
In this demo, there are three key components:
|
In this demo, there are three key components:
|
||||||
|
|
||||||
1. `node-server`: This is a standard gRPC Server, implemented in Node.
|
1. `node-server`: This is a standard gRPC Server, implemented in Node. This
|
||||||
This server listens at port `:9090` and implements the service's business
|
server listens at port `:9090` and implements the service's business logic.
|
||||||
logic.
|
|
||||||
|
|
||||||
2. `envoy`: This is the Envoy proxy. It listens at `:8080` and forwards the
|
2. `envoy`: This is the Envoy proxy. It listens at `:8080` and forwards the
|
||||||
browser's gRPC-Web requests to port `:9090`. This is done via a config file
|
browser's gRPC-Web requests to port `:9090`. This is done via a config file
|
||||||
`envoy.yaml`.
|
`envoy.yaml`.
|
||||||
|
|
||||||
3. `commonjs-client`: This component generates the client stub class using
|
3. `commonjs-client`: This component generates the client stub class using the
|
||||||
the `protoc-gen-grpc-web` protoc plugin, compiles all the JS dependencies
|
`protoc-gen-grpc-web` protoc plugin, compiles all the JS dependencies using
|
||||||
using `webpack`, and hosts the static content `echotest.html` and
|
`webpack`, and hosts the static content `echotest.html` and `dist/main.js`
|
||||||
`dist/main.js` using a simple web server at port `:8081`. Once the user
|
using a simple web server at port `:8081`. Once the user interacts with the
|
||||||
interacts with the webpage, it sends a gRPC-Web request to the Envoy proxy
|
webpage, it sends a gRPC-Web request to the Envoy proxy endpoint at `:8080`.
|
||||||
endpoint at `:8080`.
|
|
||||||
|
|
||||||
|
|
||||||
### What's next
|
### What's next
|
||||||
|
|
||||||
- Work through a more detailed tutorial in [gRPC Basics: Web](/docs/tutorials/basic/web/)
|
- Work through a more detailed tutorial in [gRPC Basics: Web](/docs/tutorials/basic/web/).
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,7 @@ To use this approach, first create a class in your project that conforms to
|
||||||
```
|
```
|
||||||
|
|
||||||
When creating an RPC object, pass an instance of this class to call option `authTokenProvider`:
|
When creating an RPC object, pass an instance of this class to call option `authTokenProvider`:
|
||||||
|
|
||||||
```objective-c
|
```objective-c
|
||||||
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
|
GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init];
|
||||||
options.authTokenProvider = [[TokenProvider alloc] init];
|
options.authTokenProvider = [[TokenProvider alloc] init];
|
||||||
|
|
|
||||||
|
|
@ -63,40 +63,58 @@ service RouteGuide {
|
||||||
|
|
||||||
Then we define `rpc` methods inside our service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service:
|
Then we define `rpc` methods inside our service definition, specifying their request and response types. gRPC lets you define four kinds of service method, all of which are used in the `RouteGuide` service:
|
||||||
|
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub and waits for a response to come back, just like a normal function call.
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server and gets a stream to read a sequence of messages back. The client reads from the returned stream until there are no more messages. As you can see in our example, you specify a server-side streaming method by placing the `stream` keyword before the *response* type.
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
the returned stream until there are no more messages. As you can see in our
|
||||||
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
|
keyword before the *response* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages and sends them to the server, again using a provided stream. Once the client has finished writing the messages, it waits for the server to read them all and return its response. You specify a client-side streaming method by placing the `stream` keyword before the *request* type.
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
has finished writing the messages, it waits for the server to read them all
|
||||||
|
and return its response. You specify a client-side streaming method by placing
|
||||||
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages using a read-write stream. The two streams operate independently, so clients and servers can read and write in whatever order they like: for example, the server could wait to receive all the client messages before writing its responses, or it could alternately read a message then write a message, or some other combination of reads and writes. The order of messages in each stream is preserved. You specify this type of method by placing the `stream` keyword before both the request and the response.
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
and servers can read and write in whatever order they like: for example, the
|
||||||
|
server could wait to receive all the client messages before writing its
|
||||||
|
responses, or it could alternately read a message then write a message, or
|
||||||
|
some other combination of reads and writes. The order of messages in each
|
||||||
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type:
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
|
the request and response types used in our service methods - for example, here's
|
||||||
|
the `Point` message type:
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Points are represented as latitude-longitude pairs in the E7 representation
|
// Points are represented as latitude-longitude pairs in the E7 representation
|
||||||
|
|
@ -109,7 +127,6 @@ message Point {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Generating client code
|
### Generating client code
|
||||||
|
|
||||||
Next we need to generate the gRPC client interfaces from our .proto
|
Next we need to generate the gRPC client interfaces from our .proto
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ You can see the complete .proto file in
|
||||||
|
|
||||||
To define a service, you specify a named `service` in your .proto file:
|
To define a service, you specify a named `service` in your .proto file:
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
service RouteGuide {
|
service RouteGuide {
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
@ -87,10 +87,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
and waits for a response to come back, just like a normal function call.
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
and gets a stream to read a sequence of messages back. The client reads from
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
|
@ -98,13 +98,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a server-side streaming method by placing the `stream`
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
and sends them to the server, again using a provided stream. Once the client
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
|
@ -112,11 +112,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
and return its response. You specify a client-side streaming method by placing
|
and return its response. You specify a client-side streaming method by placing
|
||||||
the `stream` keyword before the *request* type.
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -127,17 +127,17 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
```c
|
```protobuf
|
||||||
// Points are represented as latitude-longitude pairs in the E7 representation
|
// Points are represented as latitude-longitude pairs in the E7 representation
|
||||||
// (degrees multiplied by 10**7 and rounded to the nearest integer).
|
// (degrees multiplied by 10**7 and rounded to the nearest integer).
|
||||||
// Latitudes should be in the range +/- 90 degrees and longitude should be in
|
// Latitudes should be in the range +/- 90 degrees and longitude should be in
|
||||||
|
|
@ -148,7 +148,6 @@ message Point {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Generating client and server code
|
### Generating client and server code
|
||||||
|
|
||||||
Next we need to generate the gRPC client and server interfaces from our .proto
|
Next we need to generate the gRPC client and server interfaces from our .proto
|
||||||
|
|
@ -520,17 +519,19 @@ independently.
|
||||||
|
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
Build client and server:
|
Build the client and server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ make
|
$ make
|
||||||
```
|
```
|
||||||
Run the server, which will listen on port 50051:
|
|
||||||
|
Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./route_guide_server
|
$ ./route_guide_server
|
||||||
```
|
```
|
||||||
Run the client (in a different terminal):
|
|
||||||
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ ./route_guide_client
|
$ ./route_guide_client
|
||||||
|
|
|
||||||
|
|
@ -82,10 +82,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
object and waits for a response to come back, just like a normal function
|
object and waits for a response to come back, just like a normal function
|
||||||
call.
|
call.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
and gets a stream to read a sequence of messages back. The client reads from
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
|
@ -93,13 +93,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a server-side streaming method by placing the `stream`
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
and sends them to the server, again using a provided stream. Once the client
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
|
@ -107,11 +107,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
and return its response. You specify a client-side streaming method by placing
|
and return its response. You specify a client-side streaming method by placing
|
||||||
the `stream` keyword before the *request* type.
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -122,13 +122,13 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
|
|
@ -480,28 +480,27 @@ using (var call = client.RouteChat())
|
||||||
|
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
#### Build the client and server:
|
Build the client and server:
|
||||||
|
|
||||||
##### Using Visual Studio (or Visual Studio For Mac)
|
Using Visual Studio (or Visual Studio For Mac)
|
||||||
|
: Open the solution `examples/csharp/RouteGuide/RouteGuide.sln` and select **Build**.
|
||||||
|
|
||||||
- Open the solution `examples/csharp/RouteGuide/RouteGuide.sln` and select **Build**.
|
Using `dotnet` command line tool
|
||||||
|
|
||||||
##### Using "dotnet" command line tool
|
: Run `dotnet build RouteGuide.sln` from the `examples/csharp/RouteGuide`
|
||||||
|
directory. For additional instructions on building the gRPC example with the
|
||||||
|
`dotnet` command line tool, see [Quick Start](../../quickstart/csharp.html).
|
||||||
|
|
||||||
- Run `dotnet build RouteGuide.sln` from the `examples/csharp/RouteGuide` directory.
|
Run the server:
|
||||||
See the [quickstart](../../quickstart/csharp.html) for additional instructions on building
|
|
||||||
the gRPC example with the `dotnet` command line tool.
|
|
||||||
|
|
||||||
Run the server, which will listen on port 50052:
|
```sh
|
||||||
|
|
||||||
```
|
|
||||||
> cd RouteGuideServer/bin/Debug/netcoreapp2.1
|
> cd RouteGuideServer/bin/Debug/netcoreapp2.1
|
||||||
> dotnet exec RouteGuideServer.dll
|
> dotnet exec RouteGuideServer.dll
|
||||||
```
|
```
|
||||||
|
|
||||||
Run the client (in a different terminal):
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
> cd RouteGuideClient/bin/Debug/netcoreapp2.1
|
> cd RouteGuideClient/bin/Debug/netcoreapp2.1
|
||||||
> dotnet exec RouteGuideClient.dll
|
> dotnet exec RouteGuideClient.dll
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ $ cd grpc-dart/example/route_guide
|
||||||
|
|
||||||
You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Dart quick start guide](/docs/quickstart/dart/).
|
You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Dart quick start guide](/docs/quickstart/dart/).
|
||||||
|
|
||||||
|
|
||||||
### Defining the service
|
### Defining the service
|
||||||
|
|
||||||
Our first step (as you'll know from the [Overview](/docs/)) is to
|
Our first step (as you'll know from the [Overview](/docs/)) is to
|
||||||
|
|
@ -80,10 +79,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
and waits for a response to come back, just like a normal function call.
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
and gets a stream to read a sequence of messages back. The client reads from
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
|
@ -91,13 +90,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a server-side streaming method by placing the `stream`
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
and sends them to the server, again using a provided stream. Once the client
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
|
@ -105,11 +104,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
and return its response. You specify a client-side streaming method by placing
|
and return its response. You specify a client-side streaming method by placing
|
||||||
the `stream` keyword before the *request* type.
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -120,13 +119,15 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type:
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
|
the request and response types used in our service methods - for example, here's
|
||||||
|
the `Point` message type:
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Points are represented as latitude-longitude pairs in the E7 representation
|
// Points are represented as latitude-longitude pairs in the E7 representation
|
||||||
|
|
@ -146,7 +147,7 @@ service definition. We do this using the protocol buffer compiler `protoc` with
|
||||||
a special Dart plugin.
|
a special Dart plugin.
|
||||||
This is similar to what we did in the [quickstart guide](/docs/quickstart/)
|
This is similar to what we did in the [quickstart guide](/docs/quickstart/)
|
||||||
|
|
||||||
From the `route_guide` example directory run :
|
From the `route_guide` example directory run:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
protoc -I protos/ protos/route_guide.proto --dart_out=grpc:lib/src/generated
|
protoc -I protos/ protos/route_guide.proto --dart_out=grpc:lib/src/generated
|
||||||
|
|
@ -521,21 +522,25 @@ write in any order — the streams operate completely independently.
|
||||||
|
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
Go to the `examples/route_guide` folder.
|
Work from the example directory:
|
||||||
|
|
||||||
First, make sure dependencies are downloaded:
|
```sh
|
||||||
|
$ cd examples/route_guide
|
||||||
|
```
|
||||||
|
|
||||||
|
Get packages:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ pub get
|
$ pub get
|
||||||
```
|
```
|
||||||
|
|
||||||
To run the server, simply:
|
Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ dart bin/server.dart
|
$ dart bin/server.dart
|
||||||
```
|
```
|
||||||
|
|
||||||
Likewise, to run the client:
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ dart bin/client.dart
|
$ dart bin/client.dart
|
||||||
|
|
|
||||||
|
|
@ -82,10 +82,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
and waits for a response to come back, just like a normal function call.
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
and gets a stream to read a sequence of messages back. The client reads from
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
|
@ -93,13 +93,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a server-side streaming method by placing the `stream`
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
and sends them to the server, again using a provided stream. Once the client
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
|
@ -107,11 +107,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
and return its response. You specify a client-side streaming method by placing
|
and return its response. You specify a client-side streaming method by placing
|
||||||
the `stream` keyword before the *request* type.
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -122,13 +122,15 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all the request and response types used in our service methods - for example, here's the `Point` message type:
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
|
the request and response types used in our service methods - for example, here's
|
||||||
|
the `Point` message type:
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Points are represented as latitude-longitude pairs in the E7 representation
|
// Points are represented as latitude-longitude pairs in the E7 representation
|
||||||
|
|
@ -148,13 +150,15 @@ service definition. We do this using the protocol buffer compiler `protoc` with
|
||||||
a special gRPC Go plugin.
|
a special gRPC Go plugin.
|
||||||
This is similar to what we did in the [quickstart guide](/docs/quickstart/go/)
|
This is similar to what we did in the [quickstart guide](/docs/quickstart/go/)
|
||||||
|
|
||||||
From the `route_guide` example directory run :
|
From the `route_guide` example directory run:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
protoc -I routeguide/ routeguide/route_guide.proto --go_out=plugins=grpc:routeguide
|
protoc -I routeguide/ routeguide/route_guide.proto --go_out=plugins=grpc:routeguide
|
||||||
```
|
```
|
||||||
|
|
||||||
Running this command generates the following file in the `routeguide` directory under the `route_guide` example directory:
|
Running this command generates the following file in the `routeguide` directory
|
||||||
|
under the `route_guide` example directory:
|
||||||
|
|
||||||
- `route_guide.pb.go`
|
- `route_guide.pb.go`
|
||||||
|
|
||||||
This contains:
|
This contains:
|
||||||
|
|
@ -573,14 +577,19 @@ any order — the streams operate completely independently.
|
||||||
|
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
To compile and run the server, assuming you are in the folder
|
Work from the example directory:
|
||||||
`$GOPATH/src/google.golang.org/grpc/examples/route_guide`, simply:
|
|
||||||
|
```sh
|
||||||
|
$ cd $GOPATH/src/google.golang.org/grpc/examples/route_guide
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ go run server/server.go
|
$ go run server/server.go
|
||||||
```
|
```
|
||||||
|
|
||||||
Likewise, to run the client:
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ go run client/client.go
|
$ go run client/client.go
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,6 @@ Then change your current directory to `grpc-java/examples`:
|
||||||
$ cd grpc-java/examples
|
$ cd grpc-java/examples
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Defining the service
|
### Defining the service
|
||||||
|
|
||||||
Our first step (as you'll know from the [Overview](/docs/)) is to
|
Our first step (as you'll know from the [Overview](/docs/)) is to
|
||||||
|
|
@ -96,10 +95,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
and waits for a response to come back, just like a normal function call.
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
and gets a stream to read a sequence of messages back. The client reads from
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
|
@ -107,13 +106,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a server-side streaming method by placing the `stream`
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
and sends them to the server, again using a provided stream. Once the client
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
|
@ -121,11 +120,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
and return its response. You specify a client-side streaming method by placing
|
and return its response. You specify a client-side streaming method by placing
|
||||||
the `stream` keyword before the *request* type.
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -136,13 +135,13 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
|
|
@ -157,7 +156,6 @@ message Point {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Generating client and server code
|
### Generating client and server code
|
||||||
|
|
||||||
Next we need to generate the gRPC client and server interfaces from our .proto
|
Next we need to generate the gRPC client and server interfaces from our .proto
|
||||||
|
|
@ -181,7 +179,6 @@ The following classes are generated from our service definition:
|
||||||
`RouteGuide` service.
|
`RouteGuide` service.
|
||||||
- *stub* classes that clients can use to talk to a `RouteGuide` server.
|
- *stub* classes that clients can use to talk to a `RouteGuide` server.
|
||||||
|
|
||||||
|
|
||||||
<a name="server"></a>
|
<a name="server"></a>
|
||||||
|
|
||||||
### Creating the server
|
### Creating the server
|
||||||
|
|
|
||||||
|
|
@ -99,10 +99,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
and waits for a response to come back, just like a normal function call.
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
and gets a stream to read a sequence of messages back. The client reads from
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
|
@ -110,13 +110,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a server-side streaming method by placing the `stream`
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
and sends them to the server, again using a provided stream. Once the client
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
|
@ -124,11 +124,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
and return its response. You specify a client-side streaming method by placing
|
and return its response. You specify a client-side streaming method by placing
|
||||||
the `stream` keyword before the *request* type.
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -139,13 +139,13 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
|
|
@ -512,17 +512,19 @@ independently.
|
||||||
|
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
Build client and server:
|
Build the client and server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ npm install
|
$ npm install
|
||||||
```
|
```
|
||||||
Run the server, which will listen on port 50051:
|
|
||||||
|
Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ node ./dynamic_codegen/route_guide/route_guide_server.js --db_path=./dynamic_codegen/route_guide/route_guide_db.json
|
$ node ./dynamic_codegen/route_guide/route_guide_server.js --db_path=./dynamic_codegen/route_guide/route_guide_db.json
|
||||||
```
|
```
|
||||||
Run the client (in a different terminal):
|
|
||||||
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ node ./dynamic_codegen/route_guide/route_guide_client.js --db_path=./dynamic_codegen/route_guide/route_guide_db.json
|
$ node ./dynamic_codegen/route_guide/route_guide_client.js --db_path=./dynamic_codegen/route_guide/route_guide_db.json
|
||||||
|
|
|
||||||
|
|
@ -134,22 +134,22 @@ service method, all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server and receives a
|
- A *simple RPC* where the client sends a request to the server and receives a
|
||||||
response later, just like a normal remote procedure call.
|
response later, just like a normal remote procedure call.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *response-streaming RPC* where the client sends a request to the server and
|
- A *response-streaming RPC* where the client sends a request to the server and
|
||||||
gets back a stream of response messages. You specify a response-streaming
|
gets back a stream of response messages. You specify a response-streaming
|
||||||
method by placing the `stream` keyword before the *response* type.
|
method by placing the `stream` keyword before the *response* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *request-streaming RPC* where the client sends a sequence of messages to the
|
- A *request-streaming RPC* where the client sends a sequence of messages to the
|
||||||
server. Once the client has finished writing the messages, it waits for the
|
server. Once the client has finished writing the messages, it waits for the
|
||||||
|
|
@ -157,11 +157,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
request-streaming method by placing the `stream` keyword before the *request*
|
request-streaming method by placing the `stream` keyword before the *request*
|
||||||
type.
|
type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
to the other. The two streams operate independently, so clients and servers
|
to the other. The two streams operate independently, so clients and servers
|
||||||
|
|
@ -172,13 +172,13 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
preserved. You specify this type of method by placing the `stream` keyword
|
preserved. You specify this type of method by placing the `stream` keyword
|
||||||
before both the request and the response.
|
before both the request and the response.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,22 +124,22 @@ service method, all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server and receives a
|
- A *simple RPC* where the client sends a request to the server and receives a
|
||||||
response later, just like a normal remote procedure call.
|
response later, just like a normal remote procedure call.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *response-streaming RPC* where the client sends a request to the server and
|
- A *response-streaming RPC* where the client sends a request to the server and
|
||||||
gets back a stream of response messages. You specify a response-streaming
|
gets back a stream of response messages. You specify a response-streaming
|
||||||
method by placing the `stream` keyword before the *response* type.
|
method by placing the `stream` keyword before the *response* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *request-streaming RPC* where the client sends a sequence of messages to the
|
- A *request-streaming RPC* where the client sends a sequence of messages to the
|
||||||
server. Once the client has finished writing the messages, it waits for the
|
server. Once the client has finished writing the messages, it waits for the
|
||||||
|
|
@ -147,11 +147,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
request-streaming method by placing the `stream` keyword before the *request*
|
request-streaming method by placing the `stream` keyword before the *request*
|
||||||
type.
|
type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
to the other. The two streams operate independently, so clients and servers
|
to the other. The two streams operate independently, so clients and servers
|
||||||
|
|
@ -162,13 +162,13 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
preserved. You specify this type of method by placing the `stream` keyword
|
preserved. You specify this type of method by placing the `stream` keyword
|
||||||
before both the request and the response.
|
before both the request and the response.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
and waits for a response to come back, just like a normal function call.
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *response-streaming RPC* where the client sends a request to the server and
|
- A *response-streaming RPC* where the client sends a request to the server and
|
||||||
gets a stream to read a sequence of messages back. The client reads from the
|
gets a stream to read a sequence of messages back. The client reads from the
|
||||||
|
|
@ -94,13 +94,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a response-streaming method by placing the `stream`
|
example, you specify a response-streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *request-streaming RPC* where the client writes a sequence of messages and
|
- A *request-streaming RPC* where the client writes a sequence of messages and
|
||||||
sends them to the server, again using a provided stream. Once the client has
|
sends them to the server, again using a provided stream. Once the client has
|
||||||
|
|
@ -108,11 +108,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
return its response. You specify a request-streaming method by placing the
|
return its response. You specify a request-streaming method by placing the
|
||||||
`stream` keyword before the *request* type.
|
`stream` keyword before the *request* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectionally-streaming RPC* where both sides send a sequence of messages
|
- A *bidirectionally-streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -123,13 +123,13 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Your .proto file also contains protocol buffer message type definitions for all
|
Your `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
|
|
@ -394,13 +394,13 @@ for received_route_note in stub.RouteChat(sent_route_note_iterator):
|
||||||
|
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
Run the server, which will listen on port 50051:
|
Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ python route_guide_server.py
|
$ python route_guide_server.py
|
||||||
```
|
```
|
||||||
|
|
||||||
Run the client (in a different terminal):
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ python route_guide_client.py
|
$ python route_guide_client.py
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,10 @@ all of which are used in the `RouteGuide` service:
|
||||||
- A *simple RPC* where the client sends a request to the server using the stub
|
- A *simple RPC* where the client sends a request to the server using the stub
|
||||||
and waits for a response to come back, just like a normal function call.
|
and waits for a response to come back, just like a normal function call.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the feature at a given position.
|
// Obtains the feature at a given position.
|
||||||
rpc GetFeature(Point) returns (Feature) {}
|
rpc GetFeature(Point) returns (Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *server-side streaming RPC* where the client sends a request to the server
|
- A *server-side streaming RPC* where the client sends a request to the server
|
||||||
and gets a stream to read a sequence of messages back. The client reads from
|
and gets a stream to read a sequence of messages back. The client reads from
|
||||||
|
|
@ -94,13 +94,13 @@ rpc GetFeature(Point) returns (Feature) {}
|
||||||
example, you specify a server-side streaming method by placing the `stream`
|
example, you specify a server-side streaming method by placing the `stream`
|
||||||
keyword before the *response* type.
|
keyword before the *response* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Obtains the Features available within the given Rectangle. Results are
|
// Obtains the Features available within the given Rectangle. Results are
|
||||||
// streamed rather than returned at once (e.g. in a response message with a
|
// streamed rather than returned at once (e.g. in a response message with a
|
||||||
// repeated field), as the rectangle may cover a large area and contain a
|
// repeated field), as the rectangle may cover a large area and contain a
|
||||||
// huge number of features.
|
// huge number of features.
|
||||||
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *client-side streaming RPC* where the client writes a sequence of messages
|
- A *client-side streaming RPC* where the client writes a sequence of messages
|
||||||
and sends them to the server, again using a provided stream. Once the client
|
and sends them to the server, again using a provided stream. Once the client
|
||||||
|
|
@ -108,11 +108,11 @@ rpc ListFeatures(Rectangle) returns (stream Feature) {}
|
||||||
and return its response. You specify a client-side streaming method by placing
|
and return its response. You specify a client-side streaming method by placing
|
||||||
the `stream` keyword before the *request* type.
|
the `stream` keyword before the *request* type.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of Points on a route being traversed, returning a
|
// Accepts a stream of Points on a route being traversed, returning a
|
||||||
// RouteSummary when traversal is completed.
|
// RouteSummary when traversal is completed.
|
||||||
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
- A *bidirectional streaming RPC* where both sides send a sequence of messages
|
||||||
using a read-write stream. The two streams operate independently, so clients
|
using a read-write stream. The two streams operate independently, so clients
|
||||||
|
|
@ -123,13 +123,13 @@ rpc RecordRoute(stream Point) returns (RouteSummary) {}
|
||||||
stream is preserved. You specify this type of method by placing the `stream`
|
stream is preserved. You specify this type of method by placing the `stream`
|
||||||
keyword before both the request and the response.
|
keyword before both the request and the response.
|
||||||
|
|
||||||
```protobuf
|
```protobuf
|
||||||
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
// Accepts a stream of RouteNotes sent while a route is being traversed,
|
||||||
// while receiving other RouteNotes (e.g. from other users).
|
// while receiving other RouteNotes (e.g. from other users).
|
||||||
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Our .proto file also contains protocol buffer message type definitions for all
|
Our `.proto` file also contains protocol buffer message type definitions for all
|
||||||
the request and response types used in our service methods - for example, here's
|
the request and response types used in our service methods - for example, here's
|
||||||
the `Point` message type:
|
the `Point` message type:
|
||||||
|
|
||||||
|
|
@ -376,23 +376,28 @@ streams operate completely independently.
|
||||||
|
|
||||||
### Try it out!
|
### Try it out!
|
||||||
|
|
||||||
Build client and server:
|
Work from the example directory:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ cd examples/ruby
|
||||||
|
```
|
||||||
|
|
||||||
|
Build the client and server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # from examples/ruby
|
|
||||||
$ gem install bundler && bundle install
|
$ gem install bundler && bundle install
|
||||||
```
|
```
|
||||||
Run the server, which will listen on port 50051:
|
|
||||||
|
Run the server:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # from examples/ruby
|
|
||||||
$ bundle exec route_guide/route_guide_server.rb ../python/route_guide/route_guide_db.json
|
$ bundle exec route_guide/route_guide_server.rb ../python/route_guide/route_guide_db.json
|
||||||
$ # (note that the route_guide_db.json file is actually language-agnostic; it's just
|
|
||||||
$ # located in the python folder).
|
|
||||||
```
|
```
|
||||||
Run the client (in a different terminal):
|
|
||||||
|
> Note: The `route_guide_db.json` file is actually language-agnostic, it happens to be located in the `python` folder.
|
||||||
|
|
||||||
|
From a different terminal, run the client:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ # from examples/ruby
|
|
||||||
$ bundle exec route_guide/route_guide_client.rb ../python/route_guide/route_guide_db.json
|
$ bundle exec route_guide/route_guide_client.rb ../python/route_guide/route_guide_db.json
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ protocol buffers, including efficient serialization, a simple IDL, and easy
|
||||||
interface updating. gRPC-Web lets you access gRPC services built in this manner
|
interface updating. gRPC-Web lets you access gRPC services built in this manner
|
||||||
from browsers using an idiomatic API.
|
from browsers using an idiomatic API.
|
||||||
|
|
||||||
|
|
||||||
<a name="setup"></a>
|
<a name="setup"></a>
|
||||||
|
|
||||||
### Define the Service
|
### Define the Service
|
||||||
|
|
@ -74,7 +73,6 @@ function doEcho(call, callback) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Configure the Envoy Proxy
|
### Configure the Envoy Proxy
|
||||||
|
|
||||||
In this example, we will use the [Envoy](https://www.envoyproxy.io/)
|
In this example, we will use the [Envoy](https://www.envoyproxy.io/)
|
||||||
|
|
@ -119,15 +117,11 @@ this:
|
||||||
You may also need to add some CORS setup to make sure the browser can request
|
You may also need to add some CORS setup to make sure the browser can request
|
||||||
cross-origin content.
|
cross-origin content.
|
||||||
|
|
||||||
|
|
||||||
In this simple example, the browser makes gRPC requests to port `:8080`. Envoy
|
In this simple example, the browser makes gRPC requests to port `:8080`. Envoy
|
||||||
forwards the request to the backend gRPC server listening on port `:9090`.
|
forwards the request to the backend gRPC server listening on port `:9090`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Generate Protobuf Messages and Service Client Stub
|
### Generate Protobuf Messages and Service Client Stub
|
||||||
|
|
||||||
|
|
||||||
To generate the protobuf message classes from our `echo.proto`, run the
|
To generate the protobuf message classes from our `echo.proto`, run the
|
||||||
following command:
|
following command:
|
||||||
|
|
||||||
|
|
@ -163,7 +157,6 @@ In the `--grpc-web_out` param above:
|
||||||
Our command generates the client stub, by default, to the file
|
Our command generates the client stub, by default, to the file
|
||||||
`echo_grpc_web_pb.js`.
|
`echo_grpc_web_pb.js`.
|
||||||
|
|
||||||
|
|
||||||
### Write JS Client Code
|
### Write JS Client Code
|
||||||
|
|
||||||
Now you are ready to write some JS client code. Put this in a `client.js` file.
|
Now you are ready to write some JS client code. Put this in a `client.js` file.
|
||||||
|
|
@ -201,7 +194,6 @@ You will need a `package.json` file
|
||||||
|
|
||||||
### Compile the JS Library
|
### Compile the JS Library
|
||||||
|
|
||||||
|
|
||||||
Finally, putting all these together, we can compile all the relevant JS files
|
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.
|
into one single JS library that can be used in the browser.
|
||||||
|
|
||||||
|
|
@ -212,6 +204,5 @@ $ npx webpack client.js
|
||||||
|
|
||||||
Now embed `dist/main.js` into your project and see it in action!
|
Now embed `dist/main.js` into your project and see it in action!
|
||||||
|
|
||||||
|
|
||||||
[protobuf documentation]:https://developers.google.com/protocol-buffers/
|
[protobuf documentation]:https://developers.google.com/protocol-buffers/
|
||||||
[main page]:/docs/
|
[main page]:/docs/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue