gRPC & ASP.NET Core 3.1: What’s gRPC-web & how to create a gRPC-web service ?
What’s gRPC-web ?
In the summer of 2016, both a team at Google and Improbable independently started working on implementing something that could be called “gRPC for the browser”. They soon discovered each other’s existence and got together to define a spec for the new protocol.
It is currently impossible to implement the HTTP/2 gRPC spec in the browser, as there is simply no browser API with enough fine-grained control over the requests. For example: there is no way to force the use of HTTP/2, and even if there was, raw HTTP/2 frames are inaccessible in browsers. The gRPC-web spec starts from the point of view of the HTTP/2 spec, and then defines the differences. These notably include:
- Supporting both HTTP/1.1 and HTTP/2.
- Sending of gRPC trailers at the very end of request/response bodies as indicated by a new bit in the gRPC message header.
- A mandatory proxy for translating between gRPC-web requests and gRPC HTTP/2 responses.
Note that gRPC-web is not compatible with client-side and bi-directional streaming but only with unary and server-side streaming.
Envoy can be used as the mandatory proxy:
Because Improbable implementation supports TypeScript, I chose this library to make the demo in the next article, here is the link of Improbable gRPC-web repository: https://github.com/improbable-eng/grpc-web
gRPC-web & ASP.NET Core 3.1
In january 2020, Microsoft has announced an experimental support for gRPC-web with ASP.NET Core. Compatible with browsers (like Angular, React apps and more SPAs), Blazor WebAssembly and even Xamarin, that implementation brings an important feature: the uselessness of using a proxy such as Envoy.
To learn more about Microsoft announcement you can read this article: https://devblogs.microsoft.com/aspnet/grpc-web-experiment/
Implementation of gRPC-web & ASP.NET Core 3.1
We’ll need to download that preview package in your ASP.NET Core 3 project:
Install-Package Grpc.AspNetCore.Web -Version 2.28.0-pre2
In our Startup. cs we will add the required config:
Configure CORS policies in ASP.NET Core 3
gRPC-web requires CORS.
- Origins must be set with our known domains (such as localhost and our official domain name on internet)
- Methods allowed must be POST and depending the browser OPTIONS too
- All Request headers must be allowed
- Response headers (exposed headers) must allow Grpc-Status and Grpc-Message
Activate gRPC-web middleware
The middleware app.UseGrpcWeb() must be activated. Its role is to catch requests that ask a gRPC endpoint to answer a non binary answer then text instead in order to be compatible with the browser, there are 2 types of Content-Type:
- application/grpc-web which is compatible with unary services
- application/grpc-web-text which is compatible with unary and server-side streaming services
Apply Cors and enable gRPC-web on services
This is the last step, we need to apply Cors and gRPC-web on services: .MapGrpcService<CountryGrpcService().RequireCors(“MyPolicy”).EnableGrpcWeb();
gRPC-web can be enabled for all services by adding this line in ConfigureServices: services.AddGrpcWeb(o => o.GrpcWebEnabled = true); so you don’t need to add on each service .EnableGrpcWeb();
The Startup.cs file should look like this:
For more information you can go to the Microsoft documentation: https://docs.microsoft.com/en-us/aspnet/core/grpc/browser?view=aspnetcore-3.1
Azure App Service support
The thing you need to know is that Azure App Services doesn’t support HTTP/2 then you have to deploy your app with HTTP/1 as Kestrel default end points protocol settings in the appsettings.json file.
If you keep HTTP/2 in your settings, it will only work on Windows App Services because this one runs with module named ASPNetCoreModuleV2 that makes sure the app works fine on Windows (turns HTTP/2 to HTTP/1). On Linux App Services the docker behind the scene will fail on start:
In the next article we will how to consume an gRPC-web service with an Angular 8 app and also with console app using HttpClient.