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);