[Vite + React] Running an ASP.NET Core application behind a reverse proxy
Masui Masanori

Masui Masanori @masanori_msl

About: Programmer, husband, father I love C#, TypeScript, Go, etc.

Location:
Wakayama, Japan
Joined:
Jul 17, 2020

[Vite + React] Running an ASP.NET Core application behind a reverse proxy

Publish Date: Dec 5 '24
5 0

Intro

This time, I will try running my ASP.NET Core application behind reverse proxy.
On the client-side, I will use a React application generated by Vite.

The URL will be changed when I use a reverse proxy.

How to access URL
Direct access http//localhost:5170
Using a reverse proxy http://localhost/officefiles

Thus, I need to change the settings to match this URL.

vite.config.ts

To change the asset paths of the React application, I can change "base" in vite.config.ts to "/officefiles/".

vite.config.ts

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

// https://vite.dev/config/
export default defineConfig({
  base: "/officefiles/",
  plugins: [react()],

})
Enter fullscreen mode Exit fullscreen mode

Problems

When I access the React application, the URL automatically changes from "http://localhost:5173" to "http://localhost:5173/officefiles/".
However, after the change, four problems occurred.

  1. ERR_TOO_MANY_REDIRECTS
  2. Couldn't access ASP.NET Core Web API
  3. Route paths of react-router-dom
  4. Accessing ASP.NET Core Web API from the React application

Problem 1. ERR_TOO_MANY_REDIRECTS

When I tried to access "http://localhost/officefiles" on debug mode, I got an ERR_TOO_MANY_REDIRECTS error and the page couldn't be opened.
Because this problem only occurred when the application has been run with the "dotnet run" command, I decided not to use a reverse proxy for debugging.

Problem 2. Couldn't access ASP.NET Core Web API

Although I tried to access an ASP.NET Core Web API(ex. http://localhost:5170/api/files), it would be routed to the Vite-side and I would get a 404 error.
So I changed "UseSpa" would be executed only if the accessed URL does not contain "/api".

Program.cs

...
   app.MapControllers();
   app.MapWhen(context => context.Request.Path.StartsWithSegments("/api") == false,
       b => {
           b.UseSpa(spa =>
           {
               if (builder.Environment.EnvironmentName == "Development") 
               {
                   spa.Options.SourcePath = "office-file-accessor";
                   spa.UseProxyToSpaDevelopmentServer("http://localhost:5173");
               }
               else
               {
                    spa.Options.SourcePath = "office-file-accessor/dist";
               }
           });
       });
   app.Run();
...
Enter fullscreen mode Exit fullscreen mode

Problem 3. Route paths of react-router-dom

Route paths of react-router-dom wouldn't be changed, so I added "basename" into the "Router" tag.

App.tsx

import './App.css'
import {
  BrowserRouter as Router,
  Route,
  Routes,
  Link
} from "react-router-dom";
import { IndexPage } from './IndexPage';
import { RegisterPage } from './RegisterPage';
function App() {
  return (
    <>

      <Router basename="/officefiles">

      <Link to="/">TOP</Link>
      <p>|</p>
      <Link to="/register">Register</Link>
      <Routes>
        <Route path="/" element={<IndexPage />} />
        <Route path="/register" element={<RegisterPage />} />
      </Routes  >
      </Router>
    </>
  )
}
export default App
Enter fullscreen mode Exit fullscreen mode

Problem 4. Accessing ASP.NET Core Web API from the React application

The ASP.NET Core Web API URLs what were accessed by the React application wouldn't be changed.
Because I couldn't find how to change the URLs automatically, so I decided to switch the URL depending on whether I was in the product environment or not.

serverUrlGetter.ts

export function getServerUrl() {
    if(import.meta.env.MODE === "production") {
        return "/officefiles";
    }
    return "";
}
Enter fullscreen mode Exit fullscreen mode

IndexPage.tsx

import { useEffect } from "react"
import { getServerUrl } from "./web/serverUrlGetter";

export function IndexPage(): JSX.Element {
    useEffect(() => {
        fetch(`${getServerUrl()}/api/files`, {
            mode: "cors",
            method: "GET"
        })
        .then(res => res.text())
        .then(res => console.log(res))
        .catch(err => console.error(err));
    }, []);


    return <h1>Hello World!</h1>
}
Enter fullscreen mode Exit fullscreen mode

Comments 0 total

    Add comment