Install x dotnet tool:
$ dotnet tool install --global x
Create a new C# App:
$ dotnet new console
Add ServiceStack.GrpcClient NuGet Package:
$ dotnet add package ServiceStack.GrpcClient
Add TodoWorld DTOs:
$ x csharp https://todoworld.servicestack.net
Use TodoWorld DTOs with generic GrpcServiceClient
to call TodoWorld gRPC Service:
using System;
using System.Threading.Tasks;
using ServiceStack;
using TodoWorld.ServiceModel;
namespace TodoWorld
{
class Program
{
public static async Task Main(string[] args)
{
ProtoBuf.Grpc.Client.GrpcClientFactory.AllowUnencryptedHttp2 = true;
var client = new GrpcServiceClient("http://todoworld.servicestack.net:5054");
var response = await client.GetAsync(new Hello { Name = "gRPC C#" });
Console.WriteLine(response.Result);
}
}
}
Override Program.cs
with the above C# Example:
$ x mix todoworld-cs
Run example:
$ dotnet run
using System;
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using ServiceStack;
using TodoWorld.ServiceModel;
namespace TodoWorld
{
class Program
{
public static async Task Main(string[] args)
{
var client = new GrpcServiceClient("https://todoworld.servicestack.net:50051",
new X509Certificate2("https://todoworld.servicestack.net/grpc.crt".GetBytesFromUrl()),
GrpcUtils.AllowSelfSignedCertificatesFrom("todoworld.servicestack.net"));
var response = await client.GetAsync(new Hello { Name = "gRPC C#" });
Console.WriteLine(response.Result);
}
}
}
Override Program.cs
with the above C# Example:
$ x mix todoworld-cs-ssl
Run example:
$ dotnet run
using System.Threading.Tasks;
using ServiceStack;
using ServiceStack.Text;
using TodoWorld.ServiceModel;
namespace CSharpGeneric
{
public class Program
{
public static async Task Main(string[] args)
{
// Certificate registration not required when using trusted local development certificate
var client = new GrpcServiceClient("https://localhost:5001");
await client.PostAsync(new ResetTodos());
//POST /todos
var todo = (await client.PostAsync(new CreateTodo { Title = "ServiceStack" })).Result;
$"new todo Id: {todo.Id}, Title: {todo.Title}".Print();
//GET /todos
var all = await client.GetAsync(new GetTodos());
$"todos: {all.Results?.Count ?? 0}".Print();
//GET /todos/1
todo = (await client.GetAsync(new GetTodo { Id = todo.Id })).Result;
$"get todo Id: {todo.Id}, Title: {todo.Title}".Print();
//GET /todos
all = await client.GetAsync(new GetTodos());
$"todos: {all.Results?.Count ?? 0}".Print();
//PUT /todos/1
await client.PutAsync(new UpdateTodo { Id = todo.Id, Title = "gRPC" });
//GET /todos/1
todo = (await client.GetAsync(new GetTodo { Id = todo.Id })).Result;
$"updated todo Title: {todo.Title}".Print();
//DELETE /todos/1
await client.DeleteAsync(new DeleteTodo { Id = todo.Id });
//GET /todos
all = await client.GetAsync(new GetTodos());
$"todos: {all.Results?.Count ?? 0}".Print();
}
}
}
Refer to /src/clients/csharp-generic for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Create a new VB.NET App:
$ dotnet new console -lang vb
Add ServiceStack.GrpcClient NuGet Package:
$ dotnet add package ServiceStack.GrpcClient
Add TodoWorld DTOs:
$ x vb https://todoworld.servicestack.net
Use TodoWorld DTOs with generic GrpcServiceClient
to call TodoWorld gRPC Service:
Imports System
Imports System.Collections.Generic
Imports System.Threading.Tasks
Imports ServiceStack
Imports TodoWorld.ServiceModel
Module Program
Async Function Todo() As Task
ProtoBuf.Grpc.Client.GrpcClientFactory.AllowUnencryptedHttp2 = true
Dim client = new GrpcServiceClient("http://todoworld.servicestack.net:5054")
Dim response = Await client.GetAsync(New Hello With { .Name = "gRPC VB.NET" })
Console.WriteLine(response.Result)
End Function
Sub Main(args As String())
Task.WaitAll(Todo())
End Sub
End Module
Override Program.vb
with the above VB.NET Example:
$ x mix todoworld-vb
Run example:
$ dotnet run
Imports System
Imports System.Collections.Generic
Imports System.Threading.Tasks
Imports System.Security.Cryptography.X509Certificates
Imports ServiceStack
Imports TodoWorld.ServiceModel
Module Program
Async Function Todo() As Task
Dim client = new GrpcServiceClient("https://todoworld.servicestack.net:50051",
new X509Certificate2("https://todoworld.servicestack.net/grpc.crt".GetBytesFromUrl()),
GrpcUtils.AllowSelfSignedCertificatesFrom("todoworld.servicestack.net"))
Dim response = Await client.GetAsync(New Hello With { .Name = "gRPC VB.NET" })
Console.WriteLine(response.Result)
End Function
Sub Main(args As String())
Task.WaitAll(Todo())
End Sub
End Module
Override Program.vb
with the above VB.NET Example:
$ x mix todoworld-vb-ssl
Run example:
$ dotnet run
Imports System
Imports System.Collections.Generic
Imports System.Threading.Tasks
Imports ServiceStack
Imports TodoWorld.ServiceModel
Imports TodoWorld.ServiceModel.Types
Module Program
Function SeqCount(c As List(Of Todo)) As Integer
Return IF(c Is Nothing, 0, c.Count)
End Function
Async Function TodoExample() As Task
' Certificate registration not required when using trusted local development certificate
Dim client = new GrpcServiceClient("https://localhost:5001")
Await client.PostAsync(New ResetTodos())
'GET /todos
Dim all = Await client.GetAsync(New GetTodos())
Console.WriteLine($"todos: {SeqCount(all.Results)}")
'POST /todos
Dim todo As Todo = (Await client.PostAsync(New CreateTodo With { .Title = "ServiceStack" })).Result
Console.WriteLine($"new todo Id: {todo.Id}, Title: {todo.Title}")
'GET /todos/1
todo = (Await client.GetAsync(New GetTodo With { .Id = todo.Id })).Result
Console.WriteLine($"get todo Id: {todo.Id}, Title: {todo.Title}")
'GET /todos
all = await client.GetAsync(new GetTodos())
Console.WriteLine($"todos: {SeqCount(all.Results)}")
'PUT /todos/1
Await client.PutAsync(New UpdateTodo With { .Id = todo.Id, .Title = "gRPC" })
'GET /todos/1
todo = (Await client.GetAsync(New GetTodo With { .Id = todo.Id })).Result
Console.WriteLine("updated todo Title: {todo.Title}")
'DELETE /todos/1
Await client.DeleteAsync(new DeleteTodo With { .Id = todo.Id })
'GET /todos
all = Await client.GetAsync(new GetTodos())
Console.WriteLine($"todos: {SeqCount(all.Results)}")
End Function
Sub Main(args As String())
Task.WaitAll(TodoExample())
End Sub
End Module
Refer to /src/clients/vb-generic for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Create a new F# App:
$ dotnet new console -lang f#
Add ServiceStack.GrpcClient NuGet Package:
$ dotnet add package ServiceStack.GrpcClient
Add TaskBuilder.fs NuGet Package
$ dotnet add package TaskBuilder.fs
Add TodoWorld DTOs:
$ x fsharp https://todoworld.servicestack.net
Register dto.fs
source file to *.fsproj
:
<ItemGroup>
<Compile Include="dtos.fs"/>
<Compile Include="Program.fs"/>
</ItemGroup>
Use TodoWorld DTOs with generic GrpcServiceClient
to call TodoWorld gRPC Service:
open System
open System.Threading
open System.Threading.Tasks
open ServiceStack
open TodoWorld.ServiceModel
open FSharp.Control.Tasks.V2
let todo () =
task {
ProtoBuf.Grpc.Client.GrpcClientFactory.AllowUnencryptedHttp2 = true
let client = new GrpcServiceClient("http://todoworld.servicestack.net:5054")
let! response = client.GetAsync(new Hello(Name = "gRPC F#"))
printfn "%s" response.Result
}
[<EntryPoint>]
let main argv =
todo().Wait()
0
Override Program.fs
with the above F# Example:
$ x mix todoworld-fs
Run example:
$ dotnet run
open System
open System.Threading
open System.Threading.Tasks
open System.Security.Cryptography.X509Certificates
open ServiceStack
open TodoWorld.ServiceModel
open FSharp.Control.Tasks.V2
let todo () =
task {
let client = new GrpcServiceClient("https://todoworld.servicestack.net:50051",
new X509Certificate2("https://todoworld.servicestack.net/grpc.crt".GetBytesFromUrl()),
GrpcUtils.AllowSelfSignedCertificatesFrom("todoworld.servicestack.net"))
let! response = client.GetAsync(new Hello(Name = "gRPC F#"))
printfn "%s" response.Result
}
[<EntryPoint>]
let main argv =
todo().Wait()
0
Override Program.fs
with the above F# Example:
$ x mix todoworld-fs-ssl
Run example:
$ dotnet run
open System
open System.Collections.Generic
open System.Threading
open System.Threading.Tasks
open ServiceStack
open TodoWorld.ServiceModel
open FSharp.Control.Tasks.V2
let todo () =
let seqCount (c: List<Todo>) = if c <> null then c.Count else 0
task {
// Certificate registration not required when using trusted local development certificate
let client = new GrpcServiceClient("https://localhost:5001")
do! client.PostAsync(new ResetTodos())
//POST /todos
let! t = client.PostAsync(new CreateTodo(Title = "ServiceStack"))
let todo = t.Result;
printfn "new todo Id: %i, Title: %s" todo.Id todo.Title
//GET /todos
let! all = client.GetAsync(new GetTodos())
printfn "todos: %i" (seqCount all.Results)
//GET /todos/1
let! t = client.GetAsync(new GetTodo(Id = todo.Id))
let todo = t.Result;
printfn "get todo Id: %i, Title: %s" todo.Id todo.Title
//GET /todos
let! all = client.GetAsync(new GetTodos())
printfn "todos: %i" (seqCount all.Results)
//PUT /todos/1
do! client.PutAsync(new UpdateTodo(Id = todo.Id, Title = "gRPC"))
//GET /todos/1
let! t = client.GetAsync(new GetTodo(Id = todo.Id))
let todo = t.Result;
printfn "updated todo Title: %s" todo.Title
//DELETE /todos/1
do! client.DeleteAsync(new DeleteTodo(Id = todo.Id))
//GET /todos
let! all = client.GetAsync(new GetTodos())
printfn "todos: %i" (seqCount all.Results)
}
[<EntryPoint>]
let main argv =
todo().Wait()
0
Refer to /src/clients/fsharp-generic for a complete example project.
Visit ServiceStack gRPC docs for more info.
Install x dotnet tool:
$ dotnet tool install --global x
Create a new C# Console App:
$ dotnet new console
Add required NuGet Packages:
$ dotnet add package Google.Protobuf
$ dotnet add package ServiceStack.GrpcClient
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Add protoc generated TodoWorld DTOs and gRPC GrpcServiceClient:
$ x proto-csharp https://todoworld.servicestack.net
Use protoc generated DTOs and GrpcServiceClient
to call TodoWorld gRPC Service:
The smart client registers a ServiceStack Interceptor to enable the richer integration features in ServiceStack
Services as found in ServiceStack's Generic GrpcServiceClient
above, including detailed structured Exception handling,
built-in JWT, Session, Credentials Auth support,
Automatically refreshing Access Tokens, etc.
This ServiceStack Interceptor can be registered using GrpcServiceStack.Client()
when creating the protoc GrpcServicesClient
:
using System;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using ServiceStack;
namespace TodoWorld
{
class Program
{
static async Task Main(string[] args)
{
var client = new GrpcServices.GrpcServicesClient(
GrpcServiceStack.Client("https://todoworld.servicestack.net:50051",
new X509Certificate2("grpc.crt"),
GrpcUtils.AllowSelfSignedCertificatesFrom("todoworld.servicestack.net")));
var response = await client.GetHelloAsync(new Hello { Name = "gRPC C#" });
Console.WriteLine(response.Result);
}
}
}
Override Program.cs
with the above C# Example:
$ x mix todoworld-csharp-smart
Run example:
$ dotnet run
Alternatively clients can opt to use the vanilla protoc generated ServiceClient without any dependency to ServiceStack.GrpcClient which will fallback to gRPC's default behavior of basic error handling with any auth headers needing to be populated manually.
Add required core package dependencies:
$ dotnet add package Grpc.Core
$ dotnet add package Grpc.Net.Client
using System;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
namespace TodoWorld
{
class Program
{
static async Task Main(string[] args)
{
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var client = new GrpcServices.GrpcServicesClient(
GrpcChannel.ForAddress("http://todoworld.servicestack.net:5054"));
var response = await client.GetHelloAsync(new Hello { Name = "gRPC C#" });
Console.WriteLine(response.Result);
}
}
}
Override Program.cs
with the above C# Example:
$ x mix todoworld-csharp
Run example:
$ dotnet run
using System;
using System.Linq;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
namespace TodoWorld
{
class Program
{
static async Task Main(string[] args)
{
var client = new GrpcServices.GrpcServicesClient(
GrpcChannel.ForAddress("https://todoworld.servicestack.net:50051", new GrpcChannelOptions {
HttpClient = new System.Net.Http.HttpClient(new System.Net.Http.HttpClientHandler {
ClientCertificates = { new X509Certificate2("grpc.crt") },
ServerCertificateCustomValidationCallback = (req, cert, certChain, sslErrors) =>
cert.SubjectName.RawData.SequenceEqual(cert.IssuerName.RawData) && // self-signed
cert.GetNameInfo(X509NameType.DnsName, forIssuer:false) == "todoworld.servicestack.net" &&
(sslErrors & ~sslErrors.RemoteCertificateChainErrors) == sslErrors.None // only this
})
}));
var response = await client.GetHelloAsync(new Hello { Name = "gRPC C#" });
Console.WriteLine(response.Result);
}
}
}
Override Program.cs
with the above C# Example:
$ x mix todoworld-csharp-ssl
Run example:
$ dotnet run
using System;
using System.Threading.Tasks;
using Grpc.Net.Client;
using TodoWorld;
namespace CSharp
{
public class Program
{
static async Task Main(string[] args)
{
// Certificate registration not required when using trusted local development certificate
var client = new GrpcServices.GrpcServicesClient(GrpcChannel.ForAddress("https://localhost:5001"));
await client.PostResetTodosAsync(new ResetTodos());
//POST /todos
var todo = (await client.PostCreateTodoAsync(new CreateTodo { Title = "ServiceStack" })).Result;
Console.WriteLine($"new todo Id: {todo.Id}, Title: {todo.Title}");
//GET /todos
var all = await client.CallGetTodosAsync(new GetTodos());
Console.WriteLine($"todos: {all.Results?.Count ?? 0}");
//GET /todos/1
todo = (await client.CallGetTodoAsync(new GetTodo { Id = todo.Id })).Result;
Console.WriteLine($"get todo Id: {todo.Id}, Title: {todo.Title}");
//GET /todos
all = await client.CallGetTodosAsync(new GetTodos());
Console.WriteLine($"todos: {all.Results?.Count ?? 0}");
//PUT /todos/1
await client.PutUpdateTodoAsync(new UpdateTodo { Id = todo.Id, Title = "gRPC" });
//GET /todos/1
todo = (await client.CallGetTodoAsync(new GetTodo { Id = todo.Id })).Result;
Console.WriteLine($"updated todo Title: {todo.Title}");
//DELETE /todos/1
await client.CallDeleteTodoAsync(new DeleteTodo { Id = todo.Id });
//GET /todos
all = await client.CallGetTodosAsync(new GetTodos());
Console.WriteLine($"todos: {all.Results?.Count ?? 0}");
}
}
}
Refer to /src/clients/csharp for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Create a new Swift Console App:
$ swift package init --type executable
Add grpc-swift
Swift Package in Package.swift
and "GRPC" dependency to each target:
import PackageDescription
let package = Package(
name: "TodoWorld",
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.8")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "TodoWorld",
dependencies: ["GRPC"]),
.testTarget(
name: "TodoWorldTests",
dependencies: ["TodoWorld","GRPC"]),
]
)
Add protoc generated TodoWorld DTOs and gRPC GrpcServiceClient:
$ cd Sources/TodoWorld
$ x proto-swift https://todoworld.servicestack.net
Use protoc generated DTOs and GrpcServiceClient
to call TodoWorld gRPC Service:
import Foundation
import GRPC
import NIO
import NIOSSL
do {
let configuration = ClientConnection.Configuration(
target: .hostAndPort("todoworld.servicestack.net", 5054),
eventLoopGroup: MultiThreadedEventLoopGroup(numberOfThreads: 1)
)
let client = GrpcServicesServiceClient(connection: ClientConnection(configuration: configuration))
var request = Hello()
request.name = "gRPC Swift"
let response = try client.getHello(request).response.wait().result
print(response)
} catch {
print("ERROR\n\(error)")
}
Override main.swift
with the above Swift Example:
$ x mix todoworld-swift
Run example:
$ swift run
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Use certificate when initializing ClientConnection.Configuration:
import Foundation
import GRPC
import NIO
import NIOSSL
do {
let configuration = ClientConnection.Configuration(
target: .hostAndPort("todoworld.servicestack.net", 50051),
eventLoopGroup: MultiThreadedEventLoopGroup(numberOfThreads: 1),
tls: .init(certificateChain: try NIOSSLCertificate.fromPEMFile("grpc.crt").map { .certificate($0) },
certificateVerification: .none) //TODO enable SSL verification
)
let client = GrpcServicesServiceClient(connection: ClientConnection(configuration: configuration))
var request = Hello()
request.name = "gRPC Swift"
let response = try client.getHello(request).response.wait().result
print(response)
} catch {
print("ERROR\n\(error)")
}
Override main.swift
with the above Swift Example:
$ x mix todoworld-swift-ssl
Run example:
$ swift run
import Foundation
import GRPC
import NIO
import NIOSSL
do {
let configuration = ClientConnection.Configuration(
target: .hostAndPort("localhost", 5001),
eventLoopGroup: MultiThreadedEventLoopGroup(numberOfThreads: 1),
tls: .init(certificateChain: try NIOSSLCertificate.fromPEMFile("dev.crt").map { .certificate($0) })
)
let client = GrpcServicesServiceClient(connection: ClientConnection(configuration: configuration))
print("TODO EXAMPLE")
_ = try client.postResetTodos(ResetTodos()).response.wait()
//POST /todos
var createTodo = CreateTodo()
createTodo.title = "ServiceStack"
var todo = try client.postCreateTodo(createTodo).response.wait().result
print("new todo Id: \(todo.id), Title: \(todo.title)")
//GET /todos
var all = try client.callGetTodos(GetTodos()).response.wait()
print("todos: \(all.results.count)")
//GET /todos/1
var getTodo = GetTodo()
getTodo.id = todo.id
todo = try client.callGetTodo(getTodo).response.wait().result
print("get todo Id: \(todo.id), Title: \(todo.title)")
//PUT /todos/1
var updateTodo = UpdateTodo()
updateTodo.id = todo.id
updateTodo.title = "gRPC"
_ = try client.putUpdateTodo(updateTodo).response.wait()
//GET /todos/1
todo = try client.callGetTodo(getTodo).response.wait().result
print("get todo Id: \(todo.id), Title: \(todo.title)")
//DELETE /todos/1
var deleteTodo = DeleteTodo()
deleteTodo.id = todo.id
_ = try client.callDeleteTodo(deleteTodo).response.wait()
//GET /todos
all = try client.callGetTodos(GetTodos()).response.wait()
print("todos: \(all.results.count)")
} catch {
print("ERROR\n\(error)")
}
Refer to /src/clients/swift for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Create a new Gradle Java Console App (example uses IntelliJ IDEA Community):
Update build.gradle with required dependencies:
plugins {
id 'java'
id 'com.google.protobuf' version '0.8.8'
id 'idea'
}
group 'org.example'
version '1.0-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
def grpcVersion = '1.25.0'
def nettyTcNativeVersion = '2.0.26.Final'
def protobufVersion = '3.11.0'
dependencies {
implementation "io.grpc:grpc-netty:${grpcVersion}"
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"
compileOnly "javax.annotation:javax.annotation-api:1.2"
implementation "com.google.protobuf:protobuf-java-util:${protobufVersion}"
runtimeOnly "io.netty:netty-tcnative-boringssl-static:${nettyTcNativeVersion}"
testImplementation "io.grpc:grpc-testing:${grpcVersion}"
testImplementation "junit:junit:4.12"
testImplementation "org.mockito:mockito-core:2.28.2"
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
}
Add protoc generated TodoWorld DTOs and gRPC GrpcServicesBlockingStub:
$ cd src\main\java
$ x proto-java https://todoworld.servicestack.net
Use protoc generated DTOs and GrpcServiceClient
to call TodoWorld gRPC Service:
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
public class Program {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder.forAddress(
"todoworld.servicestack.net", 5054).usePlaintext().build();
GrpcServicesGrpc.GrpcServicesBlockingStub client = GrpcServicesGrpc.newBlockingStub(channel);
Services.Hello request = Services.Hello.newBuilder().setName("gRPC Java").build();
String result = client.getHello(request).getResult();
System.out.println(result);
}
}
Create Program.java
from the above Java Example:
$ x mix todoworld-java
Run example with Shift+F10
:
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services into resources folder:
$ x get https://todoworld.servicestack.net/grpc.crt -out ../resources
Use certificate when initializing gRPC Channel:
import io.grpc.ManagedChannel;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyChannelBuilder;
import java.io.File;
public class Program {
public static void main(String[] args) throws javax.net.ssl.SSLException {
ManagedChannel channel = NettyChannelBuilder.forAddress("todoworld.servicestack.net", 50051)
.sslContext(GrpcSslContexts.forClient()
.trustManager(new File(Program.class.getClassLoader().getResource("grpc.crt").getFile()))
.build())
.build();
GrpcServicesGrpc.GrpcServicesBlockingStub client = GrpcServicesGrpc.newBlockingStub(channel);
Services.Hello request = Services.Hello.newBuilder().setName("gRPC Java").build();
String result = client.getHello(request).getResult();
System.out.println(result);
}
}
Override Program.java
with the above Java Example:
$ x mix todoworld-java-ssl
Run example with Shift+F10
:
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyChannelBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import javax.net.ssl.SSLException;
import static java.lang.System.out;
class Program {
public static void main(String[] args) throws SSLException {
ManagedChannel channel = NettyChannelBuilder.forAddress("localhost", 5001)
.sslContext(GrpcSslContexts.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE) // allow localhost self-signed certificates
.build())
.build();
GrpcServicesGrpc.GrpcServicesBlockingStub client = GrpcServicesGrpc.newBlockingStub(channel);
out.println("TODO EXAMPLE");
client.postResetTodos(Services.ResetTodos.newBuilder().build());
//POST /todos
Services.Todo todo = client.postCreateTodo(Services.CreateTodo.newBuilder().setTitle("ServiceStack").build()).getResult();
out.println("new todo Id: " + todo.getId() + ", Title: " + todo.getTitle());
//GET /todos
Services.GetTodosResponse all = client.callGetTodos(Services.GetTodos.newBuilder().build());
out.println("todos: " + all.getResultsCount());
//GET /todos/1
todo = (client.callGetTodo(Services.GetTodo.newBuilder().setId(todo.getId()).build())).getResult();
out.println("get todo Id: " + todo.getId() + ", Title: " + todo.getTitle());
//PUT /todos/1
client.putUpdateTodo(Services.UpdateTodo.newBuilder().setId(todo.getId()).setTitle("gRPC").build());
//GET /todos/1
todo = (client.callGetTodo(Services.GetTodo.newBuilder().setId(todo.getId()).build())).getResult();
out.println("get todo Id: " + todo.getId() + ", Title: " + todo.getTitle());
//DELETE /todos/1
client.callDeleteTodo(Services.DeleteTodo.newBuilder().setId(todo.getId()).build());
//GET /todos
all = client.callGetTodos(Services.GetTodos.newBuilder().build());
out.println("todos: " + all.getResultsCount());
}
}
Refer to /src/clients/java for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Install stagehand:
$ pub global activate stagehand
Create a new Dart Console App:
$ stagehand console-full
Add required dependencies to pubspec.yaml:
dependencies:
fixnum: ^0.10.11
async: ^2.2.0
protobuf: ^1.0.1
grpc: ^2.1.3
Install dependencies:
$ pub get
Add protoc generated TodoWorld DTOs and gRPC GrpcServiceClient to lib/
folder:
$ x proto-dart https://todoworld.servicestack.net -out lib
Use protoc generated DTOs and GrpcServiceClient
to call TodoWorld gRPC Service in bin/main.dart
:
import 'dart:io';
import 'package:grpc/grpc.dart';
import 'package:TodoWorld/services.pb.dart';
import 'package:TodoWorld/services.pbgrpc.dart';
void main(List<String> args) async {
var client = GrpcServicesClient(ClientChannel('todoworld.servicestack.net', port:5054,
options:ChannelOptions(credentials: ChannelCredentials.insecure())));
var response = await client.getHello(Hello()..name = 'gRPC Dart');
print(response.result);
exit(0);
}
Override bin/main.dart
with the above Dart Example:
$ x mix todoworld-dart -out bin
Run example:
$ dart run
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Use certificate when initializing GrpcServicesClient
:
import 'dart:io';
import 'package:grpc/grpc.dart';
import 'package:TodoWorld/services.pb.dart';
import 'package:TodoWorld/services.pbgrpc.dart';
void main(List<String> args) async {
var client = GrpcServicesClient(ClientChannel('todoworld.servicestack.net', port:50051,
options:ChannelOptions(credentials: ChannelCredentials.secure(
certificates: File('grpc.crt').readAsBytesSync(),
authority: 'todoworld.servicestack.net'))));
var response = await client.getHello(Hello()..name = 'gRPC Dart');
print(response.result);
exit(0);
}
Override bin/main.dart
with the above Dart Example:
$ x mix todoworld-dart-ssl -out bin
Run example:
$ dart run
import 'dart:convert';
import 'dart:io';
import 'package:grpc/grpc.dart';
import 'package:todoworld/services.pb.dart';
import 'package:todoworld/services.pbgrpc.dart';
GrpcServicesClient createClient() {
return GrpcServicesClient(ClientChannel('localhost', port:5001,
options:ChannelOptions(credentials: ChannelCredentials.secure(
certificates: File('../certs/dev.crt').readAsBytesSync(),
authority: 'localhost'))));
}
void main(List<String> args) async {
var client = createClient();
await client.postResetTodos(ResetTodos());
//POST /todos
var todo = (await client.postCreateTodo(CreateTodo()..title = 'ServiceStack')).result;
print('new todo Id: ${todo.id}, Title: ${todo.title}');
//GET /todos
var all = await client.callGetTodos(GetTodos());
print('todos: ${all.results.length}');
//GET /todos/1
todo = (await client.callGetTodo(GetTodo()..id = todo.id)).result;
print('get todo Id: ${todo.id}, Title: ${todo.title}');
//PUT /todos/1
await client.putUpdateTodo(UpdateTodo()..id = todo.id..title = 'gRPC');
//GET /todos/1
todo = (await client.callGetTodo(GetTodo()..id = todo.id)).result;
print('get todo Id: ${todo.id}, Title: ${todo.title}');
//DELETE /todos/1
await client.callDeleteTodo(DeleteTodo()..id = todo.id);
//GET /todos
all = await client.callGetTodos(GetTodos());
print('todos: ${all.results.length}');
}
Consume ServiceStack Server Events from gRPC Server Stream API:
var stream = client.serverStreamServerEvents(StreamServerEvents()..channels.add('todos'));
await for (var r in stream) {
var obj = jsonDecode(r.json);
if (r.selector.startsWith('todos')) {
if (obj is Map) {
print('EVENT ${r.selector} [${r.channel}]: #${obj['id']} ${obj['title']}');
} else {
print('EVENT ${r.selector} [${r.channel}]: ${obj}');
}
} else {
print('EVENT ${r.selector} ${r.channels}: #${obj['userId']} ${obj['displayName']}');
}
}
var stream = client.serverStreamFiles(StreamFiles()..paths.addAll([
'/js/ss-utils.js',
'/js/hot-loader.js',
'/js/hot-fileloader.js',
]));
await for (var file in stream) {
var text = utf8.decode(file.body);
print('FILE ${file.name} (${file.length}): ${text.substring(0, text.length < 50 ? text.length : 50)} ...');
}
Refer to /src/clients/dart for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Create new TodoWorld Go module:
$ go mod init TodoWorld
Add protoc generated TodoWorld DTOs and gRPC GrpcServiceClient to services/
folder:
$ md services
$ x proto-go https://todoworld.servicestack.net -out services
Create a new Go Console App in client\main.go
:
package main
import (
context "context"
"fmt"
"log"
"google.golang.org/grpc"
pb "TodoWorld/services"
"time"
)
func main() {
conn, err := grpc.Dial("todoworld.servicestack.net:5054", grpc.WithInsecure())
if err != nil {
log.Fatalf("fail to dial: %v", err)
}
defer conn.Close()
client := pb.NewGrpcServicesClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
response, err := client.GetHello(ctx, &pb.Hello{Name: "gRPC Go"})
if err != nil {
log.Fatalf("GetHello: %v", err)
}
fmt.Println(response.Result)
}
Alternatively above Go example can be created with:
$ md client
$ x mix todoworld-go -out client
Run example:
$ go run client\main.go
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Use certificate when initializing NewGrpcServicesClient
:
package main
import (
context "context"
"fmt"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
pb "TodoWorld/services"
"time"
)
func main() {
creds, err := credentials.NewClientTLSFromFile("grpc.crt", "")
if err != nil {
log.Fatalf("could not process the credentials: %v", err)
}
conn, err := grpc.Dial("todoworld.servicestack.net:50051", grpc.WithTransportCredentials(creds))
if err != nil {
log.Fatalf("fail to dial: %v", err)
}
defer conn.Close()
client := pb.NewGrpcServicesClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
response, err := client.GetHello(ctx, &pb.Hello{Name: "gRPC Go"})
if err != nil {
log.Fatalf("GetHello: %v", err)
}
fmt.Println(response.Result)
}
Override client/main.go
with the above Go Example:
$ x mix todoworld-go-ssl -out client
Run example:
$ go run client\main.go
package main
import (
context "context"
"fmt"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"time"
pb "todoworld/services"
)
func main() {
// Load the certificates from disk
creds, err := credentials.NewClientTLSFromFile("dev.crt", "localhost:5001")
if err != nil {
log.Fatalf("could not process the credentials: %v", err)
}
conn, err := grpc.Dial(address, grpc.WithTransportCredentials(creds))
if err != nil {
log.Fatalf("fail to dial: %v", err)
}
defer conn.Close()
client := pb.NewGrpcServicesClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
_, err = client.PostResetTodos(ctx, &pb.ResetTodos{})
if err != nil {
log.Fatalf("PostResetTodos: %v", err)
}
fmt.Println("TODO EXAMPLE")
//POST /todos
r1, err := client.PostCreateTodo(ctx, &pb.CreateTodo{Title: "ServiceStack"})
if err != nil {
log.Fatalf("PostCreateTodo: %v", err)
}
todo := r1.Result
fmt.Println("new todo Id:", todo.Id, "Title:", todo.Title)
//GET /todos
all, err := client.CallGetTodos(ctx, &pb.GetTodos{})
if err != nil {
log.Fatalf("CallGetTodos: %v", err)
}
fmt.Println("todos:", len(all.GetResults()))
//GET /todos/1
r2, err := client.CallGetTodo(ctx, &pb.GetTodo{Id: todo.Id})
if err != nil {
log.Fatalf("CallGetTodo: %v", err)
}
todo = r2.Result
fmt.Println("get todo Id:", todo.Id, "Title:", todo.Title)
//PUT /todos/1
_, err = client.PutUpdateTodo(ctx, &pb.UpdateTodo{Id: todo.Id, Title: "gRPC"})
if err != nil {
log.Fatalf("PutUpdateTodo: %v", err)
}
//GET /todos/1
r2, err = client.CallGetTodo(ctx, &pb.GetTodo{Id: todo.Id})
if err != nil {
log.Fatalf("CallGetTodo: %v", err)
}
todo = r2.Result
fmt.Println("get todo Id:", todo.Id, "Title:", todo.Title)
//DELETE /todos/1
_, err = client.CallDeleteTodo(ctx, &pb.DeleteTodo{Id: todo.Id})
if err != nil {
log.Fatalf("CallDeleteTodo: %v", err)
}
//GET /todos
all, err = client.CallGetTodos(ctx, &pb.GetTodos{})
if err != nil {
log.Fatalf("CallGetTodos: %v", err)
}
fmt.Println("todos:", len(all.GetResults()))
}
Refer to /src/clients/go for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Create npm package.json:
$ npm init
Add dependencies:
{
"name": "todoworld-grpc",
"version": "0.1.0",
"description": "gRPC node.js Todo World Example",
"devDependencies": {
"@grpc/proto-loader": "^0.1.0",
"google-protobuf": "^3.6.1",
"grpc": "^1.11.0",
"webpack": "^4.16.5",
"webpack-cli": "^3.1.0"
}
}
Install dependencies:
$ npm install
Add protoc generated TodoWorld DTOs and gRPC Service Client:
$ x proto-js-node https://todoworld.servicestack.net
Use protoc generated DTOs and GrpcServicesClient
to call TodoWorld gRPC Service in index.js
:
const { Hello } = require('./services_pb.js');
const { GrpcServicesClient } = require('./services_grpc_pb.js');
const grpc = require('grpc');
const { promisify } = require('util');
async function main() {
const client = new GrpcServicesClient('todoworld.servicestack.net:5054',
grpc.credentials.createInsecure());
// Convert gRPC's callback APIs to await friendly promises
const { getHello } = promisifyAll(client);
let request = new Hello();
request.setName("gRPC Node.js");
let response = await getHello(request);
console.log(response.getResult());
}
function promisifyAll(client) {
const to = {};
for (var k in client) {
if (typeof client[k] != 'function') continue;
to[k] = promisify(client[k].bind(client));
}
return to;
}
main();
Create index.js
with the above Node.js Example:
$ x mix todoworld-node
Run example:
$ node --no-deprecation index.js
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Use certificate when initializing GrpcServicesClient
:
const { Hello } = require('./services_pb.js');
const { GrpcServicesClient } = require('./services_grpc_pb.js');
const grpc = require('grpc');
const { promisify } = require('util');
const fs = require('fs');
async function main() {
const client = new GrpcServicesClient('todoworld.servicestack.net:50051',
grpc.credentials.createSsl(fs.readFileSync('grpc.crt')));
// Convert gRPC's callback APIs to await friendly promises
const { getHello } = promisifyAll(client);
let request = new Hello();
request.setName("gRPC Node.js");
let response = await getHello(request);
console.log(response.getResult());
}
function promisifyAll(client) {
const to = {};
for (var k in client) {
if (typeof client[k] != 'function') continue;
to[k] = promisify(client[k].bind(client));
}
return to;
}
main();
Override index.js
with the above Node.js Example:
$ x mix todoworld-node-ssl
Run example:
$ node --no-deprecation index.js
const {
ResetTodos,
CreateTodo,
GetTodo,
GetTodos,
UpdateTodo,
DeleteTodo,
} = require('./services_pb.js');
const { GrpcServicesClient } = require('./services_grpc_pb.js');
const grpc = require('grpc');
const { promisify } = require('util');
const fs = require('fs');
async function main() {
const client = new GrpcServicesClient('localhost:5001',
grpc.credentials.createSsl(fs.readFileSync('../certs/dev.crt')));
// Convert gRPC's callback APIs to await friendly promises
const {
postResetTodos,
postCreateTodo,
callGetTodos,
callGetTodo,
putUpdateTodo,
callDeleteTodo,
} = promisifyAll(client);
console.log('TODO EXAMPLE');
await postResetTodos(new ResetTodos());
//POST /todos
request = new CreateTodo();
request.setTitle('ServiceStack');
var todo = (await postCreateTodo(request)).getResult();
console.log(`new todo Id: ${todo.getId()}, Title: ${todo.getTitle()}`);
//GET /todos
var all = await callGetTodos(new GetTodos());
console.log(`todos: ${all.getResultsList().length}`);
//GET /todos/1
request = new GetTodo();
request.setId(todo.getId());
todo = (await callGetTodo(request)).getResult();
console.log(`get todo Id: ${todo.getId()}, Title: ${todo.getTitle()}`);
//PUT /todos/1
request = new UpdateTodo();
request.setId(todo.getId());
request.setTitle('gRPC');
await putUpdateTodo(request);
//GET /todos/1
request = new GetTodo();
request.setId(todo.getId());
todo = (await callGetTodo(request)).getResult();
console.log(`get todo Id: ${todo.getId()}, Title: ${todo.getTitle()}`);
//DELETE /todos/1
request = new DeleteTodo();
request.setId(todo.getId());
await callDeleteTodo(request);
//GET /todos
all = await callGetTodos(new GetTodos());
console.log(`todos: ${all.getResultsList().length}`);
}
// Necessary until gRPC provides a native async friendly solution https://github.com/grpc/grpc-node/issues/54
function promisifyAll(client) {
const to = {};
for (var k in client) {
if (typeof client[k] != 'function') continue;
to[k] = promisify(client[k].bind(client));
}
return to;
}
main();
Refer to /src/clients/js-node for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Install grpcio-tools:
$ pip install grpcio-tools
Add protoc generated TodoWorld DTOs and gRPC Service Client:
$ x proto-python https://todoworld.servicestack.net
Use protoc generated DTOs and GrpcServicesStub
to call TodoWorld gRPC Service in main.py
:
import grpc
import services_pb2
import services_pb2_grpc
def run():
with grpc.insecure_channel('todoworld.servicestack.net:5054') as channel:
client = services_pb2_grpc.GrpcServicesStub(channel)
response = client.GetHello(services_pb2.Hello(Name="gRPC Python"))
print(response.Result)
if __name__ == '__main__':
run()
Create main.py
with the above Python Example:
$ x mix todoworld-python
Run example:
$ python main.py
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Use certificate when initializing GrpcServicesStub
:
import grpc
import services_pb2
import services_pb2_grpc
def run():
with open('grpc.crt', 'rb') as f:
credentials = grpc.ssl_channel_credentials(f.read())
with grpc.secure_channel('todoworld.servicestack.net:50051', credentials) as channel:
client = services_pb2_grpc.GrpcServicesStub(channel)
response = client.GetHello(services_pb2.Hello(Name="gRPC Python"))
print(response.Result)
if __name__ == '__main__':
run()
Override main.py
with the above Python Example:
$ x mix todoworld-python-ssl
Run example:
$ python main.py
import grpc
import services_pb2
import services_pb2_grpc
def run():
with open('dev.crt', 'rb') as f:
cer = f.read()
credentials = grpc.ssl_channel_credentials(cer)
with grpc.secure_channel('localhost:5001', credentials) as channel:
client = services_pb2_grpc.GrpcServicesStub(channel)
client.PostResetTodos(services_pb2.ResetTodos())
print("TODO EXAMPLE")
# POST /todos
todo = client.PostCreateTodo(services_pb2.CreateTodo(Title="ServiceStack")).Result
print(f'new todo Id: {todo.Id}, Title: {todo.Title}')
# GET /todos
all = client.CallGetTodos(services_pb2.GetTodos())
print(f'todos: {len(all.Results)}')
# GET /todos/1
todo = (client.CallGetTodo(services_pb2.GetTodo(Id=todo.Id))).Result
print(f'get todo Id: {todo.Id}, Title: {todo.Title}')
# PUT /todos/1
client.PutUpdateTodo(services_pb2.UpdateTodo(Id=todo.Id, Title='gRPC'))
# GET /todos/1
todo = (client.CallGetTodo(services_pb2.GetTodo(Id=todo.Id))).Result
print(f'get todo Id: {todo.Id}, Title: {todo.Title}')
# DELETE /todos/1
client.CallDeleteTodo(services_pb2.DeleteTodo(Id=todo.Id))
# GET /todos
all = client.CallGetTodos(services_pb2.GetTodos())
print(f'todos: {len(all.Results)}')
if __name__ == '__main__':
run()
Refer to /src/clients/python for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Install required gems:
$ gem install grpc bundler
Create todoworld.gemspec:
# -*- ruby -*-
# encoding: utf-8
Gem::Specification.new do |s|
s.name = 'todoworld'
s.version = '1.0.0'
s.summary = 'gRPC Ruby TodoWorld Example'
s.description = 'Simple TodoWorld demo of using gRPC from Ruby'
s.files = `git ls-files -- *`.split("\n")
s.executables = `git ls-files -- client.rb`.split("\n").map do |f|
File.basename(f)
end
s.require_paths = ['lib']
s.platform = Gem::Platform::RUBY
s.add_dependency 'grpc', '~> 1.0'
s.add_dependency 'multi_json', '~> 1.13.1'
s.add_development_dependency 'bundler', '~> 2.0'
end
Generate Gemfile
and install dependencies:
$ bundle init
$ bundle install
Add protoc generated TodoWorld DTOs and gRPC Service Client:
$ md lib
$ x proto-ruby https://todoworld.servicestack.net -out lib
Use protoc generated DTOs and GrpcServicesStub
to call TodoWorld gRPC Service in main.rb
:
#!/usr/bin/env ruby
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'services_pb'
require 'services_services_pb'
def main
client = GrpcServices::Stub.new('todoworld.servicestack.net:5054',
:this_channel_is_insecure)
response = client.get_hello(Hello.new(Name:'gRPC Ruby'))
puts response.Result
end
main
Create main.rb
with the above Ruby Example:
$ x mix todoworld-ruby
Run example:
$ main.rb
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Use certificate when initializing GrpcServicesStub
:
#!/usr/bin/env ruby
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'services_pb'
require 'services_services_pb'
def main
credentials = GRPC::Core::ChannelCredentials.new(File.read('grpc.crt'))
client = GrpcServices::Stub.new('todoworld.servicestack.net:50051', credentials)
response = client.get_hello(Hello.new(Name:'gRPC Ruby'))
puts response.Result
end
main
Override main.rb
with the above Ruby Example:
$ x mix todoworld-ruby-ssl
Run example:
$ ruby main.rb
#!/usr/bin/env ruby
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'services_pb'
require 'services_services_pb'
def main
credentials = GRPC::Core::ChannelCredentials.new(File.read('dev.crt'))
client = GrpcServices::Stub.new('localhost:5001', credentials)
client.post_reset_todos(ResetTodos.new())
puts "TODO EXAMPLE"
# POST /todos
todo = client.post_create_todo(CreateTodo.new(Title:"ServiceStack")).Result
puts "new todo Id: #{todo.Id}, Title: #{todo.Title}"
# GET /todos
all = client.call_get_todos(GetTodos.new())
puts "todos: #{all.Results.length}"
# GET /todos/1
todo = (client.call_get_todo(GetTodo.new(Id:todo.Id))).Result
puts "get todo Id: #{todo.Id}, Title: #{todo.Title}"
# PUT /todos/1
client.put_update_todo(UpdateTodo.new(Id:todo.Id, Title:'gRPC'))
# GET /todos/1
todo = (client.call_get_todo(GetTodo.new(Id:todo.Id))).Result
puts "get todo Id: #{todo.Id}, Title: #{todo.Title}"
# DELETE /todos/1
client.call_delete_todo(DeleteTodo.new(Id:todo.Id))
# GET /todos
all = client.call_get_todos(GetTodos.new())
puts "todos: #{all.Results.length}"
end
main
Refer to /src/clients/ruby for a complete example project.
This requires php
>= 5.5, pecl
, composer
Install the grpc
extension:
$ [sudo] pecl install grpc
https://windows.php.net/downloads/pecl/releases/grpc/
The PHP extension filename is in the following format:
php_grpc-{GRPC_VERSION}-{PHP_VERSION}-{THREAD_SAFETY}-{VC++_RUNTIME}-{CPU_ARCH}.zip
Select appropriate version for your OS and copy to {PHP_HOME}\ext
, then modify your php.ini file to include extension=grpc
.
Install x dotnet tool:
$ dotnet tool install --global x
Add required dependencies to composer.json:
{
"name": "servicestack/grpc-todoworld",
"description": "Simple TodoWorld demo of using gRPC from PHP",
"require": {
"grpc/grpc": "^v1.3.0",
"google/protobuf": "^v3.3.0"
},
"autoload": {
"psr-4": {
"": "route_guide/"
}
}
}
Install dependencies:
$ composer install
Add protoc generated TodoWorld DTOs and gRPC GrpcServiceClient:
$ x proto-php https://todoworld.servicestack.net
Use protoc generated DTOs and GrpcServiceClient
to call TodoWorld gRPC Service in main.php
:
<?php
require dirname(__FILE__).'/vendor/autoload.php';
@include_once dirname(__FILE__).'/GPBMetadata/Services.php';
@include_once dirname(__FILE__).'/TodoWorld/GrpcServicesClient.php';
@include_once dirname(__FILE__).'/TodoWorld/Hello.php';
@include_once dirname(__FILE__).'/TodoWorld/HelloResponse.php';
$client = new TodoWorld\GrpcServicesClient('todoworld.servicestack.net:5054', [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
$request = new TodoWorld\Hello();
$request->setName("gRPC PHP");
list($reply, $status) = $client->GetHello($request)->wait();
if ($status->code !== Grpc\STATUS_OK) {
echo "Call did not complete successfully. Status object:\n";
var_dump($status);
exit(1);
}
echo $reply->getResult();
Override main.php
with the above PHP Example:
$ x mix todoworld-php
Run example:
$ php main.php
Download TodoWorld SSL Certificate used for its gRPC HTTP/2 Services:
$ x get https://todoworld.servicestack.net/grpc.crt
Use certificate when initializing GrpcServicesClient
:
<?php
require dirname(__FILE__).'/vendor/autoload.php';
@include_once dirname(__FILE__).'/GPBMetadata/Services.php';
@include_once dirname(__FILE__).'/TodoWorld/GrpcServicesClient.php';
@include_once dirname(__FILE__).'/TodoWorld/Hello.php';
@include_once dirname(__FILE__).'/TodoWorld/HelloResponse.php';
$client = new TodoWorld\GrpcServicesClient('todoworld.servicestack.net:50051', [
'credentials' => Grpc\ChannelCredentials::createSsl(file_get_contents('grpc.crt')),
]);
$request = new TodoWorld\Hello();
$request->setName("gRPC PHP");
list($reply, $status) = $client->GetHello($request)->wait();
if ($status->code !== Grpc\STATUS_OK) {
echo "Call did not complete successfully. Status object:\n";
var_dump($status);
exit(1);
}
echo $reply->getResult();
Override main.php
with the above PHP Example:
$ x mix todoworld-php-ssl
Run example:
$ php main.php
<?php
require dirname(__FILE__).'/vendor/autoload.php';
@include_once dirname(__FILE__).'/GPBMetadata/Services.php';
@include_once dirname(__FILE__).'/TodoWorld/GrpcServicesClient.php';
@include_once dirname(__FILE__).'/TodoWorld/EmptyResponse.php';
@include_once dirname(__FILE__).'/TodoWorld/Hello.php';
@include_once dirname(__FILE__).'/TodoWorld/HelloResponse.php';
@include_once dirname(__FILE__).'/TodoWorld/Todo.php';
@include_once dirname(__FILE__).'/TodoWorld/ResetTodos.php';
@include_once dirname(__FILE__).'/TodoWorld/CreateTodo.php';
@include_once dirname(__FILE__).'/TodoWorld/CreateTodoResponse.php';
@include_once dirname(__FILE__).'/TodoWorld/GetTodo.php';
@include_once dirname(__FILE__).'/TodoWorld/GetTodoResponse.php';
@include_once dirname(__FILE__).'/TodoWorld/GetTodos.php';
@include_once dirname(__FILE__).'/TodoWorld/GetTodosResponse.php';
@include_once dirname(__FILE__).'/TodoWorld/UpdateTodo.php';
@include_once dirname(__FILE__).'/TodoWorld/UpdateTodoResponse.php';
@include_once dirname(__FILE__).'/TodoWorld/DeleteTodo.php';
@include_once dirname(__FILE__).'/TodoWorld/DeleteTodoResponse.php';
$client = new TodoWorld\GrpcServicesClient('localhost:5001', [
'credentials' => Grpc\ChannelCredentials::createSsl(file_get_contents(dirname(__FILE__).'dev.crt')),
]);
global $client;
function client() { return $GLOBALS['client']; }
function assertStatus($status)
{
if ($status->code !== Grpc\STATUS_OK) {
echo "Call did not complete successfully. Status object:\n";
var_dump($status);
exit(1);
}
}
function hello($name)
{
$request = new TodoWorld\Hello();
$request->setName($name);
list($reply, $status) = client()->GetHello($request)->wait();
assertStatus($status);
return $reply->getResult();
}
// echo hello("World") . "\n";
list($reply, $status) = $client->PostResetTodos(new TodoWorld\ResetTodos())->wait();
assertStatus($status);
//POST /todos
$request = new TodoWorld\CreateTodo();
$request->setTitle("ServiceStack");
list($reply, $status) = $client->PostCreateTodo($request)->wait();
assertStatus($status);
$todo = $reply->getResult();
echo "new todo Id: " . $todo->getId() . ", Title: " . $todo->getTitle() . "\n";
//GET /todos
list($reply, $status) = $client->CallGetTodos(new TodoWorld\GetTodos())->wait();
assertStatus($status);
echo "todos: " . count($reply->getResults()) . "\n";
//GET /todos/1
$request = new TodoWorld\GetTodo();
$request->setId($todo->getId());
list($reply, $status) = $client->CallGetTodo($request)->wait();
assertStatus($status);
$todo = $reply->getResult();
echo "get todo Id: " . $todo->getId() . ", Title: " . $todo->getTitle() . "\n";
//PUT /todos/1
$request = new TodoWorld\UpdateTodo();
$request->setId($todo->getId());
$request->setTitle("gRPC");
list($reply, $status) = $client->PutUpdateTodo($request)->wait();
assertStatus($status);
//GET /todos/1
$request = new TodoWorld\GetTodo();
$request->setId($todo->getId());
list($reply, $status) = $client->CallGetTodo($request)->wait();
assertStatus($status);
$todo = $reply->getResult();
echo "get todo Id: " . $todo->getId() . ", Title: " . $todo->getTitle() . "\n";
//DELETE /todos/1
$request = new TodoWorld\DeleteTodo();
$request->setId($todo->getId());
list($reply, $status) = $client->CallDeleteTodo($request)->wait();
assertStatus($status);
//GET /todos
list($reply, $status) = $client->CallGetTodos(new TodoWorld\GetTodos())->wait();
assertStatus($status);
echo "todos: " . count($reply->getResults()) . "\n";
Refer to /src/clients/php for a complete example project.
Install x dotnet tool:
$ dotnet tool install --global x
Create a new Flutter project with Android Studio:
Add protoc generated TodoWorld DTOs and gRPC GrpcServiceClient to lib/
folder:
$ x proto-dart https://todoworld.servicestack.net -out lib
Add required dependencies to pubspec.yaml:
dependencies:
fixnum: ^0.10.11
async: ^2.2.0
protobuf: ^1.0.1
grpc: ^2.1.3
Install dependencies by running pub get
or clicking on Get Dependencies link in the IDE:
Use protoc generated DTOs and GrpcServiceClient
to call TodoWorld gRPC Service in _MyHomePageState
class in bin/main.dart
:
import 'package:flutter/material.dart';
import 'package:flutter_grpc/services.pbgrpc.dart';
import 'package:grpc/grpc.dart';
//...
class _MyHomePageState extends State<MyHomePage> {
String result = '';
GrpcServicesClient client = GrpcServicesClient(
ClientChannel('todoworld.servicestack.net', port:50054,
options:ChannelOptions(credentials: ChannelCredentials.insecure())));
void _callGrpcService() async {
var response = await client.getHello(Hello()..name="Flutter gRPC");
setState(() {
result = response.result;
});
}
//...
}
Capture the result gRPC API request in the result
String then change the Widget build()
to
display that instead of _counter
then update the floatingActionButton
to call your _callGrpcService
method instead:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'gRPC Service Example:',
),
Text(
'$result',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _callGrpcService,
tooltip: 'gRPC Service Example',
child: Icon(Icons.play_arrow),
),
);
}
With Flutter's live-reload capability you should be able to see your changes instantly in the Android emulator where clicking the icon should display the result of your plain-text gRPC Service Request:
To use gRPC SSL we'll need a copy of our gRPC's Service SSL Certificate which we can make available to our
Flutter App by saving it to our App's assets
directory:
$ md assets
$ x get https://todoworld.servicestack.net/grpc.crt -out assets
As loading assets is an asynchronous operation we'll need to preload it either by loading it in main()
and
passing it as an attribute down to all our components or we can load it in our State widget's initState()
method:
class _MyHomePageState extends State<MyHomePage> {
String result = '';
GrpcServicesClient client;
@override
void initState() {
super.initState();
DefaultAssetBundle.of(context).load("assets/grpc.crt").then((bytes) => setState(() {
client = GrpcServicesClient(
ClientChannel('todoworld.servicestack.net', port:50051,
options:ChannelOptions(credentials: ChannelCredentials.secure(
certificates: bytes.buffer.asUint8List(),
authority: 'todoworld.servicestack.net'
))));
}));
}
void _callGrpcService() async {
var response = await client.getHello(Hello()..name="gRPC SSL");
setState(() {
result = response.result;
});
}
//...
}
You'll also need to update the port to refer to the gRPC SSL endpoint, update your Hello
request
so we can verify the result is from the new gRPC SSL request. Now after live-reload has completed,
clicking on the icon will show the response of a gRPC SSL Request:
Refer to /src/mobile/flutter/flutter_grpc for a complete example project.
This Android gRPC Example differentiates from the Java gRPC Example by using the more appropriate Java Lite which results in a much smaller code size making it more suitable to be used on embedded Java platforms like Android.
In addition it uses the Android-compatible OK HTTP SSL Libraries in-place of Netty's SSL libraries and a
custom services.proto
allow us to specify the Java package we want the generated gRPC client to use.
Install x dotnet tool:
$ dotnet tool install --global x
Create a new Android App with Android Studio:
Add protoc generated TodoWorld DTOs and gRPC GrpcServicesStub
:
$ cd app\src\main\java
$ x proto-java https://todoworld.servicestack.net
Modify the downloaded services.proto
to use the package name of your App, e.g:
option java_package = "net.servicestack.androidapp";
Generate a java-lite protoc gRPC client from your modified services.proto
:
$ x proto-java-lite services.proto
Update build.gradle with required gRPC, protobuf and OK HTTP plugins and dependencies:
plugins {
id 'com.google.protobuf' version '0.8.8'
id 'idea'
}
//...
def grpcVersion = '1.27.0'
dependencies {
implementation 'javax.annotation:javax.annotation-api:1.2'
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-auth:${grpcVersion}"
implementation "io.grpc:grpc-census:${grpcVersion}"
implementation "io.grpc:grpc-okhttp:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"
//...
}
Sync changes to your build.gradle to install the new dependencies:
Add the android.permission.INTERNET
to your AndroidManifest.xml (before <application/>
tag):
<uses-permission android:name="android.permission.INTERNET"/>
Use protoc generated DTOs and async GrpcServicesStub
to perform non-blocking TodoWorld gRPC Service requests:
ManagedChannel channel = ManagedChannelBuilder.forAddress(
"todoworld.servicestack.net", 50054).usePlaintext().build();
final GrpcServicesGrpc.GrpcServicesStub client =
GrpcServicesGrpc.newStub(channel);
fab.setOnClickListener(new View.OnClickListener() {
client.getHello(Services.Hello.newBuilder()
.setName("Android gRPC").build(),
new StreamObserver<Services.HelloResponse>() {
@Override
public void onNext(Services.HelloResponse value) {
Snackbar.make(view, value.getResult(), Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
@Override public void onError(Throwable t) {}
@Override public void onCompleted() {}
});
});
Now run your App and click the Action button to make a plain-text gRPC Request:
To use gRPC SSL we'll need a copy of our gRPC's Service SSL Certificate which we can make available to our
Android App by saving it to our App's assets
directory:
$ md ..\assets
$ x get https://todoworld.servicestack.net/grpc.crt -out ../assets
Building an TLS Channel configured with a self-signed SSL Certificate requires a bit of effort with OK HTTP so we'll include a ChannelBuilder.java to wrap up the boiler plate:
$ x mix grpc-android
This simplifies the configuration required down to just the grpc.crt
certificate loaded from the
App's Asset Manager, the host and port name of the gRPC SSL Channel:
ManagedChannel channel = null;
InputStream is = null;
try {
is = getResources().getAssets().open("grpc.crt");
channel = ChannelBuilder.buildTls(
"todoworld.servicestack.net", 50051, is);
is.close();
} catch (Throwable e) {
e.printStackTrace();
}
Lets update the gRPC API call to reflect we're now using an SSL channel:
client.getHello(Services.Hello.newBuilder()
.setName("gRPC SSL").build(),
Now after re-running our App it'll perform gRPC SSL Service requests instead:
Refer to /src/mobile/java/AndroidGrpc for a complete example project.
Visit ServiceStack gRPC docs for more info.
As it's impossible to implement the HTTP/2 gRPC spec in the browser, in order to be able to consume gRPC services from a browser a gRPC Web Proxy is needed.
The current recommendation from the gRPC Web team is to Configure the Envoy Proxy to forward gRPC browser requests to the native gRPC endpoint, however as it adds more moving parts and additional complexity, if you're not already using envoyproxy we instead recommended using ServiceStack HTTP JSON Services, made possible since ServiceStack's gRPC Service implementations are also made available over REST-ful HTTP APIs - i.e. the lingua franca of the web.
If ASP.NET Core adds native gRPC Web support then using gRPC clients may provide a more appealing option although it wont have a clean, versatile and rich API as TypeScript Add ServiceStack Reference.
If wanting to evaluate using a gRPC Web Proxy you can use generate different TypeScript and JavaScript clients using the commands below:
$ x proto-ts <url> # TypeScript + gRPC Web Text
$ x proto-ts-binary <url> # TypeScript + gRPC Web Binary
$ x proto-js-closure <url> # Google Closure + gRPC Web Text
$ x proto-js-commonjs <url> # Common JS + gRPC Web Text
Or if preferred you can use the online UI or HTTP API for generating Protocol Buffers and gRPC client proxies at grpc.servicestack.net.