13

I am using react-router (createBrowserHistory) for my react app.

Below is my code of

var ReactDOM = require('react-dom') ;

var ReactRouter = require('react-router');
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var Link = ReactRouter.Link;
var browserHistory = require('react-router');
var createBrowserHistory = require('history/lib/createBrowserHistory');

var CL = require('./page1/1.jsx');
var Validation = require('./page3/3.jsx');
var Infos = require('./page4/4.jsx');
var Confirm = require('./page7/7.jsx');
var Upload = require('./page8/8.jsx');

module.exports = (

  <Router history={new createBrowserHistory()}> 
    <Route path='/' component={CL}></Route>                                                                                                                                     
    <Route path='/validation' component={Validation}></Route>                                                                                                                                     
    <Route path='/infos' component={Infos}></Route>                                                                                                                                     
    <Route path='/confirm' component={Confirm}></Route>                                                                                                                                     
    <Route path='/upload' component={Upload}></Route>                                                                                                                                     
  </Router>
)

Wen run IIS on local, I go to localhost on browser, I can get "CL" component and show on page, however, if I go to /validation, I will get

Failed to load resource: the server respond with status of 404 (Not Found)

Anyone know what need to add to IIS or my js code to make this routing work?

tanguy_k
  • 11,307
  • 6
  • 54
  • 58
Dreams
  • 8,288
  • 10
  • 45
  • 71

6 Answers6

23

I think you are talking about react-router or similar stuff below configuration on iis 7 works for me

<rules>
     <rule name="Rewrite Text Requests" stopProcessing="true">
         <match url=".*" />
             <conditions>
                        <add input="{HTTP_METHOD}" pattern="^GET$" />
                        <add input="{HTTP_ACCEPT}" pattern="^text/html" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
             </conditions>
             <action type="Rewrite" url="/index.html" />
     </rule>
</rules>
Bo Chen
  • 717
  • 1
  • 9
  • 16
  • 2
    Awesome. I had it added to the web.config under `` section – mike123 Nov 03 '16 at 00:29
  • This works in most cases, but I had an issue with facebook crawler where it would receive a 404. It turns out that the `Accept` header is set to `*/*` when the crawler hits a site with the `{HTTP_ACCEPT}` rule above. This causes a 404 not found to display on facebook when sharing a link for example. Removing the `{HTTP_ACCEPT}` rule fixed it for me as verified [here](https://developers.facebook.com/tools/debug/sharing). Any gotchas with removing that condition? – GotDibbs Jan 01 '17 at 18:04
  • Would be amazing if someone posted a gist of a working web.config. – Learner Feb 03 '17 at 04:57
  • Great! In case you need ` – Roland Dec 27 '19 at 11:17
13

I've struggled with this a little bit so I write it for the next person: First update the web.config file (as Bo Chen mentioned).

 <system.webServer>
    <rewrite>
      <rules>
        <rule name="Rewrite Text Requests" stopProcessing="true">
          <match url=".*" />
          <conditions>
            <add input="{HTTP_METHOD}" pattern="^GET$" />
            <add input="{HTTP_ACCEPT}" pattern="^text/html" />
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
          </conditions>
          <action type="Rewrite" url="/index.html" />
        </rule>
      </rules>
    </rewrite>

This will find every request and rewrite it to /index.html instead.

So you need to have a index.html in the root of your project. Also pay attention to the extension of the file.

Ashkan S
  • 10,464
  • 6
  • 51
  • 80
3

One additional thing to note: make sure you have the URL Rewrite extension installed.

https://www.iis.net/downloads/microsoft/url-rewrite

You may also need to do an iisreset after installation.

devly
  • 35
  • 1
  • 6
3

Here is a working web.config file

<?xml version="1.0"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
     <rule name="Rewrite Text Requests" stopProcessing="true">
         <match url=".*" />
             <conditions>
                        <add input="{HTTP_METHOD}" pattern="^GET$" />
                        <add input="{HTTP_ACCEPT}" pattern="^text/html" />
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
             </conditions>
             <action type="Rewrite" url="/index.html" />
     </rule>
</rules>
    </rewrite>
  </system.webServer>
</configuration>
2

There are two things you can do...

  1. Add virtual paths to point to your spa folder for every route.
  2. Use IIS URL rewrite module. This is a long discussion to your using the SO app, so here's a post describing it- http://weblogs.asp.net/owscott/rewrite-vs-redirect-what-s-the-difference
hazardous
  • 10,627
  • 2
  • 40
  • 52
  • What you mean add virtual paths for every route?Because the router config is in a js file. – Dreams Feb 21 '16 at 07:31
  • In IIS you need to add virtual paths for every route. This makes IIS serve your spa when the browser requests the route. Right now, IIS doesn't know what to do when browser asks for /validation. After you create a "validation" virtual path and map it to your spa folder, IIS will send back your spa. – hazardous Feb 21 '16 at 07:56
  • how to add virtual paths? i only see virtual directory and it only can point to folder not js file – Dreams Feb 21 '16 at 07:58
  • It's the same thing :). If your spa is called index.html, IIS will send it back when request is for the parent folder. – hazardous Feb 21 '16 at 07:59
  • so you mean I just point to the same folder which index.html located. – Dreams Feb 21 '16 at 08:09
  • Yes, think of it this way, when you don't use hash routes, every time routes changes, on refresh, browser makes a request with the full path to IIS. Without a mapping, it doesn't know what content to send back. This is why you need virtual folders or URL rewrites. I'd recommend the latter as you can add regex to send back spa on any sub path. Otherwise you need to keep fiddling with virt folders for every route change. – hazardous Feb 21 '16 at 08:20
  • I'd recommend using URL-rewrite, as all you need is returning the spa for any sub-paths. – hazardous Feb 24 '16 at 10:22
  • Ya... I want to use URL-rewrite. I will try it out these days again.Really appreciated!! – Dreams Feb 26 '16 at 08:42
1

Another option is using an application on top of IIS to ensure you've got other features that might come in handy, like the ASP.NET framework with MVC on top of it. You could have a route there that simply catches all requests that aren't specifically mapped (like /api, /content) and route these to the html in such a way that your React app can handle it. The benefits over pure IIS really depend on your circumstance.

The following is my route configuration for ASP.NET Core, to give you an example:

app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action}/{id?}",
                defaults: new {controller = "Home", action = "Index"},
                constraints: new { controller = new NotEqualConstraint("api")});

            routes.MapRoute("api", "api/{controller}/{action}/{id?}");
            routes.MapRoute("React failover", "app/{*uri}", new {controller = "App", action = "Index"},
                new {controller = new NotEqualConstraint("api")});

        });
janpieter_z
  • 1,722
  • 13
  • 28
  • this sounds good.I will try it. So the routing will map to index action which will go to my index.html which include my react.js file? – Dreams Feb 23 '16 at 15:55
  • Exactly! I'm using a 'specific' App controller and /app is where I host mine, but depending on your situation it can simply be the normal index. – janpieter_z Feb 23 '16 at 16:00