Uso de gRPC en aplicaciones de explorador
Obtenga información sobre cómo configurar un servicio gRPC de ASP.NET Core existente al que se puede llamar desde aplicaciones del explorador mediante el protocolo gRPC-Web. gRPC-Web permite a las aplicaciones de explorador de JavaScript y Blazor llamar a servicios gRPC. No se puede llamar a un servicio HTTP/2 gRPC desde una aplicación basada en el explorador. Los servicios gRPC hospedados en ASP.NET Core se pueden configurar para admitir gRPC-Web junto con HTTP/2 gRPC.
Para instrucciones sobre cómo agregar un servicio gRPC a una aplicación de ASP.NET Core existente, consulte Incorporación de servicios gRPC a una aplicación de ASP.NET Core.
Para instrucciones sobre cómo crear un proyecto de gRPC, consulte Creación de un servidor y un cliente gRPC en ASP.NET Core.
gRPC-Web en ASP.NET Core frente a Envoy
Hay dos opciones para agregar gRPC-Web a una aplicación de ASP.NET Core:
- Compatibilidad con gRPC-Web junto con HTTP/2 gRPC en ASP.NET Core. Esta opción usa el middleware que el paquete
Grpc.AspNetCore.Webproporciona. - Use la compatibilidad con gRPC-Web del proxy de Envoy para traducir gRPC-Web a HTTP/2 gRPC. A continuación, la llamada traducida se reenvía a la aplicación ASP.NET Core.
Cada enfoque tiene ventajas y desventajas. Si el entorno de una aplicación ya usa Envoy como proxy, puede que tenga sentido usar Envoy para proporcionar compatibilidad con gRPC-Web. Para obtener una solución básica para gRPC-Web que solo requiera ASP.NET Core, Grpc.AspNetCore.Web es una buena elección.
Configuración de gRPC-Web en ASP.NET Core
Los servicios gRPC hospedados en ASP.NET Core se pueden configurar para admitir gRPC-Web junto con HTTP/2 gRPC. gRPC-Web no requiere ningún cambio en los servicios. La única modificación es la configuración de inicio.
Para habilitar gRPC-Web con un servicio gRPC de ASP.NET Core:
- Agregue una referencia al paquete Grpc.AspNetCore.Web.
- Configure la aplicación para que use gRPC-Web, agregando para ello
UseGrpcWebyEnableGrpcWeba Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb(); // Must be added between UseRouting and UseEndpoints
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb();
});
}
El código anterior:
- Agrega el middleware de gRPC-Web,
UseGrpcWeb, después del enrutamiento y antes de los puntos de conexión. - Especifica que el método
endpoints.MapGrpcService<GreeterService>()admite gRPC-Web conEnableGrpcWeb.
Como alternativa, se puede configurar el middleware gRPC-Web de forma que todos los servicios admitan gRPC-Web de forma predeterminada y no se necesite EnableGrpcWeb. Especifique new GrpcWebOptions { DefaultEnabled = true } cuando se agregue el middleware.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});
}
}
Nota
Hay un problema conocido que hace que gRPC-Web genere un error cuando está hospedado en HTTP.sys en .NET Core 3.x.
Una solución alternativa para que gRPC-Web funcione en HTTP.sys está disponible aquí.
gRPC-Web y CORS
La seguridad del explorador evita que una página web realice solicitudes a un dominio diferente del que atendió a dicha página web. Esta restricción se aplica a la hora de realizar llamadas de gRPC-Web con aplicaciones de explorador. Por ejemplo, una aplicación de explorador atendida por https://www.contoso.com no puede llamar a los servicios gRPC-Web hospedados en https://services.contoso.com. Para suavizar esta restricción, podemos recurrir al uso compartido de recursos entre orígenes (CORS).
Para permitir que una aplicación de explorador haga llamadas de gRPC-Web entre orígenes, configure CORS en ASP.NET Core. Use la compatibilidad de CORS integrada y exponga los encabezados específicos de gRPC con WithExposedHeaders.
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb()
.RequireCors("AllowAll");
});
}
El código anterior:
- Llama a
AddCorspara agregar los servicios CORS y configura una directiva CORS que expone los encabezados específicos de gRPC. - Llama a
UseCorspara agregar el middleware de CORS después del enrutamiento y antes de los puntos de conexión. - Especifica que el método
endpoints.MapGrpcService<GreeterService>()admite CORS conRequiresCors.
gRPC-Web y streaming
El gRPC tradicional a través de HTTP/2 admite el streaming en todas las direcciones. gRPC-Web ofrece compatibilidad limitada para streaming:
- Los clientes del explorador gRPC-Web no admiten la llamada a métodos de streaming de cliente y streaming bidireccional.
- Los servicios gRPC de ASP.NET Core hospedados en Azure App Service e IIS no admiten streaming bidireccional.
Al usar gRPC-Web, solo se recomienda el uso de métodos unarios y métodos de streaming de servidor.
Llamada a gRPC-Web desde el explorador
Las aplicaciones de explorador pueden usar gRPC-Web para llamar a servicios gRPC. Existen algunos requisitos y limitaciones a la hora de llamar a servicios gRPC con gRPC-Web desde el explorador:
- El servidor debe estar configurado para admitir gRPC-Web.
- No se pueden usar llamadas de streaming de cliente ni de streaming bidireccional. Sí se puede usar el streaming de servidor.
- Para llamar a servicios gRPC en otro dominio, hay que configurar CORS en el servidor.
Cliente gRPC-Web de JavaScript
Existe un cliente gRPC-Web de JavaScript. Para obtener instrucciones sobre cómo usar gRPC-Web en JavaScript, vea Escribir código de cliente de JavaScript con gRPC-Web.
Configuración de gRPC-Web con el cliente gRPC de .NET
El cliente gRPC de .NET se puede configurar para realizar llamadas de gRPC-Web. Esto resulta útil en las aplicaciones Blazor WebAssembly, que se hospedan en el explorador y tienen las mismas limitaciones HTTP de código JavaScript. Llamar a gRPC-Web con un cliente .NET es igual que HTTP/2 gRPC. La única modificación es cómo se crea el canal.
Para usar gRPC-Web:
- Agregue una referencia al paquete Grpc.Net.Client.Web.
- Asegúrese de que la referencia al paquete Grpc.Net.Client sea 2.29.0 o superior.
- Configure el canal para que use
GrpcWebHandler:
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
El código anterior:
- Configura un canal para que use gRPC-Web.
- Crea un cliente y realiza una llamada usando el canal.
GrpcWebHandler tiene las siguientes opciones de configuración:
- InnerHandler: elemento HttpMessageHandler subyacente que realiza la solicitud HTTP de gRPC, por ejemplo,
HttpClientHandler. - GrpcWebMode: tipo de enumeración que especifica si el
Content-Typede la solicitud HTTP gRPC esapplication/grpc-weboapplication/grpc-web-text.GrpcWebMode.GrpcWebconfigura el contenido que se va a enviar sin codificación. Valor predeterminado.GrpcWebMode.GrpcWebTextconfigura el contenido para que tenga codificación Base64. Esto es necesario en las llamadas de streaming de servidor en los exploradores.
- HttpVersion: elemento
Versiondel protocolo HTTP que se usa para establecer HttpRequestMessage.Version en la solicitud HTTP de gRPC subyacente. gRPC-Web no requiere que haya una versión específica y no invalida el valor predeterminado a menos que así se especifique.
Importante
Los clientes de gRPC generados tienen métodos sincrónicos y asincrónicos para llamar a métodos unarios. Así, SayHello es sincrónico y SayHelloAsync, asincrónico. La llamada a un método sincrónico en una aplicación Blazor WebAssembly hace que la aplicación deje de responder. En Blazor WebAssembly, siempre se deben usar métodos asincrónicos.
Uso de la fábrica de cliente gRPC con gRPC-Web
Se puede crear un cliente de .NET compatible con gRPC-Web mediante la fábrica de cliente de gRPC.
Para usar gRPC-Web con la fábrica de cliente:
- Agregue referencias de paquete al archivo del proyecto para los paquetes siguientes:
- Registre un cliente de gRPC con inserción de dependencias mediante el método de extensión genérico
AddGrpcClient. En una aplicación Blazor WebAssembly, los servicios se registran con la inserción de dependencias enProgram.cs. - Configure
GrpcWebHandlermediante el método de extensión ConfigurePrimaryHttpMessageHandler.
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
Para obtener más información, vea Integración de la fábrica de cliente de gRPC en .NET.