DEV Community

Masui Masanori
Masui Masanori

Posted on

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

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

Top comments (0)