react routing is able to handle different url path but tomcat returns 404 not available resources

First, you must be aware of the following differences when using react-router.

When you enter localhost:3003/test/ in your browser, it will request the server, and then it will receive /test/index.html, the js bundle, css, ...

After that, whenever you click an internal link (eg. localhost:3003/test/t/), your browser will not request the server again. React-router will resolve this client-side, re-render portions of the page, and update browser's address bar (using HTML5 pushstate()), without triggering another server request.

When you enter localhost:3003/test/t/ directly in the address bar, your browser will request the server, and Tomcat does not have /test/t/index.html or so, and it returns a 404. It's because Tomcat doesn't know anything about react-redux nor javascript.

A way to handle this is to configure 404 errors to be forward to /test/index.html. It's probably how your webpack dev server is configured by default.

There is plenty of examples of doing this on apache, if you have one in front of our Tomcat. Search for html5 pushstate apache config.

Here is an example:

httpd.conf:

...
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
 </IfModule>
...

If you are using Tomcat alone, you may try to specify this in the web.xml, inside your .war file:

...
<error-page>
    <error-code>404</error-code>
    <location>/index.html</location>
</error-page>
...

Note that this is not a react-router specific problem, every app that uses HTML5 pushstate() needs to handle this somehow. Javascript servers may handle this more seamlessly though.


Tomcat 8 and above has a simple built-in solution for this. You do not need to put it behind Apache to handle this, or switch to hash routing, or hack a redirect page to go back to a different place on your own server...

Use Tomcat Rewrite

It works for any single-page-app framework that has UI-routing like React, Angular, ExtJS, etc.


In a nutshell:

1) Add a RewriteValve to /tomcat/webapps/{your-web-app-directory}/META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context>  
  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
  ... your other context items
</Context>

2) Create a file named: /tomcat/webapps/{your-web-app-directory}/WEB-INF/rewrite.config and then add rewrite rules for any paths you want to point to your index page:

RewriteRule ^/user(.*)$    /index.html [L]
RewriteRule ^/home(.*)$    /index.html [L]
RewriteRule ^/contact(.*)$ /index.html [L]

These rules tell Tomcat to send all requests with these three named paths straight to index.html.

3) Restart Tomcat

The rules can get fancier, like sending all requests to index.html except for a certain path, which is useful for /api calls that have to go somewhere besides index.html. The link above covers additional examples of how to use Tomcat Rewrite.


I have the same problem routing not working. If 404 not redirecting and loading the index.html problem. I tried several ways and finally found a solution which fixed my problem.

This worked for me on Tomcat 8

inside ROOT folder of Tomcat make a new folder WEB-INF and create web.xml 

You can do this by

sudo gedit /opt/tomcat/webapps/ROOT/WEB-INF/web.xml

paste the below in the web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>your_display_name</display-name>

    <error-page>
        <error-code>404</error-code>
        <location>/index.html</location>
    </error-page>

</web-app>

Restart the Tomcat. This fixed the routing problem for me. Hope this helps for someone I think. Thanks