ASP.NET Core gRPC 應用程式中的 gRPC-Web
瞭解如何使用gRPC-Web通訊協定,設定可從瀏覽器應用程式呼叫的現有 ASP.NET Core gRPC 服務。 gRPC-Web 允許瀏覽器 JavaScript 和 Blazor 應用程式呼叫 gRPC 服務。 您無法從瀏覽器型應用程式呼叫 HTTP/2 gRPC 服務。 ASP.NET Core中裝載的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。
如需將 gRPC 服務新增至現有 ASP.NET Core應用程式的指示,請參閱將 gRPC 服務新增至 ASP.NET Core應用程式。
如需建立 gRPC 專案的指示,請參閱在 ASP.NET Core 中建立 .NET Core gRPC 用戶端和伺服器。
ASP.NET Core gRPC-Web 與 Envoy
有兩個選項可用來將 gRPC-Web 新增至 ASP.NET Core應用程式:
- 在 ASP.NET Core 中支援 gRPC-Web 與 gRPC HTTP/2。 此選項使用套件提供的
Grpc.AspNetCore.Web
中介軟體。 - 使用 Envoy Proxy 的 gRPC-Web 支援,將 gRPC-Web 轉譯為 gRPC HTTP/2。 接著會將轉譯的呼叫轉送到 ASP.NET Core應用程式。
每個方法都有優缺點。 如果應用程式的環境已經使用 Envoy 做為 Proxy,則也可以使用 Envoy 來提供 gRPC-Web 支援。 對於只需要 ASP.NET Core的 gRPC-Web 基本解決方案, Grpc.AspNetCore.Web
是不錯的選擇。
在 ASP.NET Core 中設定 gRPC-Web
ASP.NET Core中裝載的 gRPC 服務可以設定為支援 gRPC-Web 以及 HTTP/2 gRPC。 gRPC-Web 不需要對服務進行任何變更。 唯一的修改是啟動組態。
若要使用 ASP.NET Core gRPC 服務啟用 gRPC-Web:
- 新增封裝的
Grpc.AspNetCore.Web
參考。 - 將 和
EnableGrpcWeb
新增UseGrpcWeb
至Startup.cs
,將應用程式設定為使用 gRPC-Web:
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();
});
}
上述程式碼:
- 在路由之後和端點之前,新增 gRPC-Web 中介軟體
UseGrpcWeb
。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法支援 gRPC-Web 與EnableGrpcWeb
。
或者,您可以設定 gRPC-Web 中介軟體,讓所有服務預設都支援 gRPC-Web, EnableGrpcWeb
而且不需要。 指定 new GrpcWebOptions { DefaultEnabled = true }
新增中介軟體的時機。
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>();
});
}
}
注意
已知問題會導致 gRPC-Web 在 .NET Core 3.x 中 由 HTTP.sys裝載 時失敗。
(grpc/grpc-dotnet #853) 中提供 grpc-web 實驗性與 UseHttpSys () ? (grpc/grpc-dotnet #853) 中提供 gRPC-Web HTTP.sys 運作的因應措施。
gRPC-Web 和 CORS
瀏覽器安全性可防止網頁向不同網域提出要求,而不是提供網頁的網域。 這項限制適用于使用瀏覽器應用程式進行 gRPC-Web 呼叫。 例如,由 https://www.contoso.com
提供的瀏覽器應用程式會遭到封鎖,而無法呼叫裝載于 上的 https://services.contoso.com
gRPC-Web 服務。 跨原始來源資源分享 (CORS) 可用來放寬這項限制。
若要允許瀏覽器應用程式進行跨原始來源 gRPC-Web 呼叫,請在ASP.NET Core 中設定 CORS。 使用內建 CORS 支援,並使用 公開 gRPC 特定標頭。 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");
});
}
上述程式碼:
- 呼叫
AddCors
以新增 CORS 服務,並設定公開 gRPC 特定標頭的 CORS 原則。 - 在路由設定和端點設定之前,呼叫
UseCors
以新增 CORS 中介軟體。 - 指定
endpoints.MapGrpcService<GreeterService>()
方法支援使用RequireCors
CORS。
gRPC-Web 和串流
傳統 gRPC over HTTP/2 支援用戶端、伺服器和雙向串流。 gRPC-Web 提供有限的串流支援:
- gRPC-Web 瀏覽器用戶端不支援呼叫用戶端串流和雙向串流方法。
- gRPC-Web .NET 用戶端不支援透過 HTTP/1.1 呼叫用戶端串流和雙向串流方法。
- ASP.NET Core裝載于 Azure App 服務 和 IIS 上的 gRPC 服務不支援雙向串流。
使用 gRPC-Web 時,我們只建議使用一元方法和伺服器串流方法。
HTTP 通訊協定
包含在 .NET SDK 中的 ASP.NET Core gRPC 服務範本會建立僅針對 HTTP/2 設定的應用程式。 當應用程式僅支援傳統 gRPC over HTTP/2 時,這是很好的預設值。 不過,gRPC-Web 同時適用于 HTTP/1.1 和 HTTP/2。 某些平臺,例如 UWP 或 Unity,無法使用 HTTP/2。 若要支援所有用戶端應用程式,請將伺服器設定為啟用 HTTP/1.1 和 HTTP/2。
更新 中的 appsettings.json
預設通訊協定:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
或者, 在啟動程式碼中設定 Kestrel 端點。
在相同的埠上啟用 HTTP/1.1 和 HTTP/2 需要 TLS 進行通訊協定交涉。 如需詳細資訊,請參閱ASP.NET Core gRPC 通訊協定交涉。
從瀏覽器呼叫 gRPC-Web
瀏覽器應用程式可以使用 gRPC-Web 來呼叫 gRPC 服務。 從瀏覽器使用 gRPC-Web 呼叫 gRPC 服務時,有一些需求和限制:
- 伺服器必須包含支援 gRPC-Web 的組態。
- 不支援用戶端串流和雙向串流呼叫。 支援伺服器串流。
- 在不同的網域上呼叫 gRPC 服務需要伺服器上的 CORS 設定。
JavaScript gRPC-Web 用戶端
JavaScript gRPC-Web 用戶端存在。 如需如何從 JavaScript 使用 gRPC-Web 的指示,請參閱 使用 gRPC-Web 撰寫 JavaScript 用戶端程式代碼。
使用 .NET gRPC 用戶端設定 gRPC-Web
.NET gRPC 用戶端可以設定為進行 gRPC-Web 呼叫。 這適用于 Blazor WebAssembly 裝載在瀏覽器中的應用程式,而且具有 JavaScript 程式碼的相同 HTTP 限制。 使用 .NET 用戶端呼叫 gRPC-Web 與 HTTP/2 gRPC相同。 唯一的修改是通道的建立方式。
若要使用 gRPC-Web:
- 新增封裝的
Grpc.Net.Client.Web
參考。 - 確定套件的
Grpc.Net.Client
參考是 2.29.0 版或更新版本。 - 將通道設定為使用
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" });
上述程式碼:
- 設定通道以使用 gRPC-Web。
- 建立用戶端並使用通道進行呼叫。
GrpcWebHandler
具有下列組態選項:
InnerHandler
:發出 gRPC HTTP 要求的基礎 HttpMessageHandler ,例如HttpClientHandler
。GrpcWebMode
:列舉型別,指定 gRPC HTTP 要求Content-Type
為application/grpc-web
或application/grpc-web-text
。GrpcWebMode.GrpcWeb
會設定傳送內容而不進行編碼。 預設值。GrpcWebMode.GrpcWebText
會設定 base64 編碼的內容。 瀏覽器的伺服器串流呼叫需要 。
HttpVersion
:用來在基礎 gRPC HTTP 要求上設定 HttpRequestMessage.Version 的 HTTP 通訊協定Version
。 gRPC-Web 不需要特定版本,而且除非指定,否則不會覆寫預設值。
重要事項
產生的 gRPC 用戶端具有同步和非同步方法來呼叫一元方法。 例如, SayHello
是同步的,而且 SayHelloAsync
是非同步。 在 中 Blazor WebAssembly 一律需要非同步方法。 在應用程式中呼叫同步方法 Blazor WebAssembly 會導致應用程式沒有回應。
搭配 gRPC-Web 使用 gRPC 用戶端處理站
使用 gRPC 用戶端處理站建立與 gRPC-Web相容的 .NET 用戶端:
- 將套件參考新增至下列套件的專案檔:
- 使用泛型
AddGrpcClient
擴充方法,使用相依性插入 (DI) 註冊 gRPC 用戶端。 Blazor WebAssembly在應用程式中,服務會在 中Program.cs
向 DI 註冊。 - 使用擴充方法進行 ConfigurePrimaryHttpMessageHandler 設定
GrpcWebHandler
。
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));
如需詳細資訊,請參閱 .NET 中的 gRPC 用戶端處理站整合。