How to use HTTP/2 from a React website for communication?

Viewed 48

In order to educate myself about web technologies, I am building a small project with the following setup:

  • An ASP.NET 6 server that provides gRPC services and a REST API
  • A .NET 6 WPF client application as Desktop gRPC client
  • A .NET 6 MAUI app as Mobile gRPC client
  • A React website that "talks" to the server with REST

I have had experience with gRPC, backend development and Desktop clients, so creating a simple server and the WPF client was no problem. Creating a simple .NET MAUI app was something new, but I managed to get it running. So these three applications talk to each other using gRPC and it works smoothly.

As for the React website, I first used an ASP.NET WebAPI sample project from a tutorial website and it worked fine. However, I wanted to integrate the REST API into my existing server that so far only provided gRPC services. My issue is, that I can't make them (server and React website) talk.

My server

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

My Program.cs is pretty simple, I only set the URLs for HTTP and HTTPS. In my Setup.cs, I set the message sizes, add my gRPC service used by the Desktop and Mobile clients and I added the sample REST GET from the tutorial I used for self-education.

My React client

I basically have an un-edited project that you get when you add a new "Standalone JavaScript React Project" in Visual Studio 2022. The only thing I have changed is the URL in the setupProxy.js which looks as follows.

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

Error when using HTTPS When I use the code as above, I see the following errors when starting my React website.

enter image description here

Error when using HTTP When I change the URL in setupProxy.js to my HTTP address (http://192.168.1.20:5000), I don't get an error in my server console output, but I get an error in my Node console from the website.

enter image description here

I am very new to React / Node / REST and my problem might be trivial for you, but any help is greatly appreciated. I think that once I have my basic setting going, I can learn more about these topics step by step.

1 Answers

I found the solution. The configuration of my React app was totally fine, but the issue was on my ASP.NET side. Because I use gRPC, my HTTPS connection was HTTP/2 only, but the incoming GET request from my React app was using HTTP 1. When I configured my endpoints to HTTP1 and 2, but gRPC and REST API work.

Related