Angular deep linking - Apache Tomcat

2020-07-17 05:01发布

问题:

I'm building an Angular app. It is hosted with base a href as /hris. So my base url to access the app will be domain.com/hris. Further, I have 3 different apps of which one is called term. So when I click on the term link it goes to domain.com/hris/term.

When the user directly tries to access the link domain.com/hris/term, it returns 404 with a message: HTTP Status 404 - /hris/term.

I don't want 404 to occur. How to get this done?

What I have done so far:

I tried to create a .htaccess file in the folder, where index.html resides.(I built the Angular app using ng build --base-href=/hris/). I deployed the dist folder to the server in a directory called hris.

In the .htaccess file I used the following variants, to no avail.

1

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

2

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

3

    <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteCond %{REQUEST_FILENAME} -s [OR]
        RewriteCond %{REQUEST_FILENAME} -l [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^.*$ - [NC,L]
        RewriteRule ^(.*) index.html [NC,L]
   </IfModule>

I am using Angular 5. Please let me know if my approach is right, or what I have to do to get this going.

Version: Apache Tomcat 7- Version 7.0.64

回答1:

".htaccess" files do not work on Tomcat. Put the rewriting config into a file WEB-INF/rewrite.conf, maybe like this:

RewriteCond %{SERVLET_PATH} !-f
RewriteRule ^/(.*)$ /index.html [L]

Next you need to add a file called META-INF/context.xml which enables the rewriting, i.e.:

<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true" tldValidation="false" xmlValidation="false">

  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

</Context>

Also remove the HashLocationStrategy from your Angular app.

Update

Why rewriting

  • Since Angular apps are SPAs the only real page that gets addressed at all is index.html.
  • Therefore any link like an href would leave that page and quit the app.
  • Angular uses its Router to redirect to virtual paths inside the app, without leaving index.html.
  • A web server would guess these paths are real files and since they do not exist, respond with an 404 HTTP status (in case of Tomcat its the DefaultServlet serving static content).
  • To get around this problem url rewriting can be used.

How to enable rewriting

  • First you need to enable the RewriteValve, which is a network filter and is disabled by default. To do so, you can add a context.xml to your war file like in the example above (portable version), or add it to the server.xml (server-side version).
  • After that add a rewrite.conf file to setup the rewriting conditions.
  • In the example above the first line tells Tomcat to look for "files which are not real/existing files" !-f, in the current servlet path. The servlet path part is neccessary, if your app is not deployed as ROOT (i.e. www.xyz.com/myApp) and will be set accordingly.
  • The second line mapps every "virtual path" from the Angular router to index.html.


回答2:

For fixing the deep link issue when deploying angular application (with PathLocationStrategy routing) on apache tomcat server (8, 9) -

  1. Configure the RewriteValve in server.xml
  2. Write the rewrite rule in rewrite.config

server.xml -

...
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />

...
      </Host>
...

rewrite.config - (note - /hello/ is the context path of the angular app on tomcat)

RewriteCond %{REQUEST_PATH} !-f
RewriteRule ^/hello/(.*) /hello/index.html

I have documented this in my article - Fixing deep linking issue – Deploying angular application on Tomcat server