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
".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.
For fixing the deep link issue when deploying angular application (with PathLocationStrategy routing) on apache tomcat server (8, 9) -
- Configure the RewriteValve in server.xml
- 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