Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

$location.absUrl() returns undefined with base href and html5Mode #11091

Closed
ilovett opened this issue Feb 17, 2015 · 53 comments
Closed

$location.absUrl() returns undefined with base href and html5Mode #11091

ilovett opened this issue Feb 17, 2015 · 53 comments

Comments

@ilovett
Copy link

ilovett commented Feb 17, 2015

Running Angular 1.3.13

base href to load all assets from a specific subdirectory

    <base href="/marketing/" />

enable html 5 mode

    // remove hash /#/
    $locationProvider.html5Mode(true);

Routes are setup like this:

    $routeProvider
      .when('/', {
        templateUrl: 'views/main.html',
        controller: 'MainCtrl'
      })
      .when('/about', {
        templateUrl: 'views/about.html',
        controller: 'AboutCtrl'
      })
      .otherwise({
        redirectTo: '/'
      });

Upon loading the application, the following error is thrown n times (I believe per anchor href on the page)

2VM9729 angular.js:11607 TypeError: Cannot read property 'replace' of undefined
    at trimEmptyHash (VM9729 angular.js:10564)
    at $LocationProvider.$get (VM9729 angular.js:11374)
    at Object.invoke (VM9729 angular.js:4185)
    at VM9729 angular.js:4003
    at getService (VM9729 angular.js:4144)
    at Object.invoke (VM9729 angular.js:4176)
    at VM9729 angular.js:4003
    at getService (VM9729 angular.js:4144)
    at Object.invoke (VM9729 angular.js:4176)
    at VM9729 angular.js:6485

Debugging this issue, I found at this line:

    // rewrite hashbang url <> html5 url
    if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
      $browser.url($location.absUrl(), true);
    }

$location.absUrl() returns undefined

My GUESS is that the base href is throwing off the matching of routes at $.when('/'), and so is undefined...

@ilovett
Copy link
Author

ilovett commented Feb 17, 2015

BTW, this setup of serving assets from a subdirectory but having the routes relative to root is required for our setup of having 2 separate applications running on the same domain, we just needed to differentiate the static folders from each other and don't want to include those subdirectories in every route.

This may not be a bug but would be nice to have some way of telling angular about how to map routes vs. assets

@Feamor
Copy link

Feamor commented Feb 19, 2015

I have the same problem.

My base href is ru

When I run applucation by

http://myDomain.com/ru 

it's all right, but when I use

http://myDomain.com 

(without base href) I have an exception

TypeError: Cannot read property 'replace' of undefined

@ghost
Copy link

ghost commented Feb 27, 2015

The same for me, also with Angular 1.3.14

@kindofone
Copy link

Same for me. Any response on this?

@Chryssie
Copy link

Chryssie commented Mar 4, 2015

I just encountered this issue, however, I'm not using ngRoute in any fashion. My case was that the check for the base url was case sensitive and my url in the browser was lowercase, but in the base is was uppercase.

