9

I have custom routes like follows:

// @flow

import React, { PureComponent } from 'react';
import { Switch, Redirect } from 'react-router-dom';
import { withRouter } from 'react-router';

import { Route } from 'components/Routes';
import Story from 'pages/Story';
import Page404 from 'pages/404';

class Routes extends PureComponent<{}> {
  render() {
    return (
      <Switch>
        <Route exact path="/" render={props => <Story {...props} />} />
        <Route
          exact
          path="/chapter/:id"
          render={props => <Story {...props} />}
        />
        <Route path="/404" render={props => <Page404 {...props} />} />
        <Redirect to="/404" /* Must be the last one */ />
      </Switch>
    );
  }
}

export default withRouter(Routes);

This works fine in localhost, if I visit localhost:3000/chapter/3 the web app redirects successfully, unfortunately in live builds running on azure app services if I visit: mysite.azurewebsites.net/chapter/3 I'm given an error:

The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

I'm running a Windows based App Service plan. I'm sure there's some option to set up redirecting, i.e. /chapter/* -> /www_siteroot/ but I haven't been able to figure out how to do it.

I fixed the issue by going to the app service settings and adding /chapter/1, /chapter/2, etc, etc under 'Virtual applications and directories' and directing them to site\wwwroot.

I'd prefer to have a wildcard option like /chapter/* but it doesn't seem to work and I get an error.

meds
  • 21,699
  • 37
  • 163
  • 314

4 Answers4

12

If you have your repo connected to the Azure Web App, then you can place this web.config file in the /public folder of a create-react-app project.

<?xml version="1.0"?>
<configuration>
    <system.webServer>

        <directoryBrowse enabled="false"/>

        <urlCompression doDynamicCompression="true" doStaticCompression="true"/>

        <!-- <staticContent>
            <clientCache cacheControlMaxAge="120.00:00:00" cacheControlMode="UseMaxAge"/>
        </staticContent> -->
        <caching enabled="true" enableKernelCache="true">
            <profiles>
                <add extension=".css" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
                <add extension=".js" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
                <add extension=".svg" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
                <add extension=".png" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange"/>
            </profiles>
        </caching>

        <rewrite>
            <rules>
                <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="{REQUEST_URI}" pattern="^/(api)" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/index.html" />
                </rule>
            </rules>
        </rewrite>

    </system.webServer>
</configuration>
craigcaulfield
  • 3,381
  • 10
  • 32
  • 40
ericswyang
  • 121
  • 1
  • 3
  • 1
    All I want to say is Thank you for this. Been fighting this issue for a week and you resolved it for me in 1 min. – Matt Jul 06 '21 at 19:54
  • @ericswyang I am running the app service on a Linux server on Azure. I tried this solution but it does not work. – Archit Sandesara Aug 09 '21 at 20:49
6

Since you're on Windows based App Service Plan, your Azure webapp is running under IIS with URL Rewriting module enabled. As such, you can create a simple URL Rewrite rule that directs all requests coming from https://mysite.azurewebsites.net/chapter/* to your site root in which case the client will receive your React/Redux application, and your React application would take care of all subsequent logic and rendering of content etc..

Here are the steps to create this URL Rewrite rule:

  1. In Azure Portal, create FTP deployment credentials.
  2. Locally on your computer, create a Web.config file with following content:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="Chapter-Redirect" stopProcessing="true">
                    <match url="chapter/*" />
                    <action type="Rewrite" url="/" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>
  1. Open up FTP client (Filezilla is a good one) and login to your site and upload the Web.config file.
  2. Test by visiting: https://mysite.azurewebsites.net/chapter/*

Here's more info on IIS URL Rewrite.

Mike Urnun MSFT
  • 463
  • 3
  • 4
  • This answer is the real deal. I was misguided by a sub-optimal answer that shouldn't have 84 votes: https://stackoverflow.com/a/50767709/3231884 THANKS A LOT! – Luis Gouveia Jul 31 '20 at 13:06
  • @Mike I am running the app service on Linux server on Azure. I tried this solution but it does not work. – Archit Sandesara Aug 09 '21 at 20:47
1

Solution to those who are running App Service with Linux is to create configuration file .htaccess instead of web.config. Create this file to root of your public folder with the following content:

RewriteEngine On
RewriteRule "^[^\.]+$" "index.html"
Tommi L.
  • 360
  • 1
  • 6
  • 14
0

I was trying to do the same with a Azure Static Web App using a Create React App that deploys from GitHub. None of the above seemed to work for me, but adding a staticwebapp.config.json in my project's root with the following got URL rewriting working properly again:

{
  "navigationFallback": {
    "rewrite": "index.html",
    "exclude": ["*.{svg,png,jpg,gif}","*.{css,scss}","*.js"]
  }
}

See the documentation about Fallback Routes here.

Mike Skott
  • 181
  • 1
  • 10