it-swarm.com.de

react Routing ist in der Lage, verschiedene URL-Pfade zu verarbeiten, Tomcat gibt jedoch nicht verfügbare Ressourcen zurück

Ich bin neu in reactjs und habe ein kleines Projekt in reactjs, mit dem ich spielen und lernen kann. Ich muss Header eingeben, die basierend auf URL-Pfaden angezeigt werden. Das Folgende ist also meine index.js, die das Routing übernimmt:

 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'));

Wie Sie sehen, verwende ich test als Root-Verzeichnis. Auf der Grundlage der Benutzereingaben für die URL entschied ich mich, welchen Header ich verwenden soll. Auch hier ist Bridge2.js:

export class Bridge2 extends React.Component {
render() {

    return (
        <div>
            <div className="row">
                <Header2/>
            </div>
            <div className="row">
                {this.props.children}
            </div>
        </div>
    );
}
}

und 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
    );
}
}

Wenn ich dies in einem Webpack-Dev-Server ausführen, funktioniert alles einwandfrei. Wenn ich zum Beispiel http://localhost:3003/test/ bridge.js verwende, und wenn ich http://localhost:3003/test/t/ bridge2.js lade, wird das geladen, was erwartet wird.

Da der Web Pack Dev Server jedoch kein Produktionsserver ist, verwende ich Tomcat. Jetzt verwende ich das Eclipse-Webanwendungsprojekt, und ich habe meine bundle.js-Datei und die index.html dort hin kopiert. Nun ist das Problem, wenn ich den Tomcat-Server betreibe, kann er diesen Pfad gut erkennen und anzeigen: 

http://localhost:8080/test/ aber für http://localhost:8080/test/t/ bekomme ich:

HTTP-Status 404 -/test/t /

das heißt im Grunde, dass die Ressourcendatei nicht verfügbar ist. Soweit ich das beobachte, stellt dies kein Problem bei der Codierung dar, da das Routing in Web Pack Dev-Servern einwandfrei funktioniert. Bei Tomcat scheint das Reagieren mit Routing jedoch nicht in der Lage zu sein. Stimmt etwas nicht mit dem, was ich tue? Ist das überhaupt machbar? Kann jemand helfen?

16
Hamed Minaee

Zunächst müssen Sie die folgenden Unterschiede beachten, wenn Sie den reakt-Router verwenden.

Wenn Sie in Ihrem Browser 'localhost: 3003/test /' eingeben, fordert der Server den Server an und erhält dann /test/index.html, das js-Bundle, css, ...

Wenn Sie anschließend auf einen internen Link klicken (z. B. 'localhost: 3003/test/t /'), fordert Ihr Browser den Server nicht erneut an. 

Der React-Router löst dieses clientseitige Problem auf, rendert Teile der Seite erneut und aktualisiert die Adressleiste des Browsers (mithilfe von html5 pushstate), ohne eine weitere Serveranfrage auszulösen.

Wenn Sie 'localhost: 3003/test/t /' direkt in die Adressleiste eingeben, fordert Ihr Browser den Server an, und Tomcat verfügt nicht über /test/t/index.html oder gibt eine Fehlermeldung aus. Weil Tomcat nichts über React-Redux und Javascript weiß.

Um dies zu umgehen, können Sie 404-Fehler so konfigurieren, dass sie an /test/index.html weitergeleitet werden. Wahrscheinlich ist Ihr Webpack-Dev-Server standardmäßig konfiguriert.

Es gibt viele Beispiele dafür auf Apache, wenn Sie eines vor unserem Tomcat haben. Suchen Sie nach "html5 pushstate Apache config".

Hier ist ein Beispiel 

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>
...

Wenn Sie nur Tomcat verwenden, können Sie versuchen, dies in der web.xml in Ihrer Kriegsdatei anzugeben.

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

Beachten Sie, dass dies kein spezifisches Problem der Reaktion ist, da jede App, die html5 pushstate verwendet, dies irgendwie behandeln muss. Javascript-Server können dies jedoch nahtloser handhaben. 

31
Rafael Z.

Meine Lösung ist eine Problemumgehung für JSP-Engines (z. B. Tomcat), funktioniert jedoch mit minimalem Code hervorragend.

Ich habe eine "index.jsp" parallel zu "index.html" (im Inhaltsverzeichnis) mit folgendem Code erstellt:

index.jsp

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

Ich habe alle URLs konfiguriert, um sie in web.xml an diese JSP weiterzuleiten

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>

Nun wird jede an Tomcat angeforderte URL intern zu index.jsp umgeleitet, die effektiv index.html ist. Sobald der Reakt-Router im Browser geladen ist, sorgt er dafür, dass die richtige Komponente und nachfolgende Anforderungen gerendert werden.

5
Bipul

Tomcat hat eine einfache integrierte Lösung dafür . Sie brauchen es nicht hinter Apache zu stellen oder auf das Hash-Routing zu wechseln oder eine Weiterleitungsseite zu hacken, um zu einem anderen Ort auf Ihrem eigenen Server zurückzukehren ...

