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.
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.
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).
(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:
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.
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:/";
}
}
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With