Ronit Oommen
Ronit Oommen

Reputation: 3160

404 Error on refresh for angular(v4+) deployed on tomcat server

I have deployed an angular application with lazy loading. The application works perfectly when hosted on Github.io domain but I am getting an error when I deployed the app on tomcat server using mobaxterm. When the page reloads or refreshes the app loses the routing state and throws a 404 error.

HTTP Status 404 - /enquiry

type Status report

message /enquiry

description The requested resource is not available.

Apache Tomcat/7.0.72

Console-Log:: GET http://appv2.proctur.com/enquiry/addEnquiry 404 (Not Found) Navigated to http://appv2.proctur.com/enquiry/addEnquiry

If I do not refresh the page and use the app in one go then its OK, just fail to understand what the issue is on refresh.

PS:: this is my first time hosting an angular application on tomcat server if I made any silly mistake please let me know.

For better clarification, I am adding the routing.module.ts where I lazy load the modules. This is imported into app.module.ts::

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

@NgModule({
imports: [
    RouterModule.forRoot([
        { path: '', redirectTo: '/authPage', pathMatch: 'full' },
        { path: 'authPage', loadChildren: 'app/components/auth-page/auth-page.module#AuthPageModule' },
        { path: 'course', loadChildren: 'app/components/course/course.module#CourseModule' },
        { path: 'enquiry', loadChildren: 'app/components/enquiry/enquiry.module#EnquiryModule' },
        { path: 'student', loadChildren: 'app/components/students/student.module#StudentModule' },
    ])
],
exports: [
    RouterModule
]
})
export class AppRoutingModule {
}

Upvotes: 20

Views: 19820

Answers (5)

Abd Abughazaleh
Abd Abughazaleh

Reputation: 5545

I solved my problem by config web.xml inside Angular Project

1 - Create Folder WEB-INF inside src angular folder and add web.xml with below code :

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

2 - Modify angular.json search on "assets" and add "src/WEB-INF" as below :

  "assets": [
              "src/favicon.ico",
              "src/assets",
              "src/WEB-INF"
            ],

3 - Build angular project with this command :

ng build --prod

4 - Modify <base href="/"> in index.html after build it in dist/index.html to be <base href="./">

5 - Restart Tomcat Server

Upvotes: 6

Sunil Shakya
Sunil Shakya

Reputation: 9487

This also working if you defind 404 page Web.xml file

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

So refresh page http://appv2.proctur.com/enquiry/addEnquiry 404 error found redirect to index.html and call your actual route in anguler side then it will go to correct location.

Upvotes: 9

Nithin Kumar Biliya
Nithin Kumar Biliya

Reputation: 3011

Angular (2+) supports two types of Routing Strategies – HashLocationStrategy and PathLocationStrategy. PathLocationStrategy is the default configuration when you build an application using the angular CLI. PathLocationStrategy is having lot of advantages over the HashLocationStrategy and is the recommended configuration which is discussed in the docs here.

The drawback of PathLocationStrategy is that it needs specific configuration to be done at the server side. If this configuration is not done at the server end, then it leads to 404 when deep links are accessed directly. Also this configuration depends on which server is being used.

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

Upvotes: 9

Armen Vardanyan
Armen Vardanyan

Reputation: 3315

The previous answer is correct, but we don't really need hashes in our url-s. The problem is as follows: For example, if we have a route named '/users/all', and navigate there from '/' inside our app, then it is perfectly okay, as Angular's own router will resolve the route and display the page, but if we go directly to that route, e.g. by typing in the url in the browser's address bar, we'll get 404, Why? Because your server (tomcat in your case) will try to find a folder named 'users' and an 'all' file inside it, which, obviously, is non-existent, as it is merely an Angular route, not an actual file inside your server's system. But you can configure your server in a way, the it will fallback to your index.html file, which contains the app, so the pages will be displayed correctly (in the case of our example, the server will return index.html, then the Angular app will run and resolve the route). Read more about this here.

Upvotes: 11

Akshay Garg
Akshay Garg

Reputation: 1040

When angular app load first-time url will serve from a server. when you navigate pages then it handled at client side. when you refresh the page then request will go to server(tomcat or node). but that routed url doesn't exist on server. then comes 404 error. you can resolve by HashLocationStrategy, added {useHash: true} object in routing configuration ie.

RouterModule.forRoot(routes, {useHash: true})

More details:- https://codecraft.tv/courses/angular/routing/routing-strategies/#_hashlocationstrategy

Upvotes: 24

Related Questions