React网站如何与启用HTTP/2的ASP.NET 6服务器通信?
我正在学习Web技术,搭建了一套包含以下组件的项目:
- 提供gRPC服务与REST API的ASP.NET 6服务器
- 作为桌面gRPC客户端的.NET 6 WPF应用
- 作为移动端gRPC客户端的.NET 6 MAUI应用
- 通过REST与服务器通信的React网站
目前服务器和WPF、MAUI客户端的gRPC通信正常,但在把REST API集成到原本只支持gRPC的服务器后,React网站无法和服务器通信。
服务器配置
appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*", "Kestrel": { "EndpointDefaults": { "Protocols": "Http2" } } }
launchSettings.json
{ "$schema": "https://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { "applicationUrl": "http://localhost:18460", "sslPort": 44326 } }, "profiles": { "Gather.Server": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": false, "launchUrl": "weatherforecast", "applicationUrl": "https://localhost:7081;http://localhost:5081", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": false, "launchUrl": "weatherforecast", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) { // This retrieves the proper IP address and port numbers that are used below. var configuration = ServiceFactory.Instance.GetConfiguration(); return Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder => { webBuilder.ConfigureKestrel(options => { // http://192.168.1.20:5000 options.Listen(configuration.IPAddress, configuration.HttpPort); // https://192.168.1.20:5005 options.Listen(configuration.IPAddress, configuration.HttpsPort, configure => configure.UseHttps()); }); webBuilder.UseStartup<Startup>(); }); }
Startup.cs
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddGrpc(options => { options.MaxReceiveMessageSize = 16 * 1024 * 1024; options.MaxSendMessageSize = 16 * 1024 * 1024; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGrpcService<AuthenticationService>(); var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; endpoints.MapGet("/weatherforecast", () => { return Enumerable.Range(1, 5).Select(index => new WeatherForecast(DateTime.Now.AddDays(index), Random.Shared.Next(-20, 55), summaries[Random.Shared.Next(summaries.Length)])) .ToArray(); }); }); } }
React客户端配置
React项目是Visual Studio 2022中创建的「Standalone JavaScript React Project」,仅修改了setupProxy.js:
setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware'); const context = [ "/weatherforecast", ]; module.exports = function (app) { const appProxy = createProxyMiddleware(context, { target: 'https://192.168.1.20:5005', secure: false, changeOrigin: true, logLevel: 'debug' }); app.use(appProxy); };
错误情况
- 使用HTTPS时:启动React网站出现连接错误
- 使用HTTP时:服务器控制台无错误,但Node控制台出现错误
我刚接触React/Node/REST,希望能解决这个通信问题。
核心问题:HTTP/2 兼容性
服务器配置里,appsettings.json 把Kestrel的默认协议设为了Http2,但React代理和大多数浏览器的REST请求默认使用HTTP/1.1,HTTP/2在纯文本(非TLS)场景下支持有限,且部分代理工具对HTTP/2的支持不完善,这是导致通信失败的主要原因。
修复步骤
调整Kestrel协议配置
修改appsettings.json,给HTTP和HTTPS端点分别指定协议,让HTTP端点支持HTTP/1.1,HTTPS端点同时支持HTTP/1.1和HTTP/2:"Kestrel": { "Endpoints": { "Http": { "Url": "http://192.168.1.20:5000", "Protocols": "Http1" }, "Https": { "Url": "https://192.168.1.20:5005", "Protocols": "Http1AndHttp2" } } }或者保留
Program.cs中的代码配置,在Listen时指定协议:options.Listen(configuration.IPAddress, configuration.HttpPort, listenOptions => { listenOptions.Protocols = HttpProtocols.Http1; }); options.Listen(configuration.IPAddress, configuration.HttpsPort, listenOptions => { listenOptions.Protocols = HttpProtocols.Http1AndHttp2; listenOptions.UseHttps(); });更新React代理配置
如果使用HTTP测试,把代理目标改成HTTP地址:target: 'http://192.168.1.20:5000',如果用HTTPS,先通过
dotnet dev-certs https --trust命令信任开发环境证书,代理配置保持secure: false即可。添加CORS支持
服务器本身配置CORS可避免潜在跨域问题,在Startup.cs的ConfigureServices中添加:services.AddCors(options => { options.AddPolicy("AllowAll", policy => { policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); });然后在
Configure中,路由前启用CORS:app.UseCors("AllowAll"); app.UseRouting();验证端点可达性
先直接在浏览器访问http://192.168.1.20:5000/weatherforecast或https://192.168.1.20:5005/weatherforecast,确认服务器能正常返回数据后,再测试React应用。
内容的提问来源于stack exchange,提问作者GameDevAlien