The function in question that was doing the case sensitive comparison for me was "beginsWith" in $$parseLinkUrl (there's two of those). While it may not be exactly what your case is this is where it parses the absUrl so that would be a good place to see what's happening.

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

@ilovett
Copy link
Author

ilovett commented Mar 4, 2015

related #11223

@SamHwang1990
Copy link

it seem the bug is caused by the 814th line in file "src/ng/location.js": $location.$$parseLinkUrl(initialUrl, initialUrl);

the code above send the initialUrl as param twice, it is weird, so i try to send appBase as the first param to $$parseLinkUrl, then the bug fixed.

just want to know this is a correct solution?

@akerfoot
Copy link

@SamHwang1990, that will not work if you use any app routing.

For example, if you have the following:

// From <base> href Url
baseHref = '/username/'
// From $browser.url(), what the user typed in the URL bar
initialUrl = 'http://www.example.com/UserName/additional/path/data/?queryString=something#fragment/data'
// From appBase = serverBase(initialUrl) + (baseHref || '/');
appBase = 'http://www.example.com/username/'

If you pass appBase as the first param to $$parseLinkUrl, you will lose all of the routing data, in this case additional/path/data/?queryString=something#fragment/data.

The two parameters for $$parseLinkUrl are the absolute URL and the relative URL, and in this case, since the url is from the browser (not an href link in the body) there is not relative URL so the full path is passed for both.

@akerfoot
Copy link

@Chryssie, and anyone dealing with case-sensitivity, you may want to read what I wrote over on #11223

@jscontrust
Copy link

Same here with angular 1.3.14
Is there a workaround? Is it fixed in 1.4.0? I´m at development status so it would be ok for me to install a unstable version...

@joelmdev
Copy link

Same issue here. Workaround is to set base path to "/" and use full url paths.

@mikerains
Copy link

mikerains commented Mar 17, 2015

https://docs.angularjs.org/guide/$location - see the section on "Relative links" - using "/my-base" and the prior section "HTML link rewriting" example of "/not-my-base/link".

My app configured with:
<base href="Main"/>
$locationProvider.html5Mode(true);

Should be able to have <a href="/Main/Somepage"/> that causes $location.path to change
Should be able to have <a href="/not-my-base/Somepage"/> that causes window.location.href to change (ie: cause a browser refresh).

However when the ng-app is initializing, the routing configuration fails with error stack::
Cannot read property 'replace' of undefined
at trimEmptyHash
In Angular.js line 10551 (for version 1.3.14)

Also tried 1.4.x.

@joelmdev
Copy link

I believe I have this sorted. I'm trying to build angular from scratch to regression test a fix, but running into some issues. Will submit a pull request as soon as I get angular built and tested.

@Narretz
Copy link
Contributor

Narretz commented Mar 22, 2015

That sounds great @joelmdev
Don't hesitate to ask if you have problems with the build. We always try to make it easier for people to contribute.

@Narretz Narretz added this to the 1.4.x - jaracimrman-existence milestone Mar 22, 2015
@Getitdan
Copy link

Same thing here.

$location.absUrl() returns undefined, so trimEmptyHash function in the following code gets an exception:

if (trimEmptyHash($location.absUrl()) != trimEmptyHash(initialUrl)) {
     $browser.url($location.absUrl(), true);
}

Has someone already solved that?

@joelmdev
Copy link

@Narretz I wasted a lot of time trying to get everything to build on Windows and ultimately had to go with an Ubuntu VM. Still working out some bugs with the VM, but I got Angular to build and the unit tests to run. I may need some assistance on creating an e2e test to cover the fix. Any pointers on where I can go to get some advice on that?

@Narretz
Copy link
Contributor

Narretz commented Mar 23, 2015

@joelmdev
Not knowing what problems you had, I've been using git bash on Windows, maybe you can give this a try if the cl integration is lacking.
Most location tests are unit tests, but a good e2e is always welcome.
The e2e tests are run with protractor (via grunt). You can add your own inside test/e2e: you need both a test file (with normal jasmine specs etc.) and a fixture file, which is the base html for your test. Protractor will automatically wait for angular in your spec file, and then you can inspect the page or change to location etc. See the protractor docs for more about that.

@pinnprophead
Copy link

I have this problem also. Can the fix be shared until an updated release is made?

@joelmdev
Copy link

starting at line 10811, replace

var locationPrototype = {

  /**
   * Are we in html5 mode?
   * @private
   */
  $$html5: false,

with

var locationPrototype = {

  /**
   * Ensure absolute url is initialized.
   * @private
   */
  $$absUrl:'',

  /**
   * Are we in html5 mode?
   * @private
   */
  $$html5: false,

@Narretz I believe this fix requires an integration test, I don't see how to isolate it enough for a unit test. Would you agree?

@Muenze
Copy link

Muenze commented Jun 15, 2015

@joelmdev
Your solution fixed our problem
file:/// load of our angularJS app in an UIWebView

@joelmdev
Copy link

I'll submit a pull request sometime this week and see where it gets me.

@joelmdev
Copy link

This appears to be fixed, perhaps inadvertently, in the latest version available via Nuget. Can someone else verify?

@Narretz
Copy link
Contributor

Narretz commented Jun 16, 2015

@joelmdev you mean in 1.4.1? The only location fix in it is this: 91b6022

de-code pushed a commit to de-code/bower-angular that referenced this issue Jun 19, 2015
@soee
Copy link

soee commented Jun 20, 2015

Still have this in 1.4.1.

@kenkouot
Copy link

Still seeing this issue in 1.4.1 and installed 1.4.2-build.4082+sha.1ce5d21 from bower and this issue is still present. It breaks the entire page from loading.

@kpennell
Copy link

kpennell commented Jul 6, 2015

Running into this as well. So dang frustrating.

@crucialfelix
Copy link

http://sodr/ru/#!/home http://sodr/ru#!/home should work I think.
You need the trailing slash if that's what your base is set to.

On Wed, Aug 26, 2015 at 11:22 PM Artiom Neganov notifications@github.com
wrote:

My case seems a bit different.
I have an application which should work both in html5 and Hashbang mode:

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

When I access it via html5 url like http://sodr/ru/home it works,
but when I use a variant with hashprefix like http://sodr/ru#!/home it
fails with error:

Uncaught TypeError: Cannot read property 'replace' of undefined in angular.js:11345

is set to 'http://sodr/ru/'

Ideas?


Reply to this email directly or view it on GitHub
#11091 (comment)
.

@joeldenning
Copy link

I'm almost embarrassed to offer this hack as a workaround solution to this problem, but I'm finding it useful so far and thought that it might benefit someone here.

If before you load angular onto the page, you put

        var nativeGetElementsByTagName = document.getElementsByTagName;
        document.getElementsByTagName = function(query) {
            if (query === 'base') {
                return [];
            } else {
                return nativeGetElementsByTagName.apply(this, arguments);
            }
        }

then angular will be fooled into thinking that there is no base tag at all. And then the error referenced in this issue does not happen.

Completely ignoring the base tag may or may not be what you really want in the end, but if it is then this works :p

@joelmdev
Copy link

@joeldenning I'll give this a shot. If this fixes the problem until my fix is committed and approved, then it's a great workaround. I'm having to keep custom copies of angular source in my repo instead of letting a package manager restore them for me as well as apply the same fix in place whenever updates are released.

I know that the fix I provided has worked for everyone that has tried it and doesn't seem to cause any regression bugs, but I'm just not familiar enough with Angular testing to provide the necessary test coverage to submit the change as a pull request.

@Nness
Copy link

Nness commented Oct 20, 2015

I am using angular 1.4.3. The issue for my case is base tag case sensitive.
Eg: path is /aBc/test while base tag setup as /ABC/ then angular throw error that described in this issue. But works fine if base setup as /aBc/.

My application is base on server side MVC, thus I have ability to change base tag value base on query URL. Thus resolved issue.

Challenge is angular base route is case sensitive while my server is case insensitive.

@crucialfelix
Copy link

@Nness set route to be case insensitive:

caseInsensitiveMatch: true

https://docs.angularjs.org/api/ngRoute/provider/$routeProvider

@Nness
Copy link

Nness commented Dec 9, 2015

@crucialfelix

I'm using ui-router not ngRoute. That config is no use. Take look the issue under uirouter:
angular-ui/ui-router#197

@rameshkumarv
Copy link

@joelmdev
your trick helped me and I found exact issue in my app.

I have used "/demo/" as my base URL and I was tried to access my app using "www.domainname.com" got the error. The error is gone when I access the app using the URL "www.domainname.com/demo".

This could help someone.

@codedbypaul
Copy link

Wondering if this is related to the issue I'm having currently.

$location.absUrl()

returns a value in Chrome but not in IE.

I'm using a base url and html5 mode.

rvpatkar added a commit to rvpatkar/angular.js that referenced this issue Feb 19, 2016
rvpatkar added a commit to rvpatkar/angular.js that referenced this issue Feb 19, 2016
…html5Mode

$location's absUrl incorrectly returned undefined when using base href and html5Mode. Initializaing it to fix this issue.

Closes angular#11091
Waldo000000 pushed a commit to ZapTechnology/angular.js that referenced this issue Mar 1, 2016
@ghost
Copy link

ghost commented Mar 24, 2016

(Almost) The same as codedbypaul here,

$location.absUrl()

Returns a correct value in Chrome but not Firefox

@lili21
Copy link

lili21 commented May 24, 2016

still have this in 1.5.5. any plan about this issue?

@gkalpak
Copy link
Member

gkalpak commented May 24, 2016

IIRC a PR was merged into master recently that initializes $$absUrl. It might take care of this.
@lili21, can you check if the problem still exists on the current snapshot ?

@gkalpak
Copy link
Member

gkalpak commented May 24, 2016

The PR I had in mind is #14488, but it hasn't been merged yet. (Thx @Narretz for pointing it out.)
You should keep an eye on that one, @lili21.

@benbr-personal
Copy link

@joelmdev Saved my bacon my friend, this really needs fixing.

First time I've ran into the issue and I've used HTML5Mode on lots of different apps, really need to find out whats causing it.

@Narretz Narretz modified the milestones: 1.4.x, 1.5.x May 27, 2016
@jdimov
Copy link

jdimov commented Jun 5, 2016

I have the same problem in last snapshot as well - AngularJS v1.5.7-build.4844+sha.cd3673e.
Is there any solution?

@gkalpak
Copy link
Member

gkalpak commented Jun 6, 2016

@jdimov, the fixed is tracked at #14488.

@gkalpak gkalpak closed this as completed in b9ac336 Jun 6, 2016
gkalpak pushed a commit that referenced this issue Jun 6, 2016
Initialize `$$absUrl` to an empty string, in order to avoid exception, when base href
and current location have different domains.

Fixes #11091
Fixes #13565

Closes #14488
@jdimov
Copy link

jdimov commented Jun 6, 2016

Thanks. I think in 1.5.6 is working fine.

On Mon, Jun 6, 2016 at 3:54 PM, Georgios Kalpakas notifications@github.com
wrote:

Closed #11091 #11091 via
b9ac336
b9ac336
.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#11091 (comment), or mute
the thread
https://github.com/notifications/unsubscribe/AC3clEx5oIhyALbzKbznuxVXSwKqCvBzks5qJBihgaJpZM4Dhxwb
.

@joelmdev
Copy link

Glad this got fixed. I would have committed the fix a long time ago, but getting an environment setup for angular contribution development proved prohibitively time consuming.

SevInf pushed a commit to SevInf/Charge that referenced this issue Oct 9, 2016
Few changes were required to make it happen:
1. base url must point to ./ and all asset refrences must
use relative paths.
2. Angular must be updated to 1.5.10 due to this bug
angular/angular.js#11091
3. Second package.json, specifically for electron app, is added.
4. main.js file with electron initalisation code is added.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.