Skip to content

Commit bf44dc2

Browse files
constantantAndrewKushnir
authored andcommitted
fix(common): Update Location to support base href containing origin (#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
1 parent 7df1989 commit bf44dc2

File tree

3 files changed

+71
-12
lines changed

3 files changed

+71
-12
lines changed

packages/common/src/location/location.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export class Location implements OnDestroy {
5757
/** @internal */
5858
_subject: EventEmitter<any> = new EventEmitter();
5959
/** @internal */
60-
_baseHref: string;
60+
_basePath: string;
6161
/** @internal */
6262
_locationStrategy: LocationStrategy;
6363
/** @internal */
@@ -67,8 +67,8 @@ export class Location implements OnDestroy {
6767

6868
constructor(locationStrategy: LocationStrategy) {
6969
this._locationStrategy = locationStrategy;
70-
const browserBaseHref = this._locationStrategy.getBaseHref();
71-
this._baseHref = stripTrailingSlash(_stripIndexHtml(browserBaseHref));
70+
const baseHref = this._locationStrategy.getBaseHref();
71+
this._basePath = _stripOrigin(stripTrailingSlash(_stripIndexHtml(baseHref)));
7272
this._locationStrategy.onPopState((ev) => {
7373
this._subject.emit({
7474
'url': this.path(true),
@@ -127,7 +127,7 @@ export class Location implements OnDestroy {
127127
* @returns The normalized URL string.
128128
*/
129129
normalize(url: string): string {
130-
return Location.stripTrailingSlash(_stripBaseHref(this._baseHref, _stripIndexHtml(url)));
130+
return Location.stripTrailingSlash(_stripBasePath(this._basePath, _stripIndexHtml(url)));
131131
}
132132

133133
/**
@@ -294,10 +294,18 @@ export function createLocation() {
294294
return new Location(ɵɵinject(LocationStrategy as any));
295295
}
296296

297-
function _stripBaseHref(baseHref: string, url: string): string {
298-
return baseHref && url.startsWith(baseHref) ? url.substring(baseHref.length) : url;
297+
function _stripBasePath(basePath: string, url: string): string {
298+
return basePath && url.startsWith(basePath) ? url.substring(basePath.length) : url;
299299
}
300300

301301
function _stripIndexHtml(url: string): string {
302302
return url.replace(/\/index.html$/, '');
303303
}
304+
305+
function _stripOrigin(baseHref: string): string {
306+
if (/^(https?:)?\/\//.test(baseHref)) {
307+
const [, pathname] = baseHref.split(/\/\/[^\/]+/);
308+
return pathname;
309+
}
310+
return baseHref;
311+
}

packages/common/test/location/location_spec.ts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {CommonModule, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
9+
import {APP_BASE_HREF, CommonModule, Location, LocationStrategy, PathLocationStrategy, PlatformLocation} from '@angular/common';
1010
import {MockLocationStrategy, MockPlatformLocation} from '@angular/common/testing';
1111
import {TestBed} from '@angular/core/testing';
1212

@@ -55,7 +55,7 @@ describe('Location Class', () => {
5555
return new MockPlatformLocation();
5656
}
5757
},
58-
{provide: Location, useClass: Location, deps: [LocationStrategy, PlatformLocation]},
58+
{provide: Location, useClass: Location, deps: [LocationStrategy]},
5959
]
6060
});
6161

@@ -147,7 +147,7 @@ describe('Location Class', () => {
147147
return new MockPlatformLocation();
148148
}
149149
},
150-
{provide: Location, useClass: Location, deps: [LocationStrategy, PlatformLocation]},
150+
{provide: Location, useClass: Location, deps: [LocationStrategy]},
151151
]
152152
});
153153

@@ -215,4 +215,55 @@ describe('Location Class', () => {
215215
expect(notificationCount).toBe(1);
216216
});
217217
});
218+
219+
describe('location.normalize(url) should return only route', () => {
220+
const basePath = '/en';
221+
const route = '/go/to/there';
222+
const url = basePath + route;
223+
const getBaseHref = (origin: string) => origin + basePath + '/';
224+
225+
it('in case APP_BASE_HREF starts with http:', () => {
226+
const origin = 'http://example.com';
227+
const baseHref = getBaseHref(origin);
228+
229+
TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});
230+
231+
const location = TestBed.inject(Location);
232+
233+
expect(location.normalize(url)).toBe(route);
234+
});
235+
236+
it('in case APP_BASE_HREF starts with https:', () => {
237+
const origin = 'https://example.com';
238+
const baseHref = getBaseHref(origin);
239+
240+
TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});
241+
242+
const location = TestBed.inject(Location);
243+
244+
expect(location.normalize(url)).toBe(route);
245+
});
246+
247+
it('in case APP_BASE_HREF starts with no protocol', () => {
248+
const origin = '//example.com';
249+
const baseHref = getBaseHref(origin);
250+
251+
TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});
252+
253+
const location = TestBed.inject(Location);
254+
255+
expect(location.normalize(url)).toBe(route);
256+
});
257+
258+
it('in case APP_BASE_HREF starts with no origin', () => {
259+
const origin = '';
260+
const baseHref = getBaseHref(origin);
261+
262+
TestBed.configureTestingModule({providers: [{provide: APP_BASE_HREF, useValue: baseHref}]});
263+
264+
const location = TestBed.inject(Location);
265+
266+
expect(location.normalize(url)).toBe(route);
267+
});
268+
});
218269
});

packages/common/testing/src/location_mock.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export class SpyLocation implements Location {
2525
/** @internal */
2626
_subject: EventEmitter<any> = new EventEmitter();
2727
/** @internal */
28-
_baseHref: string = '';
28+
_basePath: string = '';
2929
/** @internal */
3030
_locationStrategy: LocationStrategy = null!;
3131
/** @internal */
@@ -43,7 +43,7 @@ export class SpyLocation implements Location {
4343
}
4444

4545
setBaseHref(url: string) {
46-
this._baseHref = url;
46+
this._basePath = url;
4747
}
4848

4949
path(): string {
@@ -81,7 +81,7 @@ export class SpyLocation implements Location {
8181
if (url.length > 0 && !url.startsWith('/')) {
8282
url = '/' + url;
8383
}
84-
return this._baseHref + url;
84+
return this._basePath + url;
8585
}
8686

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

0 commit comments

Comments
 (0)