Dies sollte für jedes Single-Page-App-Framework mit UI-Routing wie React, Angular, ExtJS usw. funktionieren.


In einer Nussschale:

1) Fügen Sie ein RewriteValve zu .__ hinzu. 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) Schreibregeln für alle Pfade unter /webapps/{your-web-app-directory}/WEB-INF/rewrite.config hinzufügen

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

Diese einfachen Regeln weisen Tomcat an, alle Anforderungen mit diesen drei benannten Pfaden direkt an index.html zu senden. 

Die Regeln können jedoch viel schicker werden, beispielsweise das Senden aller Anforderungen an index.html außer einen bestimmten Pfad, z. für /api-Anrufe, die woanders hingehen müssen. Der oben verlinkte Text umfasst alle Details.

2
Geronimo

Ich denke, eine Antwort auf die Frage des OP sollte auch den Zugriff auf statische Ressourcen über das Standard-Servlet betreffen.

Nach meinem Verständnis tritt das Problem in Multi-View-React-Anwendungen auf, bei denen ein Router zum Ändern der Seiten-URL verwendet wird, um den Status der Anwendung anzuzeigen. Dies ist Nizza, aber wenn Sie die Seite versehentlich neu laden, erhalten Sie 404, da es keine Ressource gibt, die der geänderten URL entspricht. Dies bedeutet auch, dass solche veränderten URLs nicht als direkter Zugriff auf verschiedene Anwendungsansichten mit einem Lesezeichen versehen werden können. Es sei denn, wir bekommen eine kleine Hilfe von der Serverseite.

Je nachdem, wie der Zugriff auf statische Ressourcen gehandhabt wird, oder der gewählten Implementierung (Filter, Servlet oder sogar JSP), sind weitere Lösungen möglich. Die Grundidee besteht jedoch darin, die Hauptanwendungs-HTML-Datei für jede in React definierte Route bereitzustellen.

Angenommen, Sie verfügen über zwei in Ihrer Anwendung definierte Reaktionsrouten:

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

Sie könnten ein RouterServlet erstellen, um Anforderungen an/view1 oder/view2 zurück an das Kontextstammverzeichnis (/) weiterzuleiten, vorausgesetzt, Sie haben die Anwendung hier zugeordnet.

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

Sie können es so konfigurieren:

<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
arpadf

Ich bin zwar nicht mit Tomcat vertraut, aber es ist am wahrscheinlichsten, dass Ihr Server nach einer /test/t- oder /test/t/index.html-Datei sucht.

Wenn Sie einen Browserverlauf verwenden, benötigen Sie einen Server, der Routing verarbeiten kann. Normalerweise handelt es sich dabei um eine Wildcard-Route (*), die Ihre index.html-Datei zurückgibt (die wiederum Ihre gebündelten Js sowie alle anderen statischen Dateien in der Indexdatei zurückgibt).

Eine Lösung besteht darin, zur Verwendung eines Hash-Routers zu wechseln. Wenn Sie kein Routing auf dem Server durchführen können (besonders relevant für Personen, die statische Inhalte hosten), ist Hash-Routing erforderlich. Da Sie jedoch einen Server verwenden, können Sie sollten Routing einrichten können, mit dem Sie einen Browser-Router verwenden können.

Wie gesagt, ich bin mit Tomcat nicht vertraut, daher werde ich nur beschreiben, wie die Konfiguration aussehen soll.

  1. Alle Anfragen nach statischen Dateien sollten regelmäßig ausgeführt werden.
  2. Alle anderen Anfragen an /test/* (wobei * eine beliebige URL ist) sollten Ihre index.html-Datei liefern.
1
Paul S

Ich habe das gleiche Problem, dass das Routing nicht funktioniert. Wenn 404 das index.html-Problem nicht umleitet und lädt. Ich habe mehrere Möglichkeiten ausprobiert und schließlich eine Lösung gefunden, die mein Problem gelöst hat.

Bei Tomcat 8 hat das funktioniert

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

Sie können dies durch 

Sudo gedit /opt/Tomcat/webapps/ROOT/WEB-INF/web.xml

fügen Sie das unten in die web.xml ein

<!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>

Starten Sie den Kater neu. Das Problem mit dem Routing wurde behoben. Ich hoffe, das hilft jemandem, den ich denke. Vielen Dank

1
Shinto Joseph

Für Tomcat-Versionen unter 8. Sie können einfach eine web.xml - Datei hinzufügen und den 404 an index.html Weiterleiten.

webapps/[mein-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
Jerad Rutnam

In meinem Fall wollte ich eine einfache Lösung wie beim Erstellen einer Kundenfehlerseite. Diese Lösung setzt jedoch immer noch einen Statuscode 404, der nicht erwünscht ist.

Daher verwende ich eine kleine JSP-Datei, die den Statuscode auf 200 setzt, bevor die index.html des SPAs ausgegeben werden.

Ich hoffe, dass dies jemand anderen hilft, nach einer einfachen Lösung zu suchen, ohne den Status 404 zurückzugeben.

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
Clayton Bell