Search code examples
reactjsnode.jsazureiismicrosoft-web-deploy

Web Deployment React - 404 Error on API Calls


I have developed an internal web application using React Typescript and built a Express API for all my backend communications with a Postgresql DB.

I have these deployed to separate server internally, The Express API is running on a Linux machine with NGINX configured for both HTTP with a internal CA and then HTTPS with a go daddy cert. The React Webapp is deployed to Windows Server 2019 using IIS, I have gone through the process of setting up the URL Rewrite & AAR as person the Microsoft documentation online.

Internally everything is working great, Internally using the IIS https://iiserver/Board to reach it.

When i have used Microsoft AAD/Entra/Azure what ever its official label is to setup a Enterprise Application to expose the webpage to the internet with security to visit the web app. The webpage itself is working just fine as https://WebApp.Company.com/Board, i had initial issue that the proxy was certified with our Go Daddy cert but i put that onto the API server and all was well.

My issue now is that when ever it attempts to make a call to the API which internally it would be https://APIServer/api/deplist, the IIS setup should reverse proxy it when i use https://WebApp.Company.com/api/deplist. the Rewrite rules are setup as below.

My main issue i'm trying to solve here is kind of two fold, 1 am i even approaching this the correct way, the internal webapp we want to expose it publicly with the Entra security in front of it because its for company use only, but i can't figure out how to have this so don't have to attempt to expose the API i built internally in the same manner.

EDIT - Solved

This ended up being something of a red herring situation that i was attempting chase my tail around. the issue ended up being that my API calls to the Webserver weren't being made correctly the IIS Server was serving the webpage as https://WebApp.Company.com/Board which means my api call of https://WebApp.Company.com/API wasn't ever hitting the URL ReWrite, what ended up fixing my issue was in my react webpage i changed the external URL to be https://WebApp.Company.com/Board rather then https://WebApp.Company.com so the API call ended up looking like https://WebApp.Company.com/Board/API/deplist.

<configuration>
  <system.webServer>
    <httpErrors errorMode="Detailed" />
    <asp scriptErrorSentToBrowser="true" />
    <rewrite>
      <rules>
        <!-- New Rule for API Reverse Proxy -->
        <rule name="API Reverse Proxy" stopProcessing="true">
          <match url="^api/(.*)" />
          <conditions logicalGrouping="MatchAll">
            <add input="{HTTP_HOST}" pattern=".*" />
          </conditions>
          <action type="Rewrite" url="https://APIServer/api/{R:1}" />
        </rule>

        <!-- Existing Rule for React Routes -->
        <rule name="React Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="/Board/" />
        </rule>
      </rules>
      <outboundRules>
        <preConditions>
          <preCondition name=".*" patternSyntax="Wildcard" />
        </preConditions>
      </outboundRules>
    </rewrite>
  </system.webServer>
</configuration>```



Solution

  • Directly test the endpoint https://WebApp.Company.com/api/deplist in the browser or using Postman.

    • If this fails, the rewrite rule is not forwarding requests correctly. Check the IIS logs and enable Failed Request Tracing for /api/* requests to diagnose the issue.

    Check the /api/ rule is not overridden by the React routes rule. Add a condition to explicitly exclude /api/ requests from being processed by the React routes rule.

    <add input="{URL}" pattern="^api/" negate="true" />
    

    Updated rewrite rules:

    <rewrite>
      <rules>
        <!-- API Reverse Proxy -->
        <rule name="API Reverse Proxy" stopProcessing="true">
          <match url="^api/(.*)" />
          <conditions logicalGrouping="MatchAll" />
          <action type="Rewrite" url="https://APIServer/api/{R:1}" />
        </rule>
    
        <!-- React Routes -->
        <rule name="React Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{URL}" pattern="^api/" negate="true" />
          </conditions>
          <action type="Rewrite" url="/Board/" />
        </rule>
      </rules>
    </rewrite>
    

    If the browser blocks requests with a CORS error, Check the API server allows requests from the web app domain (https://WebApp.Company.com).