A routing reaction is capable of handling different URLs, but tomcat returns 404 inaccessible resources

I am new to reactjs and I have a small project in reactjs to play and learn it. I need to have a type of headers to be shown based on the urls. So this is my index.js that handles routing:

  const history = useRouterHistory(createHistory)({ basename: '/test' }) class Tj extends React.Component { render() { return ( <Router history={history}> <Route path={"/"} component={Bridge} > <IndexRoute component={Home} /> <Route path={"user"} component={T} /> <Route path={"home"} component={Home} /> </Route> <Route path={"/t/"} component={Bridge2} > <IndexRoute component={T} /> <Route path={"contact"} component={Home} /> </Route> </Router> ); } } render( <Provider store={store}> <Tj/> </Provider>, window.document.getElementById('mainContainer')); 

As you can see, I use test as the root directory and based on user input for url. I decide which title to use. Also here is Bridge2.js :

 export class Bridge2 extends React.Component { render() { return ( <div> <div className="row"> <Header2/> </div> <div className="row"> {this.props.children} </div> </div> ); } } 

and Bridge.js :

 export class Bridge extends React.Component { render() { // alert(this.props.children.type); var Content; if(this.props.children.type){ Content=<div> <div className="row"> <Header/> </div> <div className="row"> {this.props.children} </div> </div>; } else{ Content=<div> <div className="row"> <Header/> </div> <div className="row"> {this.props.children} </div> </div>; } return ( Content ); } } 

When I run this on the webpack dev server everything works fine. For example, when I use http://localhost:3003/test/ , the bridge.js file is loaded, and if I run http://localhost:3003/test/t/ , the bridge2.js file is loaded, which is expected.

However, since the dev web package server is not a production server, I am using tomcat, and at the moment I am using the eclipse web application project, and I copied the bundle.js file and index.html there. Now the problem is that when I start the tomcat server, it is able to recognize and show this path:

http://localhost:8080/test/ , but when for http://localhost:8080/test/t/ we get:

HTTP Status 404 - / test / t /

which basically says the resource file is unavailable. As far as I understand, this is not a problem in coding, as routing works fine in the dev web package server, but when it comes to tomcat, it seems that the routing reaction is not able to handle it. Is there something wrong with what I'm doing? Is this done in general? Can anyone help?

+20
source share
8 answers

First you should be aware of the following differences when using a reactive router.

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

After that, whenever you click on an internal link (for example, "localhost: 3003 / test / t /"), your browser will no longer request a server.

React-router will solve this client side, redisplay parts of the page and refresh the address bar of the browser (using html5 pushstate) without starting another server request.

When you enter "localhost: 3003 / test / t /" directly in the address bar, your browser requests the server, and Tomcat does not have /test/t/index.html or so, and it returns 404, This is because Tomcat doesn’t knows about reduction reaction or javascript.

The way to handle this is to set up 404 errors to go into /test/index.html. It is likely how your devp web server server is configured by default.

There are many examples of this on apache if you have one in front of our Tomcat. Search for "html5 pushstate apache config".

Here is one 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 use only tomcat, you can try to specify this in the web.xml file inside your war file.

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

Please note that this is not a problem with a specific route, every application using html5 pushstate should somehow handle this. However, Javascript servers can handle this more easily.

+36
source

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 return to another place on your own server ...

Use Tomcat Rewrite

It works for any single page application environment that has UI routing like React, Angular, ExtJS, etc.


In a nutshell:

1) Add 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 with the name: / /tomcat/webapps/{your-web-app-directory}/WEB-INF/rewrite.config and then add rewrite rules for any paths that you want to indicate on 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 directly to index.html.

3) Restart Tomcat

Rules can become more elegant, like sending all requests to index.html, except for a certain path, which is useful for calls /api that should go somewhere other than index.html . The link above covers additional use cases for Tomcat Rewrite.

+7
source

My solution is similar to a workaround for JSP engines (like Tomcat), but works fine with minimal code.

I created "index.jsp" in parallel with "index.html" (in the root folder of the content) with the following code:

index.jsp

 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@include file="index.html"%> 

I configured all the URLs to redirect to this JSP in web.xml

web.xml

 <servlet> <servlet-name>index</servlet-name> <jsp-file>index.jsp</jsp-file> </servlet> <servlet-mapping> <servlet-name>index</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> 

Now, any URL requested by Tomcat will be internally redirected to index.jsp, which is effectively index.html. After loading the adapter in the browser, it takes care of rendering the correct component and subsequent requests.

+6
source

I have the same problem as routing does not work. If 404 does not redirect or load the index.html problem. I tried several ways and finally found a solution that 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 

Can you do this

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

paste below in 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 Tomcat. This fixed the routing problem for me. Hope this helps someone I think. thanks

+4
source

While I am not familiar with Tomcat, it is most likely that your server is looking for the file /test/t or /test/t/index.html , and since it does not exist, it returns a 404 error.

When you use browser history, you need to have a server that can handle routing. This will usually be a wildcard ( * ) pattern that returns your index.html file (which, in turn, will return your nested js, as well as any other static files included in the index file).

One solution is to switch to a hash router. If you cannot route on the server (this is especially important for people who post static content), then hash routing is required. However, since you are using a server, you should be able to configure routing that allows you to use a browser router.

As I said, I am not familiar with Tomcat, so I just describe what should be in the configuration.

  • All requests for static files should be performed regularly.
  • All other /test/* requests (where * is any URL) should serve your index.html file.
+1
source

I think that the answer to the OP question should also concern access to static resources through the default servlet.

In my understanding, the problem arises in React multiple view applications, where Router is used to change the page URL to reflect the state of the application. This is good, but if you reload the page by accident, you will get 404, since there will be no resource corresponding to the changed URL. It also means that such modified URLs cannot be marked as direct access to various application views. Unless we get a little help from the server.

Depending on how access to static resources is handled or the chosen implementation (filter, servlet or even JSP), there are more solutions, but the main idea is to serve the main application HTML file for all Routes defined in the Response.

Suppose you have two React Routes defined in your application:

 <Route path={"view1"} component={View1} /> <Route path={"view2"} component={View2} /> 

You can create a RouterServlet to forward requests to / view1 or / view2 back to the root context (/), assuming you have mapped the application here.

 void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getServletContext().getRequestDispatcher("/").forward(request, response); } 

You can configure it as follows:

 <servlet> <servlet-name>RouterServlet</servlet-name> <servlet-class>package.RouterServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>RouterServlet</servlet-name> <url-pattern>/view1/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>RouterServlet</servlet-name> <url-pattern>/view2/*</url-pattern> </servlet-mapping> 
+1
source

In my case, I wanted a simple solution, like when creating a page with a client error. However, this solution still sets the status code 404 which is undesirable.

Therefore, I use a small JSP file that sets the status code to 200 before displaying SPA index.html .

I hope this helps someone else looking for a simple solution without returning 404 status.

web.xml

 <error-page> <error-code>404</error-code> <location>/spa.jsp</location> </error-page> 

spa.jsp

 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><% response.setStatus(200); %><%@include file="./dashboard/index.html"%> 
0
source

For versions of Tomcat below 8. You can simply add web.xml and direct 404 to index.html .

webapps / [my-app-name] / WEB-INF / web.xml

 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>my-app-name</display-name> <error-page> <error-code>404</error-code> <location>/index.html</location> </error-page> </web-app> 
0
source

Source: https://habr.com/ru/post/1013352/


All Articles