Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(common): Location does not support base href containing origin #48327

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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