AngularJS + Base Href Case Sensitive?

All we need is an easy explanation of the problem, so here it is.

I’m struggling to understand why my base href seems to be case sensitive. I have a page with a base href and utilizes angularjs routing.

html:

<html ng-app="app">
    <head>
        <base href="/Foo/" rel="nofollow noreferrer noopener"/>
    </head>
    <body>
        <div>Foo</div>
        <div ng-view></div>  
    </body>
</html>

js:

var module = angular.module('app', []);

module.config(function ($routeProvider, $locationProvider) {
    $routeProvider
        .when('/Home/Page1', { templateUrl = 'partials/page1' })
        .otherwise({ redirectTo: '' });

     $locationProvider.html5Mode(true);
     $locationProvider.hashPrefix('!');
});

If I navigate to http://www.example.com/Foo/, it’s fine. But when I navigate to http://www.example.com/foo/ I get an angular error:

Error: Invalid url "http://www.example.com/foo/", missing path prefix "/Foo" !
at Error (<anonymous>)
at Object.LocationUrl.$$parse (http://www.example.com/foo/Scripts/angular.js:4983:13)
at Object.LocationUrl (http://www.example.com/foo/Scripts/angular.js:5014:8)
at $LocationProvider.$get (http://www.example.com/foo/Scripts/angular.js:5387:21)
at Object.invoke (http://www.example.com/foo/Scripts/angular.js:2809:28)
at http://www.example.com/foo/Scripts/angular.js:2647:37
at getService (http://www.example.com/foo/Scripts/angular.js:2769:39)
at Object.invoke (http://www.example.com/foo/Scripts/angular.js:2787:13)
at $CompileProvider.directive (http://www.example.com/foo/Scripts/angular.js:3613:43)
at Array.forEach (native) angular.js:5582

If it helps/makes a difference, site is hosted on IIS and using MVC 4.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

You need to turn off case sensitivity of angularjs route provider.

Please review the detail of this feature:
add caseInsensitiveMatch option for url matching

Method 2

I’m using UI-router, so was not able to resolve the route case sensitivity using the methods suggested for ngRoute. The solution at
https://github.com/angular-ui/ui-router/issues/197
worked for me for the routes but not for the base href issue which was the original problem posted.

I was able to resolve this issue by adding a decorator for $browser which sets basehref and url to lowercase. If you look at the origin of the values being compared that are causing the issues in the beginsWith method that is causing the issue, you’ll see that they ultimately originate from $browser.

Ultimately, that solution solved for both routes and base href case sensitivity and the $urlRouterProvider suggestion was not needed. So if you don’t have an explicitly set base href element in your DOM, the $urlRouterProvider rule suggested in that link would solve your issue. Otherwise, this solves for both base href and for routes.

Full solution which resolved the issue for both base href and routing using ui-router:

  $provide.decorator('$browser', [
                    '$delegate', function($delegate) {

                        var _baseHref = $delegate.baseHref,
                            _url = $delegate.url;

                        $delegate.baseHref = function() {
                            return angular.lowercase(_baseHref());
                        };
                        $delegate.url = function(url, replace) {
                            // no need to modify the setter
                            if (url) {
                                return _url(url, replace);
                            }
                            // just lowercase the getter
                            return angular.lowercase(_url());
                        };
                        return $delegate;
                    }
                ]);

Method 3

Had the same problem but have a different solution. This works for me and doesn’t interfere with routing, beginsWith or the assumption that things are/should be lower case.

Put this before angular is initialized (like in the head of your html page)

// Fix base url being case sensitive
(function () {
     var base = document.querySelector("base");
     var normalized = RegExp(base.href, "i").exec(location.href);
     base.href = normalized ? normalized[0] : base.href;
}());

Method 4

a nice solution to this problem is to create a decorator for $route and set the rules how case insensitives. With this way you don’t have to create the field caseInsensitiveMatch for each “when”.
In this URL you can found more about this solution: http://iranreyes.com/angularjs-decorating-route

Method 5

As of today, caseInsensitiveMatch is not included in the stable version of AngularJS 1.0.7 but it is included in the unstable version 1.1.5 (https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js)
Tested and working as expected

Method 6

The accepted answer will not work since that only effects the routes and not the base url. This is a bug that looks to be “too hard” to fix for the Angular developers. Reference —https://github.com/angular/angular.js/issues/4056

To fix this yourself you need to rewrite the beginsWith() function in angular.js to compare on lowercase —

function beginsWith(begin, whole) {
	if (whole.toLowerCase().indexOf(begin.toLowerCase()) === 0)
	{
    return whole.substr(begin.length);
  }
}

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply