14

I'm trying to figure out the way how to setup Apache Tomcat server to serve angular application with deep links. For example:

A static server routinely returns index.html when it receives a request for mysite.com/. But it rejects mysite.com/heroes/42 and returns a 404 - Not Found error unless it is configured to return index.html instead.

I want to serve angular app on localhost/angular, I have tried following:

1) Build angular application with:

ng build --prod --base-href .

2) Copy contents of build folder(default: dist) to $ApacheLocation/webapps/angular

3) Add RewriteRules at $ApacheLocation/conf/Catalina/localhost/rewrite.config

# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]  
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d  
RewriteRule ^ - [L]

# If the requested resource doesn't exist, use index.html
RewriteRule ^\/angular\/.*$ /angular/index.html

4) Adding valve just below Host tag

 <Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true"> 
   <Valve className="org.apache.catalina.valves.rewrite.RewriteValve"/>

5) Starting Tomcat server and going to localhost/angular will give me:

Uncaught SyntaxError: Unexpected token < for all .js bundles (e.g main.bundle.js)

If I don't include rewrite rules, tomcat will serve localhost/angular as expected but will give 404 on deep links.

My setup configuration:

  • tomcat version 9.0.0.M26
  • angular version 4.4.2
  • @angular/cli: 1.4.2
  • node: 8.5.0
  • npm: 5.4.2
  • os: linux x64
4
  • i had that problem and i know how fix that, just leave your index .html content here and the path you want to put your project in. then i will leave an answer, just reply me when you done that Commented Sep 20, 2017 at 7:28
  • Here is full link to test project: github.com/avuletica/test try to host it on localhost/angular @valakhosravi Commented Sep 20, 2017 at 8:16
  • i want to see your dist folder (the folder that built after ng build --prod --base-href ). Commented Sep 20, 2017 at 8:23
  • Pushed changes with ng build --prod -bh . -d /angular check build folder @valakhosravi Commented Sep 20, 2017 at 8:27

2 Answers 2

8

I managed to fix this problem e.g http://localhost:8080/angular/player/detail/4 with following steps:

1) Build angular application with: ng build --prod -bh ./ -d /angular

2) Copy contents of builded app to $ApacheLocation/webapps/angular

3) Rewrite rule:

RewriteCond %{REQUEST_PATH} !-f
RewriteRule ^/angular/(.*) /angular?path=$1

4) Setup navigation at app.component.ts:

constructor(private activatedRoute: ActivatedRoute, private router: Router) { }

ngOnInit() {
const path = this.activatedRoute.snapshot.queryParams['path'];
const navigateTo = '/' + path;

if (path) {
  this.router.navigate([navigateTo]);
}

}

You can find test project here: https://github.com/avuletica/test

Explanation of rewrite rules:

# %{REQUEST_PATH} corresponds to the full path that is used for mapping.
# ! NOT character 
# '-f' (is regular file) Treats the TestString as a pathname and tests whether or not it exists, and is a regular file.
# ^ matches the beginning of the string or line
# . matches any charceter except line breaks
# * match 0 or more of the preceding token

So basically if there is no file on /angular/anything tomcat sends full path as query string to angular application and from that query param angular handles routing.

Sign up to request clarification or add additional context in comments.

4 Comments

There should be no need to make any client-side changes. Angular CLI's dev server supports deep links without such configuration, so it must be possible exclusively server-side.
@Ante Vulentic Antic.. Where to add the Rewrite rule.?
client side changes are not optimal solution imho
We have sorted out the same issues but got one big one after that, there is no good way to clear the cache after each deployment, as tomcat overrides the no-cache headers from index.html
3

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 issue in my article - Fixing deep linking issue – Deploying angular application on Tomcat server

Note - there is no client side setup needed for achieving this (apart from the default config coming out of CLI). All the client side routing is handles by the Angular Routing module.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.