GRPC-Web + Blazor CORS 问题
GRPC-Web + Blazor CORS Issue
我正在尝试创建一个 Blazor WASM 应用程序,它将使用 grpc-web 调用 GRPC 网关。
网关服务的描述是:
syntax = "proto3";
import "Services/AdService.proto";
package BonnieAndClydesdale.Core;
service GatewayService {
rpc GetAds (AdRequest) returns (AdReply);
}
我已经按照 this guide 在服务器和客户端上设置 grpc-web。
我的服务器 program.cs
中有这个:
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection();
builder.Services.AddGrpcClient<AdService.AdServiceClient>(o => o.Address = new("https://localhost:7223")); // Downstream GRPC service
WebApplication app = builder.Build();
// Configure the HTTP request pipeline.
app.MapGrpcService<GatewayService>().EnableGrpcWeb();
app.UseGrpcWeb();
这在我的 blazor 应用程序的 program.cs
中:
builder.Services.AddSingleton(services =>
{
HttpClient httpClient = new(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler()));
string baseUri = "https://localhost:7080"; // TODO - Add to AppSettings
GrpcChannel channel = GrpcChannel.ForAddress(baseUri, new() { HttpClient = httpClient });
return new GatewayService.GatewayServiceClient(channel);
});
但是,当我加载此页面时:
public partial class ForSale: ComponentBase
{
[Inject]
private GatewayService.GatewayServiceClient Client { get; init; } = null!;//TODO replace with service
private readonly List<AdDetails> _ads;
public ForSale()
{
_ads = new();
}
protected override async Task OnInitializedAsync()
{
AdReply? rep = await Client.GetAdsAsync(new());
if (rep.AdDetails is not null)
{
_ads.AddRange(rep.AdDetails);
}
}
}
我收到 CORS 错误:
Access to fetch at
'https://localhost:7080/BonnieAndClydesdale.Core.GatewayService/GetAds'
from origin 'https://localhost:5001' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
关于如何解决这个问题有什么想法吗?
编辑
我看到很多类似问题的答案都建议使用 services.AddCors(...)
和 app.UseCors()
,但这些方法在 Blazor WASM 应用程序中似乎不存在。
问题源于对需要设置 CORS 政策的地方的误解。它需要在网关服务器中设置,而不是在 Blazor WASM web-app 上设置。这是有道理的,因为 CORS 是在服务器上实现的,但由于大多数教程似乎都假设我们使用的是 Blazor 服务器,所以出现了混淆。
为了完整起见,我将其添加到 网关 的 startup.cs
(不是 Blazor 应用程序)。
const string corsPolicy = "_corsPolicy";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: corsPolicy,
policy =>
{
policy.WithOrigins("https://localhost:5001",
"http://localhost:5000")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
WebApplication app = builder.Build();
app.UseCors(corsPolicy);
我正在尝试创建一个 Blazor WASM 应用程序,它将使用 grpc-web 调用 GRPC 网关。
网关服务的描述是:
syntax = "proto3";
import "Services/AdService.proto";
package BonnieAndClydesdale.Core;
service GatewayService {
rpc GetAds (AdRequest) returns (AdReply);
}
我已经按照 this guide 在服务器和客户端上设置 grpc-web。
我的服务器 program.cs
中有这个:
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection();
builder.Services.AddGrpcClient<AdService.AdServiceClient>(o => o.Address = new("https://localhost:7223")); // Downstream GRPC service
WebApplication app = builder.Build();
// Configure the HTTP request pipeline.
app.MapGrpcService<GatewayService>().EnableGrpcWeb();
app.UseGrpcWeb();
这在我的 blazor 应用程序的 program.cs
中:
builder.Services.AddSingleton(services =>
{
HttpClient httpClient = new(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler()));
string baseUri = "https://localhost:7080"; // TODO - Add to AppSettings
GrpcChannel channel = GrpcChannel.ForAddress(baseUri, new() { HttpClient = httpClient });
return new GatewayService.GatewayServiceClient(channel);
});
但是,当我加载此页面时:
public partial class ForSale: ComponentBase
{
[Inject]
private GatewayService.GatewayServiceClient Client { get; init; } = null!;//TODO replace with service
private readonly List<AdDetails> _ads;
public ForSale()
{
_ads = new();
}
protected override async Task OnInitializedAsync()
{
AdReply? rep = await Client.GetAdsAsync(new());
if (rep.AdDetails is not null)
{
_ads.AddRange(rep.AdDetails);
}
}
}
我收到 CORS 错误:
Access to fetch at 'https://localhost:7080/BonnieAndClydesdale.Core.GatewayService/GetAds' from origin 'https://localhost:5001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
关于如何解决这个问题有什么想法吗?
编辑
我看到很多类似问题的答案都建议使用 services.AddCors(...)
和 app.UseCors()
,但这些方法在 Blazor WASM 应用程序中似乎不存在。
问题源于对需要设置 CORS 政策的地方的误解。它需要在网关服务器中设置,而不是在 Blazor WASM web-app 上设置。这是有道理的,因为 CORS 是在服务器上实现的,但由于大多数教程似乎都假设我们使用的是 Blazor 服务器,所以出现了混淆。
为了完整起见,我将其添加到 网关 的 startup.cs
(不是 Blazor 应用程序)。
const string corsPolicy = "_corsPolicy";
builder.Services.AddCors(options =>
{
options.AddPolicy(name: corsPolicy,
policy =>
{
policy.WithOrigins("https://localhost:5001",
"http://localhost:5000")
.AllowAnyHeader()
.AllowAnyMethod();
});
});
WebApplication app = builder.Build();
app.UseCors(corsPolicy);