Skip to content

Commit

Permalink
fix(common): Update Location to support base href containing `origi…
Browse files Browse the repository at this point in the history
…n` (#48327)

In case `APP_BASE_HREF` is set including `origin` the further usage of it might cause failure

e.g.
If an app is placed on `https://example.com` and bundles are on `https://cdn-example.com` you have to set `APP_BASE_HREF` up as `https://example.com/` and build the app with `--base-href` as `https://cdn-example.com/` but it does not work because of the bug

Fixes #48175

PR Close #48327
  • Loading branch information
constantant authored and AndrewKushnir committed Dec 7, 2022
1 parent 7df1989 commit bf44dc2
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 12 deletions.
20 changes: 14 additions & 6 deletions packages/common/src/location/location.ts
Expand Up @@ -57,7 +57,7 @@ export class Location implements OnDestroy {
/** @internal */
_subject: EventEmitter<any> = new EventEmitter();
/** @internal */
_baseHref: string;
_basePath: string;
/** @internal */
_locationStrategy: LocationStrategy;
/** @internal */
Expand All @@ -67,8 +67,8 @@ export class Location implements OnDestroy {

constructor(locationStrategy: LocationStrategy) {
this._locationStrategy = locationStrategy;
const browserBaseHref = this._locationStrategy.getBaseHref();
this._baseHref = stripTrailingSlash(_stripIndexHtml(browserBaseHref));
const baseHref = this._locationStrategy.getBaseHref();
this._basePath = _stripOrigin(stripTrailingSlash(_stripIndexHtml(baseHref)));
this._locationStrategy.onPopState((ev) => {
this._subject.emit({
'url': this.path(true),
Expand Down Expand Up @@ -127,7 +127,7 @@ export class Location implements OnDestroy {
* @returns The normalized URL string.
*/
normalize(url: string): string {
return Location.stripTrailingSlash(_stripBaseHref(this._baseHref, _stripIndexHtml(url)));
return Location.stripTrailingSlash(_stripBasePath(this._basePath, _stripIndexHtml(url)));
}

/**
Expand Down Expand Up @@ -294,10 +294,18 @@ export function createLocation() {
return new Location(ɵɵinject(LocationStrategy as any));
}

function _stripBaseHref(baseHref: string, url: string): string {
return baseHref && url.startsWith(baseHref) ? url.substring(baseHref.length) : url;
function _stripBasePath(basePath: string, url: string): string {
return basePath && url.startsWith(basePath) ? url.substring(basePath.length) : url;
}

function _stripIndexHtml(url: string): string {
return url.replace(/\/index.html$/, '');
}

function _stripOrigin(baseHref: string): string {
if (/^(https?:)?\/\//.test(baseHref)) {
const [, pathname] = baseHref.split(/\/\/[^\/]+/);
return pathname;
}
return baseHref;
}
57 changes: 54 additions & 3 deletions packages/common/test/location/location_spec.ts
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {CommonModule, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
import {APP_BASE_HREF, CommonModule, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
import {MockLocationStrategy, MockPlatformLocation} from '@angular/common/testing';
import {TestBed} from '@angular/core/testing';

Expand Down Expand Up @@ -55,7 +55,7 @@ describe('Location Class', () => {
return new MockPlatformLocation();
}
},
{provide: Location, useClass: Location, deps: [LocationStrategy, PlatformLocation]},
{provide: Location, useClass: Location, deps: [LocationStrategy]},
]
});

Expand Down Expand Up @@ -147,7 +147,7 @@ describe('Location Class', () => {
return new MockPlatformLocation();
}
},
{provide: Location, useClass: Location, deps: [LocationStrategy, PlatformLocation]},
{provide: Location, useClass: Location, deps: [LocationStrategy]},
]
});

Expand Down Expand Up @@ -215,4 +215,55 @@ describe('Location Class', () => {
expect(notificationCount).toBe(1);
});
});

describe('location.normalize(url) should return only route', () => {
const basePath = '/en';
const route = '/go/to/there';
const url = basePath + route;
const getBaseHref = (origin: string) => origin + basePath + '/';

it('in case APP_BASE_HREF starts with http:', () => {
const origin = 'http://example.com';
const baseHref = getBaseHref(origin);

TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});

const location = TestBed.inject(Location);

expect(location.normalize(url)).toBe(route);
});

it('in case APP_BASE_HREF starts with https:', () => {
const origin = 'https://example.com';
const baseHref = getBaseHref(origin);

TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});

const location = TestBed.inject(Location);

expect(location.normalize(url)).toBe(route);
});

it('in case APP_BASE_HREF starts with no protocol', () => {
const origin = '//example.com';
const baseHref = getBaseHref(origin);

TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});

const location = TestBed.inject(Location);

expect(location.normalize(url)).toBe(route);
});

it('in case APP_BASE_HREF starts with no origin', () => {
const origin = '';
const baseHref = getBaseHref(origin);

TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});

const location = TestBed.inject(Location);

expect(location.normalize(url)).toBe(route);
});
});
});
6 changes: 3 additions & 3 deletions packages/common/testing/src/location_mock.ts
Expand Up @@ -25,7 +25,7 @@ export class SpyLocation implements Location {
/** @internal */
_subject: EventEmitter<any> = new EventEmitter();
/** @internal */
_baseHref: string = '';
_basePath: string = '';
/** @internal */
_locationStrategy: LocationStrategy = null!;
/** @internal */
Expand All @@ -43,7 +43,7 @@ export class SpyLocation implements Location {
}

setBaseHref(url: string) {
this._baseHref = url;
this._basePath = url;
}

path(): string {
Expand Down Expand Up @@ -81,7 +81,7 @@ export class SpyLocation implements Location {
if (url.length > 0 && !url.startsWith('/')) {
url = '/' + url;
}
return this._baseHref + url;
return this._basePath + url;
}

go(path: string, query: string = '', state: any = null) {
Expand Down

0 comments on commit bf44dc2

Please sign in to comment.