Mateusz Klimentowicz
Mateusz Klimentowicz

Reputation: 709

Angular / Spring Boot / Azure Ingress - URL rewriting

I use Angular as frontend technology, spring boot for the backend and Azure Ingress as webserver. My problem is that when the user refreshes the site there comes an 404 error because of Angular routes. I wonder if this approach to solve this problem is a good practice and if there may araise any problem with my own AJAX calls:

@Configuration
class WebApplicationConfig
{
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer()
    {
        return container -> {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/index.html"));
        };
    }
}

?

Edit

What I am searching for is some kind of URL rewriting (e.g. on Apache webserver) for my technology stack. Currently there is a static folder in the JAR file that is returning my Angular files. If the link is requested always the angular files (index.html and dependencies) are returned but while the user is working the URL changes (only in frontend) and if he then hit site refresh there comes an 404 error.

e.g.

http://somehost/some/static/url/ <-- OK

http://somehost/some/static/url/and/angular/route <-- 404

So I wonder if the solution above would be a good one. Or maybe there is another better solution?

Upvotes: 0

Views: 340

Answers (2)

Georg Wittberger
Georg Wittberger

Reputation: 386

It sounds like your Angular app is directly served by your Spring Boot app. If you want to stick with this solution (avoiding a separate web server) you will have to make sure that Spring Boot serves the index.html of your Angular app under any route (except those intended for API of course), as stated by Mixalloff.

Here is how I did it in a project:

  • Put the Angular project as a sub-project in your Maven project, let's say in src/main/frontend. So if you build the Angular app you will get its static resources in the folder src/main/frontend/dist.
  • Use the maven-resources-plugin to copy only the index.html generated in src/main/frontend/dist to the output directory target/classes/templates. So there should be the file target/classes/templates/index.html in the end.
  • Use the maven-resources-plugin to copy any other static resources (like JavaScript, CSS, etc.) from src/main/frontend/dist to the output directory target/classes/static. This is where your files are also located currently.
  • Include a cheap template engine into your Spring Boot app, e.g. use the spring-boot-starter-mustache to get Mustache auto-configured as your template engine for Spring MVC. We will use the index.html generated for your Angular app as a Mustache template.
  • Create a Spring controller with a method returning the index view name for any path. Note the request mapping to /** here:

    @Controller
    public class IndexPageController {
      @RequestMapping("/**")
      public String index() {
        return "index";
      }
    }
    

The wildcard method returning the index page is automatically sorted last by Spring MVC, see https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-ann-requestmapping-pattern-comparison

So you can still add more controllers mapped to more specific paths, e.g. /api/v1/whatever.

In the end, your Spring Boot app will always return the index.html file for any route that does not match a more specific request mapping.

And this comes with even more sugar: Since the index.html is processed as a Mustache template it can contain server-side template markup if needed.

Upvotes: 2

Mixalloff
Mixalloff

Reputation: 837

The Angular is independently determine routes and must manage the display of 404 Page and another pages. You need always give away index.html file for all requests in your server

Upvotes: 0

Related Questions