Understanding what it takes to remove the hash # from angular routes

Before removing the hash sign, I had

mainApp.config(function ($locationProvider, $routeProvider) {
    $routeProvider
    .when('/page', {
        controller: 'Page',
        templateUrl: 'templates/page.html'
    })
    .when('/main', {
        controller: 'Main',
        templateUrl: 'templates/main.html'
    })
    .otherwise({ redirectTo: '/main'});

    //$locationProvider.html5Mode(true);
});

and these worked fine

http://localhost:8080/index.html#/main
http://localhost:8080/index.html#/page

After removing the pound sign, I added to index.html

<base href="/">
<script src="/vendor/bootstrap-dist/js/bootstrap.min.js"></script>
<script src="/vendor/javascript/angular/angular.js"></script>
<script src="/vendor/javascript/angular/angular-route.js"></script>
<script src="/vendor/javascript/angular/ui-bootstrap-tpls-0.11.2.min.js"></script>
<script src="/javascript/index.js"></script>
<script src="/javascript/controllers/main.js"></script>
<script src="/javascript/controllers/page.js"></script>

and to index.js

$locationProvider.html5Mode(true);

now hitting http://localhost:8080 redirects to http://localhost:8080/main

but going to http://localhost:8080/main directly in the browser returns 404 and the other pages too

What should I do to fix the problem?

my backend is java


That's expected. Here's what happens when html5 is not turned on:

  • you enter the url http://localhost:8080/index.html#/main in the address bar
  • the browser makes a http request to localhost:8080/index.html and gets the html page as a response
  • the html page contains an angular application that is executed. The angular router parses the path after the hash (/main), and thus loads the associated view and controller

Now what happens when you enable html5 mode and load index.hml?

  • you enter the url http://localhost:8080/index.html in the address bar
  • the browser makes a http request to localhost:8080/index.html and gets the html page as a response
  • the html page contains an angular application that is executed. The angular router parses the path (/index.html), sees that it doesn't match any route, and thus changes the location in the address bar to the default: /main, and then loads the associated view and controller. Changing the location in the address bar doesn't make the browser do anything other than adding a new entry in its navigation history.

Now, what happens if you hit refresh, or directly enter http://localhost:8080/main in the address bar? Well in that case, you're saying the browser: "please load the page at the url http://localhost:8080/main. So that's what the browser does: it sends an HTTP request to http://localhost:8080/main. Since the server doesn't have anything at this address, it sends back a 404.

Now how to make it work? It's actually quite simple: you need to configure the server to send back the index.html page when it gets a request for the path /main (and for all the other paths of the angular application). That way, the browser will load the HTML page, the angular application it contains will be restarted, the angular router will parse the path (/main) from the URL, and it will thus load the view and the controller associated to that path.