Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I am using Angular UI Router in my angular app and i have enabled HTML5 mode to remove the # form the URL by using $locationProvider in the config.

var app = angular.module('openIDC', ['ui.router']);
app.config(function($urlRouterProvider, $stateProvider, $locationProvider) {

    $locationProvider.html5Mode(true);

    $urlRouterProvider.otherwise('/');

    $stateProvider
    .state('home', {
        url: '/',
        templateUrl: 'views/home.html',
        controller: 'HomeController'
    })
    .state('login', {
        url: '/login', 
        templateUrl: 'views/login.html',
        controller: 'LoginController'
    })
});

I have also set the <base href="/" /> tag in the index.html file as well. The routing works fine and i can navigate to pages and the # is removed but when i refresh the page using the reload button on the browser there is a 404 error response.

enter image description here

Why is this happening and how can i fix it and have HTML5 mode enabled to have proper URLs

share|improve this question
up vote 3 down vote accepted

Kasun, the reason that this is occurring is because you are trying to refresh the page from one of your sub routes (has nothing to do with ui-router).

Basically if you request www.yourdomain.com/ you likely have your server setup to return index.html which bootstraps your angular app. Once the app has loaded, any further url changes take html5Mode into consideration and update your page via ui-router.

When you reload your page the angular app is no longer valid as it has not loaded yet, so if you are trying to load a sub route (for example: www.yourdomain.com/someotherpage), then your server does not know how to deal with /someotherpage and likely returns 404 or some other error.

What you need to do is configure your server to return your angular app for all routes. I primarily use node/express, so I do something like:

app.get('*', function(req, res, next) {
    // call all routes and return the index.html file here
}

Note: I usually use something like this as a final catch all, however I also include other routes above it for things like requesting static files, web crawlers, and any other specific routes that need to be handled.

share|improve this answer
    
That's basically the solution. One thing I'd like to add: if your backend is also serving dynamic data, e.g. an API, you want to isolate the API from this redirection, so you have to add this rule only if a file that matches the request does not exists and no other API route is matched as well. – Darlan Alves Apr 29 at 22:39
    
Good point. Updated my answer. As for APIs though, I prefer to run them from a separate url/domain. – Matt Way Apr 30 at 0:42

You need to to setup url rewrite on server side

for apache it would be something like:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.html

in .htaccess file(be sure that mod_rewrite apache module is enabled)

and config like this for nginx:

location / {
    ....
    try_files $uri $uri/ /index.html =404;
}
share|improve this answer
    
How do you do the same thing in IIS? – Kasun Kodagoda Apr 29 at 7:38
1  
Not sure, never done this in IIS. But this answer looks right: stackoverflow.com/questions/12614072/… – Bogdan Savluk Apr 29 at 7:45

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.