From f8401a757c7e316439375094149bef8cc4bc17da Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 29 May 2015 15:09:04 -0700 Subject: [PATCH] PHP hello world example first draft --- README.md | 2 +- csharp/.nuget/packages.config | 4 + csharp/Greeter.sln | 79 +++++---- csharp/Greeter/packages.config | 2 +- csharp/GreeterClient/packages.config | 1 + csharp/GreeterServer/packages.config | 2 +- csharp/route_guide/.nuget/packages.config | 4 + csharp/route_guide/README.md | 39 +++-- csharp/route_guide/RouteGuide.sln | 5 + csharp/route_guide/RouteGuide/packages.config | 2 +- .../RouteGuideClient/packages.config | 2 +- .../RouteGuideServer/packages.config | 2 +- grpc-auth-support.md | 36 ++++ node/README.md | 23 +-- node/package.json | 2 +- php/.gitignore | 2 + php/README.md | 84 +++++++++ php/composer.json | 9 + php/greeter_client.php | 51 ++++++ php/helloworld.php | 160 ++++++++++++++++++ php/helloworld.proto | 50 ++++++ ruby/Gemfile | 2 +- ruby/README.md | 65 ++++--- 23 files changed, 525 insertions(+), 103 deletions(-) create mode 100644 csharp/.nuget/packages.config create mode 100644 csharp/route_guide/.nuget/packages.config create mode 100644 php/.gitignore create mode 100644 php/README.md create mode 100644 php/composer.json create mode 100644 php/greeter_client.php create mode 100644 php/helloworld.php create mode 100644 php/helloworld.proto diff --git a/README.md b/README.md index a12110d7cda..45edef01a48 100644 --- a/README.md +++ b/README.md @@ -304,7 +304,7 @@ implementation available from the network. Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { - // Use stderr here since the logger may has been reset by its JVM shutdown hook. + // Use stderr here since the logger may have been reset by its JVM shutdown hook. System.err.println("*** shutting down gRPC server since JVM is shutting down"); HelloWorldServer.this.stop(); System.err.println("*** server shut down"); diff --git a/csharp/.nuget/packages.config b/csharp/.nuget/packages.config new file mode 100644 index 00000000000..e667d9847ee --- /dev/null +++ b/csharp/.nuget/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/csharp/Greeter.sln b/csharp/Greeter.sln index 03f18878075..9430e94de99 100644 --- a/csharp/Greeter.sln +++ b/csharp/Greeter.sln @@ -1,37 +1,42 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greeter", "Greeter\Greeter.csproj", "{724DFC8C-4B57-4C3F-811C-0463BE2A2829}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreeterServer", "GreeterServer\GreeterServer.csproj", "{A7706C84-92D2-4B7A-B779-76B64D2950EC}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreeterClient", "GreeterClient\GreeterClient.csproj", "{ACCF4597-3748-4117-8633-1CB767F8CCC3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Debug|Any CPU.Build.0 = Debug|Any CPU - {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Release|Any CPU.ActiveCfg = Release|Any CPU - {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Release|Any CPU.Build.0 = Release|Any CPU - {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Release|Any CPU.Build.0 = Release|Any CPU - {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = Greeter\Greeter.csproj - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greeter", "Greeter\Greeter.csproj", "{724DFC8C-4B57-4C3F-811C-0463BE2A2829}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreeterServer", "GreeterServer\GreeterServer.csproj", "{A7706C84-92D2-4B7A-B779-76B64D2950EC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreeterClient", "GreeterClient\GreeterClient.csproj", "{ACCF4597-3748-4117-8633-1CB767F8CCC3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{FF1EBE95-F20D-4C27-8A61-D0125F3C8152}" + ProjectSection(SolutionItems) = preProject + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Debug|Any CPU.Build.0 = Debug|Any CPU + {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Release|Any CPU.ActiveCfg = Release|Any CPU + {724DFC8C-4B57-4C3F-811C-0463BE2A2829}.Release|Any CPU.Build.0 = Release|Any CPU + {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A7706C84-92D2-4B7A-B779-76B64D2950EC}.Release|Any CPU.Build.0 = Release|Any CPU + {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ACCF4597-3748-4117-8633-1CB767F8CCC3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = Greeter\Greeter.csproj + EndGlobalSection +EndGlobal diff --git a/csharp/Greeter/packages.config b/csharp/Greeter/packages.config index b1f8c6945e4..0fdc11821b0 100644 --- a/csharp/Greeter/packages.config +++ b/csharp/Greeter/packages.config @@ -1,7 +1,7 @@  - + diff --git a/csharp/GreeterClient/packages.config b/csharp/GreeterClient/packages.config index 7275d329f9d..0fdc11821b0 100644 --- a/csharp/GreeterClient/packages.config +++ b/csharp/GreeterClient/packages.config @@ -1,6 +1,7 @@  + diff --git a/csharp/GreeterServer/packages.config b/csharp/GreeterServer/packages.config index b1f8c6945e4..0fdc11821b0 100644 --- a/csharp/GreeterServer/packages.config +++ b/csharp/GreeterServer/packages.config @@ -1,7 +1,7 @@  - + diff --git a/csharp/route_guide/.nuget/packages.config b/csharp/route_guide/.nuget/packages.config new file mode 100644 index 00000000000..e667d9847ee --- /dev/null +++ b/csharp/route_guide/.nuget/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/csharp/route_guide/README.md b/csharp/route_guide/README.md index 61124fe620e..125950317e2 100644 --- a/csharp/route_guide/README.md +++ b/csharp/route_guide/README.md @@ -26,9 +26,11 @@ $ git clone https://github.com/google/grpc-common.git All the files for this tutorial are in the directory `grpc-common/csharp/route_guide`. Open the solution `grpc-common/csharp/route_guide/RouteGuide.sln` from Visual Studio (or Monodevelop on Linux). -You also should have the relevant tools installed to generate the server and client interface code. +On Windows, you should not need to do anything besides opening the solution. All the needed dependencies will be restored +for you automatically by the `Grpc` NuGet package upon building the solution. -**TODO: more on how to install protoc** +On Linux (or MacOS), you will first need to install protobuf and gRPC C Core using Linuxbrew (or Homebrew) tool in order to be +able to generate the server and client interface code and run the examples. Follow the instructions for [Linux](https://github.com/grpc/grpc/tree/master/src/csharp#usage-linux-mono) or [MacOS](https://github.com/grpc/grpc/tree/master/src/csharp#usage-macos-mono). ## Defining the service @@ -90,19 +92,25 @@ message Point { Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C# plugin. -If you want to run this yourself, make sure you've installed protoc and followed the gRPC C# plugin [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first. - -**TODO: more on how to install protoc and grpc_csharp_plugin** +If you want to run this yourself, make sure you've installed protoc and gRPC C# plugin. The instructions vary based on your OS: +- For Windows, the `Grpc.Tools` NuGet package contains the binaries you will need to generate the code. +- For Linux, make sure you've [installed gRPC C Core using Linuxbrew](https://github.com/grpc/grpc/tree/master/src/csharp#usage-linux-mono) +- For MacOS, make sure you've [installed gRPC C Core using Homebrew](https://github.com/grpc/grpc/tree/master/src/csharp#usage-macos-mono) Once that's done, the following command can be used to generate the C# code. +To generate the code on Windows, we use `protoc.exe` and `grpc_csharp_plugin.exe` binaries that are shipped with the `Grpc.Tools` NuGet package under the `tools` directory. +Normally you would need to add the `Grpc.Tools` package to the solution yourself, but in this tutorial it has been already done for you. Following command should be run from the `csharp/route_guide` directory: +``` +> packages\Grpc.Tools.0.5.0\tools\protoc -I RouteGuide/protos --csharp_out=RouteGuide --grpc_out=RouteGuide --plugin=protoc-gen-grpc=packages\Grpc.Tools.0.5.0\tools\grpc_csharp_plugin.exe RouteGuide/protos/route_guide.proto +``` + +On Linux/MacOS, we rely on `protoc` and `grpc_csharp_plugin` being installed by Linuxbrew/Homebrew. Run this command from the route_guide directory: ```shell $ protoc -I RouteGuide/protos --csharp_out=RouteGuide --grpc_out=RouteGuide --plugin=protoc-gen-grpc=`which grpc_csharp_plugin` RouteGuide/protos/route_guide.proto ``` -**TODO: command for windows** - -Running this command regenerates the following files in the RouteGuide directory: +Running one of the previous commands regenerates the following files in the RouteGuide directory: - `RouteGuide/RouteGuide.cs` defines a namespace `examples` - This contains all the protocol buffer code to populate, serialize, and retrieve our request and response message types - `RouteGuide/RouteGuideGrpc.cs`, provides stub and service classes @@ -130,6 +138,8 @@ As you can see, our server has a `RouteGuideImpl` class that implements the gene public class RouteGuideImpl : RouteGuide.IRouteGuide ``` +#### Simple RPC + `RouteGuideImpl` implements all our service methods. Let's look at the simplest type first, `GetFeature`, which just gets a `Point` from the client and returns the corresponding feature information from its database in a `Feature`. ```csharp @@ -143,6 +153,8 @@ The method is passed a context for the RPC (which is empty in the alpha release) implementation, the method returns `Task` rather than just `Feature`. You are free to perform your computations synchronously and return the result once you've finished, just as we do in the example. +#### Server-side streaming RPC + Now let's look at something a bit more complicated - a streaming RPC. `ListFeatures` is a server-side streaming RPC, so we need to send back multiple `Feature` protocol buffers to our client. ```csharp @@ -174,7 +186,9 @@ Now let's look at something a bit more complicated - a streaming RPC. `ListFeatu As you can see, here the request object is a `Rectangle` in which our client wants to find `Feature`s, but instead of returning a simple response we need to write responses to an asynchronous stream `IServerStreamWriter` using async method `WriteAsync`. -Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumerator](https://github.com/Reactive-Extensions/Rx.NET/blob/master/Ix.NET/Source/System.Interactive.Async/IAsyncEnumerator.cs), to read the stream of requests using async method `MoveNext` and property `Current`. +#### Client-side streaming RPC + +Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumerator](https://github.com/Reactive-Extensions/Rx.NET/blob/master/Ix.NET/Source/System.Interactive.Async/IAsyncEnumerator.cs), to read the stream of requests using the async method `MoveNext` and the `Current` property. ```csharp public async Task RecordRoute(Grpc.Core.ServerCallContext context, @@ -208,6 +222,9 @@ Similarly, the client-side streaming method `RecordRoute` uses an [IAsyncEnumera .SetElapsedTime((int) (stopwatch.ElapsedMilliseconds / 1000)).Build(); } ``` + +#### Bidirectional streaming RPC + Finally, let's look at our bidirectional streaming RPC `RouteChat`. ```csharp @@ -238,7 +255,7 @@ Finally, let's look at our bidirectional streaming RPC `RouteChat`. } ``` -Here the method receives both `requestStream` and `responseStream` as an argument. Reading the requests is done in a same way as in the `RecordRoute` example. Writing the responses is done the same way as in the `ListFeatures` example. +Here the method receives both `requestStream` and `responseStream` arguments. Reading the requests is done the same way as in the client-side streaming method `RecordRoute`. Writing the responses is done the same way as in the server-side streaming method `ListFeatures`. ### Starting the server @@ -264,7 +281,7 @@ As you can see, we build and start our server using `Grpc.Core.Server` class. To 1. Create an instance of `Grpc.Core.Server`. 1. Create an instance of our service implementation class `RouteGuideImpl`. -3. Register our service implementation with the server using method `AddServiceDefinition` and the generated method `RouteGuide.BindService`. +3. Register our service implementation with the server using the `AddServiceDefinition` method and the generated method `RouteGuide.BindService`. 2. Specify the address and port we want to use to listen for client requests using the `AddListeningPort` method. 4. Call `Start` on the server instance to start an RPC server for our service. diff --git a/csharp/route_guide/RouteGuide.sln b/csharp/route_guide/RouteGuide.sln index 00065b0ba9d..0b79fdc5ca7 100644 --- a/csharp/route_guide/RouteGuide.sln +++ b/csharp/route_guide/RouteGuide.sln @@ -9,6 +9,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideClient", "RouteGu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteGuideServer", "RouteGuideServer\RouteGuideServer.csproj", "{4B7C7794-BE24-4477-ACE7-18259EB73D27}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{2F6B184B-A576-4F21-AF2E-27E73D1FC96E}" + ProjectSection(SolutionItems) = preProject + .nuget\packages.config = .nuget\packages.config + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/csharp/route_guide/RouteGuide/packages.config b/csharp/route_guide/RouteGuide/packages.config index b3efb8aa7ae..49952ab6361 100644 --- a/csharp/route_guide/RouteGuide/packages.config +++ b/csharp/route_guide/RouteGuide/packages.config @@ -1,7 +1,7 @@  - + diff --git a/csharp/route_guide/RouteGuideClient/packages.config b/csharp/route_guide/RouteGuideClient/packages.config index b1f8c6945e4..0fdc11821b0 100644 --- a/csharp/route_guide/RouteGuideClient/packages.config +++ b/csharp/route_guide/RouteGuideClient/packages.config @@ -1,7 +1,7 @@  - + diff --git a/csharp/route_guide/RouteGuideServer/packages.config b/csharp/route_guide/RouteGuideServer/packages.config index b1f8c6945e4..0fdc11821b0 100644 --- a/csharp/route_guide/RouteGuideServer/packages.config +++ b/csharp/route_guide/RouteGuideServer/packages.config @@ -1,7 +1,7 @@  - + diff --git a/grpc-auth-support.md b/grpc-auth-support.md index 6a5ef0fa3d0..9b97203276b 100644 --- a/grpc-auth-support.md +++ b/grpc-auth-support.md @@ -101,6 +101,19 @@ creds = GRPC::Core::Credentials.new(load_certs) # load_certs typically loads a stub = Helloworld::Greeter::Stub.new('localhost:50051', creds: creds) ``` +###SSL/TLS for server authentication and encryption (C#) +```csharp +// Base case - No encryption +var channel = new Channel("localhost:50051"); +var client = new Greeter.GreeterClient(channel); +... + +// With server authentication SSL/TLS +var credentials = new SslCredentials(File.ReadAllText("ca.pem")); // Load a CA file +var channel = new Channel("localhost:50051", credentials); +var client = new Greeter.GreeterClient(channel); +``` + ###Authenticating with Google (Ruby) ```ruby # Base case - No encryption/authorization @@ -138,3 +151,26 @@ var scope = 'https://www.googleapis.com/auth/grpc-testing'; grpc.getGoogleAuthDelegate(auth)); }); ``` + +###Authenticating with Google (C#) +```csharp +// Base case - No encryption/authorization +var channel = new Channel("localhost:50051"); +var client = new Greeter.GreeterClient(channel); +... + +// Authenticating with Google +using Grpc.Auth; // from Grpc.Auth NuGet package +... +var credentials = new SslCredentials(File.ReadAllText("ca.pem")); // Load a CA file +var channel = new Channel("localhost:50051", credentials); + +string scope = "https://www.googleapis.com/auth/grpc-testing"; +var authorization = GoogleCredential.GetApplicationDefault(); +if (authorization.IsCreateScopedRequired) +{ + authorization = credential.CreateScoped(new[] { scope }); +} +var client = new Greeter.GreeterClient(channel, + new StubConfiguration(OAuth2InterceptorFactory.Create(credential))); +``` diff --git a/node/README.md b/node/README.md index 1ddef0e1e41..8c24a960a3e 100644 --- a/node/README.md +++ b/node/README.md @@ -4,25 +4,23 @@ gRPC in 3 minutes (Node.js) PREREQUISITES ------------- -This requires Node 10.x or greater. +- `node`: This requires Node 10.x or greater. +- [homebrew][] on Mac OS X, [linuxbrew][] on Linux. These simplify the installation of the gRPC C core. INSTALL ------- + - On Mac OS X, install [homebrew][]. On Linux, install [linuxbrew][]. Run the following command to install gRPC Node.js. + ```sh + $ curl -fsSL https://goo.gl/getgrpc | bash -s nodejs + ``` + This will download and run the [gRPC install script][], then install the latest version of gRPC Nodejs npm package. - Clone this repository ```sh $ git clone https://github.com/grpc/grpc-common.git ``` - - Download the grpc debian packages from the [latest grpc release](https://github.com/grpc/grpc/releases) and install them. - - Later, it will possible to install them directly using `apt-get install` - ```sh - $ wget https://github.com/grpc/grpc/releases/download/release-0_5_0/libgrpc_0.5.0_amd64.deb - $ wget https://github.com/grpc/grpc/releases/download/release-0_5_0/libgrpc-dev_0.5.0_amd64.deb - $ sudo dpkg -i libgrpc_0.5.0_amd64.deb libgrpc-dev_0.5.0_amd64.deb - ``` - - Install this package's dependencies ```sh @@ -49,11 +47,14 @@ TRY IT! NOTE ---- - This directory has a copy of `helloworld.proto` because it currently depends on some Protocol Buffer 2.0 syntax that is deprecated in Protocol Buffer 3.0. TUTORIAL -------- +You can find a more detailed tutorial in [gRPC Basics: Node.js][] -You can find a more detailed tutorial in [gRPC Basics: Node.js](https://github.com/grpc/grpc-common/blob/master/node/route_guide/README.md). +[homebrew]:http://brew.sh +[linuxbrew]:https://github.com/Homebrew/linuxbrew#installation +[gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install +[gRPC Basics: Node.js]:https://github.com/grpc/grpc-common/blob/master/node/route_guide/README.md diff --git a/node/package.json b/node/package.json index 456d4fd82e1..caf539518f1 100644 --- a/node/package.json +++ b/node/package.json @@ -3,7 +3,7 @@ "version": "0.5.0", "dependencies": { "async": "^0.9.0", - "grpc": "~0.5.0", + "grpc": "~0.9.0", "minimist": "^1.1.0", "underscore": "^1.8.2" } diff --git a/php/.gitignore b/php/.gitignore new file mode 100644 index 00000000000..d8a7996ab38 --- /dev/null +++ b/php/.gitignore @@ -0,0 +1,2 @@ +composer.lock +vendor/ diff --git a/php/README.md b/php/README.md new file mode 100644 index 00000000000..4c2e6f11d06 --- /dev/null +++ b/php/README.md @@ -0,0 +1,84 @@ +gRPC in 3 minutes (PHP) +=========================== + +PREREQUISITES +------------- + +This requires PHP 5.5 or greater. + +INSTALL +------- + + - Clone this repository + + ```sh + $ git clone https://github.com/grpc/grpc-common.git + ``` + + - Install Protobuf-PHP + + ``` + $ git clone https://github.com/murgatroid99/Protobuf-PHP.git + $ cd Protobuf-PHP + $ rake pear:package version=1.0 + $ pear install Protobuf-1.0.tgz + ``` + + - Install composer + + ``` + $ cd grpc-common/php + $ curl -sS https://getcomposer.org/installer | php + ``` + + - (Coming soon) Download the gRPC PECL extension + + ``` + Coming soon + ``` + + - (Temporary workaround) Compile gRPC extension from source + + ``` + $ git clone https://github.com/grpc/grpc.git + $ cd grpc + $ git checkout --track origin/release-0_9 + $ git pull --recurse-submodules && git submodule update --init --recursive + $ cd third_party/protobuf + $ ./autogen.sh && ./configure --prefix=/usr && make && make install + $ cd ../.. + $ make && make install + $ cd src/php/ext/grpc + $ phpize && ./configure && make && make install + ``` + + +TRY IT! +------- + + - Run the server + + Please follow the instruction in [Node](https://github.com/grpc/grpc-common/tree/master/node) to run the server + ``` + $ cd grpc-common/node + $ nodejs greeter_server.js + ``` + + - Run the client + + ``` + $ cd grpc-common/php + $ php composer.phar install + $ php -d extension=grpc.so greeter_client.php + ``` + +NOTE +---- + +This directory has a copy of `helloworld.proto` because it currently depends on +some Protocol Buffer 2.0 syntax. There is no proto3 support for PHP yet. + +TUTORIAL +-------- + +Coming soon diff --git a/php/composer.json b/php/composer.json new file mode 100644 index 00000000000..2deca5f0a1b --- /dev/null +++ b/php/composer.json @@ -0,0 +1,9 @@ +{ + "name": "grpc/grpc-demo", + "description": "gRPC example for PHP", + "minimum-stability": "dev", + "require": { + "php": ">=5.5.0", + "grpc/grpc": "dev-master" + } +} diff --git a/php/greeter_client.php b/php/greeter_client.php new file mode 100644 index 00000000000..8eeceb38504 --- /dev/null +++ b/php/greeter_client.php @@ -0,0 +1,51 @@ +setName($name); + list($reply, $status) = $client->SayHello($request)->wait(); + $message = $reply->getMessage(); + return $message; +} + +$name = !empty($argv[1]) ? $argv[1] : 'world'; +print(greet($name)."\n"); diff --git a/php/helloworld.php b/php/helloworld.php new file mode 100644 index 00000000000..22da3d3970f --- /dev/null +++ b/php/helloworld.php @@ -0,0 +1,160 @@ +number = 1; + $f->name = "name"; + $f->type = \DrSlump\Protobuf::TYPE_STRING; + $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL; + $descriptor->addField($f); + + foreach (self::$__extensions as $cb) { + $descriptor->addField($cb(), true); + } + + return $descriptor; + } + + /** + * Check if has a value + * + * @return boolean + */ + public function hasName(){ + return $this->_has(1); + } + + /** + * Clear value + * + * @return \helloworld\HelloRequest + */ + public function clearName(){ + return $this->_clear(1); + } + + /** + * Get value + * + * @return string + */ + public function getName(){ + return $this->_get(1); + } + + /** + * Set value + * + * @param string $value + * @return \helloworld\HelloRequest + */ + public function setName( $value){ + return $this->_set(1, $value); + } + } +} + +namespace helloworld { + + class HelloReply extends \DrSlump\Protobuf\Message { + + /** @var string */ + public $message = null; + + + /** @var \Closure[] */ + protected static $__extensions = array(); + + public static function descriptor() + { + $descriptor = new \DrSlump\Protobuf\Descriptor(__CLASS__, 'helloworld.HelloReply'); + + // OPTIONAL STRING message = 1 + $f = new \DrSlump\Protobuf\Field(); + $f->number = 1; + $f->name = "message"; + $f->type = \DrSlump\Protobuf::TYPE_STRING; + $f->rule = \DrSlump\Protobuf::RULE_OPTIONAL; + $descriptor->addField($f); + + foreach (self::$__extensions as $cb) { + $descriptor->addField($cb(), true); + } + + return $descriptor; + } + + /** + * Check if has a value + * + * @return boolean + */ + public function hasMessage(){ + return $this->_has(1); + } + + /** + * Clear value + * + * @return \helloworld\HelloReply + */ + public function clearMessage(){ + return $this->_clear(1); + } + + /** + * Get value + * + * @return string + */ + public function getMessage(){ + return $this->_get(1); + } + + /** + * Set value + * + * @param string $value + * @return \helloworld\HelloReply + */ + public function setMessage( $value){ + return $this->_set(1, $value); + } + } +} + +namespace helloworld { + + class GreeterClient{ + + private $rpc_impl; + + public function __construct($rpc_impl) { + $this->rpc_impl = $rpc_impl; + } + /** + * @param helloworld\HelloRequest $input + */ + public function SayHello(\helloworld\HelloRequest $argument, $metadata = array()) { + return $this->rpc_impl->_simpleRequest('/helloworld.Greeter/SayHello', $argument, '\helloworld\HelloReply::deserialize', $metadata); + } + } +} diff --git a/php/helloworld.proto b/php/helloworld.proto new file mode 100644 index 00000000000..ad8f7a15249 --- /dev/null +++ b/php/helloworld.proto @@ -0,0 +1,50 @@ +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; + +option java_package = "ex.grpc"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + optional string name = 1; +} + +// The response message containing the greetings +message HelloReply { + optional string message = 1; +} diff --git a/ruby/Gemfile b/ruby/Gemfile index e75f0f6137f..65d3f0ad4ae 100644 --- a/ruby/Gemfile +++ b/ruby/Gemfile @@ -3,4 +3,4 @@ source 'https://rubygems.org/' -gemspec +gem 'grpc', :git => 'https://github.com/grpc/grpc.git', :submodules => true, glob: 'src/ruby/*.gemspec' diff --git a/ruby/README.md b/ruby/README.md index 11b3d825b7e..fecd8041e08 100644 --- a/ruby/README.md +++ b/ruby/README.md @@ -3,66 +3,59 @@ gRPC in 3 minutes (Ruby) BACKGROUND ------------- -For this sample, we've already generated the server and client stubs from [helloworld.proto](https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto). +For this sample, we've already generated the server and client stubs from [helloworld.proto][] PREREQUISITES ------------- - Ruby 2.x - This requires Ruby 2.x, as the gRPC API surface uses keyword args. -If you don't have that installed locally, you can use [RVM](https://www.rvm.io/) to use Ruby 2.x for testing without upgrading the version of Ruby on your whole system. +If you don't have that installed locally, you can use [RVM][] to use Ruby 2.x for testing without upgrading the version of Ruby on your whole system. RVM is also useful if you don't have the necessary privileges to update your system's Ruby. -```sh -$ # RVM installation as specified at https://rvm.io/rvm/install -$ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 -$ \curl -sSL https://get.rvm.io | bash -s stable --ruby=ruby-2 -$ -$ # follow the instructions to ensure that your're using the latest stable version of Ruby -$ # and that the rvm command is installed -``` -- *N.B* Make sure your run `source $HOME/.rvm/scripts/rvm` as instructed to complete the set-up of RVM. -- Homebrew/Linuxbrew - -The gRPC core will be installed using [Linuxbrew][Linuxbrew] for Linux and [Homebrew][Homebrew] on Macs. -Please ensure these are installed before proceeding. + ```sh + $ # RVM installation as specified at https://rvm.io/rvm/install + $ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 + $ \curl -sSL https://get.rvm.io | bash -s stable --ruby=ruby-2 + $ + $ # follow the instructions to ensure that your're using the latest stable version of Ruby + $ # and that the rvm command is installed + ``` +- *N.B* Make sure your run `source $HOME/.rvm/scripts/rvm` as instructed to complete the set-up of RVM. INSTALL ------- - Clone this repository -- Install gRPC Ruby using the brew-based installer -```sh -$ curl -fsSL https://raw.githubusercontent.com/tbetbetbe/homebrew-grpc/master/scripts/install | bash -s ruby -``` - - Use bundler to install the example package's dependencies -```sh -$ # from this directory -$ gem install bundler # if you don't already have bundler available -$ bundle install -``` + + ```sh + $ # from this directory + $ gem install bundler # if you don't already have bundler available + $ bundle install + ``` Try it! ------- - Run the server -```sh -$ # from this directory -$ bundle exec ./greeter_server.rb & -``` + + ```sh + $ # from this directory + $ bundle exec ./greeter_server.rb & + ``` - Run the client -```sh -$ # from this directory -$ bundle exec ./greeter_client.rb -``` + + ```sh + $ # from this directory + $ bundle exec ./greeter_client.rb + ``` Tutorial -------- You can find a more detailed tutorial in [gRPC Basics: Ruby](https://github.com/grpc/grpc-common/blob/master/ruby/route_guide/README.md) -[Homebrew]: https://github.com/Homebrew/homebrew -[Linuxbrew]: https://github.com/Homebrew/linuxbrew +[helloworld.proto]:https://github.com/grpc/grpc-common/blob/master/protos/helloworld.proto +[RVM]:https://www.rvm.io/