Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 History API auto routing refresh error

I am currently working with a project using SpringBoot at the backend and HTML5 and Angular 2 at the frontend.

After I deploy the project, everything works fine when I navigate in the browser, until I press reload button. Browser will show error page.

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Mon May 08 10:16:14 CDT 2017

There was an unexpected error (type=Not Found, status=404).

No message available

This is apparently being caused by the use of the HTML 5 history API to store client-side navigation in the browser URL.

So when I start to click on items on the page, I see the URL automatically appends itself.

However, this becomes a problem when refresh is hit, the full appended URL is sent to server which can't understand it because a specific mapping of that appended URL doesn't exist.

Is there a fix to this that updates the server-side configuration so that any unknown URL returns a view of the root index.html view?

For example, when I hit refresh, the URL being queried is simply the root url http://localhost:8080/root, rather than the appended URL.

This will let the browser properly navigate rather than trying to do it on the server side.

like image 220
000000000000000000000 Avatar asked May 08 '17 15:05

000000000000000000000


People also ask

What is the HTML5 History API?

The HTML5 history API allows us to manipulate the browser history through JavaScript, some of these features have been available in older HTML versions. However, the new bits came along with HTML5.

How do I change the URL in the history API?

The most significant thing with these history API’s is that they don’t reload the page. In the past, the only way to change the URL was to change the window.location which always reloaded the page. Except, if all you changed was the hash (like how clicking a <a href="#target">link</a> doesn’t reload the page).

How do I refresh the current page in the history stack?

(The current page's relative position is 0 .) Similarly, you can move forward 2 pages by passing 2, and so forth. Another use for the go () method is to refresh the current page by either passing 0, or by invoking it without an argument: You can determine the number of pages in the history stack by looking at the value of the length property:

How do I change the URL of a website without refresh?

Using the HTML5 History API. The HTML5 History API gives developers the ability to modify a website's URL without a full page refresh. This is particularly useful for loading portions of a page with JavaScript, such that the content is significantly different and warrants a new URL. Here's an example.


2 Answers

If you look at their angular tutorial there is a relevant section "Using Natural Routes":

using a simple Spring MVC controller you can naturalize the routes in your application. All you need is a a way to enumerate the Angular routes in the server. Here we choose to do it by a naming convention: all paths that do not contain a period (and are not explicitly mapped already) are Angular routes, and should forward to the home page:

@Controller
public class SpaController {
    @RequestMapping(value = "/{[path:[^\\.]*}")
    public String redirect() {
        return "forward:/";
    }
}
like image 64
dave Avatar answered Oct 14 '22 19:10

dave


Since it seems you are only using SpringBoot as a backend, you could either redirect all your requests to the index.html

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

  @Controller
  static class Routes {

    @RequestMapping(value = "/**", method = RequestMethod.GET)
    public String index() {
      return "index.html";
    }

  }

}

Or override the ErrorController to catch the /error you are seeing and redirect to your index instead

import org.springframework.boot.autoconfigure.web.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class OverrideController implements ErrorController {

  @RequestMapping("/error")
  public String index() {
    return "index.html";
  }

  @Override
  public String getErrorPath() {
    return "index.html";
  }

}

But I would recommend to separate entirely the frontend from the backend, by serving your angular app with something that could be as basic as Nginx, since you just need to serve static files. SpringBoot seems a bit overkill or not really fit for this purpose.

Here is a good configuration example you could look into for this purpose, which is basically a catch all to an index.html

server {
  server_name yoursite.com;
  root /usr/share/html;
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }
}
like image 27
Preview Avatar answered Oct 14 '22 18:10

Preview