Search code examples
c#reactjsnode.jsasp.net-coreraspberry-pi

ASP.NET Core + React + Node.js on Raspberry Pi proxying requests does not work


I attempted to create a relatively simple website using the base-template provided in Visual Studio with React already integrated (and, as I understand, Node.js). However, I encountered an issue with redirecting requests from Node.js handlers to ASP.NET Core. While the project runs smoothly on my computer, I encountered an error when attempting the same on my Raspberry Pi:

[HPM] Error occurred while proxying request 192.168.0.101:44463/login to http://192.168.0.101:5124/ [ECONNRESET] (https://nodejs.org/api/errors.html#errors_common_system_errors)

In browser:

Error in browser debug window

Regarding IP addresses:

  • Connected from computer 192.168.0.100;
  • ASP.NET Core and reaction are located at 192.168.101;
  • ASP.NET Core port 5124, react port 44463

setupProxy.js code:

const { createProxyMiddleware } = require('http-proxy-middleware');
const httpProxy = require('http-proxy');
const { env } = require('process');

const target = env.ASPNETCORE_HTTPS_PORT ? http://localhost:${env.ASPNETCORE_HTTPS_PORT} :
    env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:5015';

const context = [
    "/login",
    "/registration",
    "/tokenvalidation",
    "/statistic",
];

module.exports = function (app) {
    const appProxy = createProxyMiddleware(context, {
        proxyTimeout: 10000,
        target: target,
        secure: false,
        headers: {
            Connection: 'Keep-Alive'
        }
    });

    app.use(appProxy);
};

Program.cs file:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using CheckersOnlineSPA.ClientApp;
using Microsoft.EntityFrameworkCore;
using CheckersOnlineSPA.Data;
using CheckersOnlineSPA.Services.OnlineClientsWatcher;
using CheckersOnlineSPA.Services.Browser;
using Microsoft.AspNetCore.WebSockets;
using CheckersOnlineSPA.Services.Games;

var builder = WebApplication.CreateBuilder(args);

builder.WebHost.UseUrls("http://192.168.0.101:5124");

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll",
        builder =>
        {
            builder.AllowAnyOrigin()
                   .AllowAnyMethod()
                   .AllowAnyHeader();
        });
});

builder.Services.AddDataProtection();
builder.Services.AddControllersWithViews();
builder.Services.AddAuthorization();
builder.Services.AddSingleton<BrowserController>();
//builder.Services.AddSingleton<OnlineClientsWatcher>();
builder.Services.AddSingleton<GamesController>();

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = Auth.AuthOptions.ISSUER,
            ValidateAudience = true,
            ValidAudience = Auth.AuthOptions.AUDIENCE,
            ValidateLifetime = true,
            IssuerSigningKey = Auth.AuthOptions.GetSymmetricSecurityKey(),
            ValidateIssuerSigningKey = true
        };
    });

string conn = "Server=192.168.0.101;Database=checkers;Uid=dimon;Pwd=qwerty123123;";
builder.Services.AddDbContext<DatabaseContext>(options => options.UseMySql(conn, ServerVersion.AutoDetect(conn)));

var app = builder.Build();

app.UseCors();
app.UseStaticFiles();
app.UseRouting();
app.UseWebSockets();
app.UseAuthentication();
app.UseAuthorization();

app.UseMiddleware<GameMiddleware>();
app.UseMiddleware<BrowserMiddleware>();
//app.UseMiddleware<ClientsCounterMiddleware>();

app.MapPost("/login", Auth.LoginHandler);
app.MapPost("/registration", Auth.RegistrationHandle);
app.MapPost("/tokenvalidation", Auth.TokenValidationHandler);
app.MapPost("/statistic", ClientsActivity.GetClientsActivityHandler );

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");
app.MapFallbackToFile("index.html");

app.Run();

Entire project on github:

Source code on github


Solution

  • When VS2022 starts the project in the dev environment, the React project will enable port 44463, and your ASP.NET Core uses port 5124.

    However, in the published files, the React project will be compiled into static resource files and processed by app.UseStaticFiles();,

    so only one port is enabled in your Raspberry Pi.

    So you need to change below code:

    const target = env.ASPNETCORE_HTTPS_PORT ? `http://localhost:${env.ASPNETCORE_HTTPS_PORT}` :
    env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'http://localhost:5015';
    

    Just make sure that the published front-end and back-end ports are consistent.