Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tomkerkhove/70229a8e4646af3b275447221b977bfb to your computer and use it in GitHub Desktop.
Save tomkerkhove/70229a8e4646af3b275447221b977bfb to your computer and use it in GitHub Desktop.
Example of consuming gRPC service with Azure API Management
using Grpc.Net.Client;
using System.Security.Authentication;
Console.WriteLine("Hello, World!");
var endpointAddress = "https://localhost:8124";
var apiPrefix = "grpc-api";
var subscriptionKey = "<subscription-key>";
GrpcChannel grpcChannel = CreateGrpcChannel(endpointAddress, apiPrefix, subscriptionKey);
var client = new TestService.TestServiceClient(grpcChannel);
// unary
var payload = new Foo { Value = 1000 };
Console.WriteLine($"Sending unary request with payload {payload.Value}");
var unaryRequest = client.UnaryAsync(payload);
Foo unaryResponse = await unaryRequest;
Console.WriteLine($"Received {unaryResponse.Value}.");
Console.WriteLine("Goodbye!");
Console.ReadLine();
static GrpcChannel CreateGrpcChannel(string endpointAddress, string apiPrefix, string subscriptionKey)
{
Console.WriteLine($"Connecting to {endpointAddress} with API prefix {apiPrefix}.");
// Only required for when not (properly) exposing on HTTPS
var httpHandler = new SocketsHttpHandler()
{
SslOptions = new()
{
RemoteCertificateValidationCallback = (_, _, _, _) => true,
EnabledSslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13,
}
};
// Use a handler given we use an Azure API Management use API prefixes
// https://learn.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-7.0#calling-grpc-services-hosted-in-a-sub-directory
var apiPrefixHandler = new ApiPrefixHandler(httpHandler, apiPrefix, subscriptionKey, enableApiInspector: true);
return GrpcChannel.ForAddress(endpointAddress, new GrpcChannelOptions { HttpHandler = apiPrefixHandler });
}
public class ApiPrefixHandler : DelegatingHandler
{
readonly bool enableApiInspector;
readonly string pathPrefix;
readonly string subscriptionKey;
public ApiPrefixHandler(HttpMessageHandler innerHandler, string pathPrefix, string subscriptionKey, bool enableApiInspector)
: base(innerHandler)
{
this.pathPrefix = pathPrefix;
this.subscriptionKey = subscriptionKey;
this.enableApiInspector = enableApiInspector;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}/{this.pathPrefix}{old.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
request.Headers.TryAddWithoutValidation("Ocp-Apim-Subscription-Key", this.subscriptionKey);
if (this.enableApiInspector)
{
request.Headers.TryAddWithoutValidation("Ocp-Apim-Trace", Boolean.TrueString);
}
return base.SendAsync(request, cancellationToken);
}
}
syntax = "proto3";
service TestService {
rpc Unary(Foo) returns (Foo);
rpc ClientStreaming(stream Foo) returns (Foo);
rpc ServerStreaming(Foo) returns (stream Foo);
rpc Duplex(stream Foo) returns (stream Foo);
}
message Foo {
int32 value = 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment