feat(common): add APIs to read component pieces of URL (#30055)
Without this change, the framework doesn't surface URL parts such as hostname, protocol, and port. This makes it difficult to rebuild a complete URL. This change provides new APIs to read these values. PR Close #30055
This commit is contained in:
parent
b44b14368f
commit
b635fe80cc
|
@ -35,6 +35,9 @@ export abstract class PlatformLocation {
|
||||||
abstract onPopState(fn: LocationChangeListener): void;
|
abstract onPopState(fn: LocationChangeListener): void;
|
||||||
abstract onHashChange(fn: LocationChangeListener): void;
|
abstract onHashChange(fn: LocationChangeListener): void;
|
||||||
|
|
||||||
|
abstract get protocol(): string;
|
||||||
|
abstract get hostname(): string;
|
||||||
|
abstract get port(): string;
|
||||||
abstract get pathname(): string;
|
abstract get pathname(): string;
|
||||||
abstract get search(): string;
|
abstract get search(): string;
|
||||||
abstract get hash(): string;
|
abstract get hash(): string;
|
||||||
|
|
|
@ -49,6 +49,9 @@ export class BrowserPlatformLocation extends PlatformLocation {
|
||||||
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('hashchange', fn, false);
|
getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('hashchange', fn, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get protocol(): string { return this.location.protocol; }
|
||||||
|
get hostname(): string { return this.location.hostname; }
|
||||||
|
get port(): string { return this.location.port; }
|
||||||
get pathname(): string { return this.location.pathname; }
|
get pathname(): string { return this.location.pathname; }
|
||||||
get search(): string { return this.location.search; }
|
get search(): string { return this.location.search; }
|
||||||
get hash(): string { return this.location.hash; }
|
get hash(): string { return this.location.hash; }
|
||||||
|
|
|
@ -14,9 +14,12 @@ import * as url from 'url';
|
||||||
import {INITIAL_CONFIG, PlatformConfig} from './tokens';
|
import {INITIAL_CONFIG, PlatformConfig} from './tokens';
|
||||||
|
|
||||||
|
|
||||||
function parseUrl(urlStr: string): {pathname: string, search: string, hash: string} {
|
function parseUrl(urlStr: string) {
|
||||||
const parsedUrl = url.parse(urlStr);
|
const parsedUrl = url.parse(urlStr);
|
||||||
return {
|
return {
|
||||||
|
hostname: parsedUrl.hostname || '',
|
||||||
|
protocol: parsedUrl.protocol || '',
|
||||||
|
port: parsedUrl.port || '',
|
||||||
pathname: parsedUrl.pathname || '',
|
pathname: parsedUrl.pathname || '',
|
||||||
search: parsedUrl.search || '',
|
search: parsedUrl.search || '',
|
||||||
hash: parsedUrl.hash || '',
|
hash: parsedUrl.hash || '',
|
||||||
|
@ -29,6 +32,9 @@ function parseUrl(urlStr: string): {pathname: string, search: string, hash: stri
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerPlatformLocation implements PlatformLocation {
|
export class ServerPlatformLocation implements PlatformLocation {
|
||||||
|
public readonly hostname: string = '/';
|
||||||
|
public readonly protocol: string = '/';
|
||||||
|
public readonly port: string = '/';
|
||||||
public readonly pathname: string = '/';
|
public readonly pathname: string = '/';
|
||||||
public readonly search: string = '';
|
public readonly search: string = '';
|
||||||
public readonly hash: string = '';
|
public readonly hash: string = '';
|
||||||
|
@ -39,6 +45,9 @@ export class ServerPlatformLocation implements PlatformLocation {
|
||||||
const config = _config as PlatformConfig | null;
|
const config = _config as PlatformConfig | null;
|
||||||
if (!!config && !!config.url) {
|
if (!!config && !!config.url) {
|
||||||
const parsedUrl = parseUrl(config.url);
|
const parsedUrl = parseUrl(config.url);
|
||||||
|
this.hostname = parsedUrl.hostname;
|
||||||
|
this.protocol = parsedUrl.protocol;
|
||||||
|
this.port = parsedUrl.port;
|
||||||
this.pathname = parsedUrl.pathname;
|
this.pathname = parsedUrl.pathname;
|
||||||
this.search = parsedUrl.search;
|
this.search = parsedUrl.search;
|
||||||
this.hash = parsedUrl.hash;
|
this.hash = parsedUrl.hash;
|
||||||
|
|
|
@ -516,6 +516,22 @@ class HiddenModule {
|
||||||
expect(location.hash).toBe('#hash');
|
expect(location.hash).toBe('#hash');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('parses component pieces of a URL', () => {
|
||||||
|
platformDynamicServer([{
|
||||||
|
provide: INITIAL_CONFIG,
|
||||||
|
useValue: {document: '<app></app>', url: 'http://test.com:80/deep/path?query#hash'}
|
||||||
|
}])
|
||||||
|
.bootstrapModule(ExampleModule)
|
||||||
|
.then(appRef => {
|
||||||
|
const location: PlatformLocation = appRef.injector.get(PlatformLocation);
|
||||||
|
expect(location.hostname).toBe('test.com');
|
||||||
|
expect(location.protocol).toBe('http:');
|
||||||
|
expect(location.port).toBe('80');
|
||||||
|
expect(location.pathname).toBe('/deep/path');
|
||||||
|
expect(location.search).toBe('?query');
|
||||||
|
expect(location.hash).toBe('#hash');
|
||||||
|
});
|
||||||
|
});
|
||||||
it('handles empty search and hash portions of the url', () => {
|
it('handles empty search and hash portions of the url', () => {
|
||||||
platformDynamicServer([{
|
platformDynamicServer([{
|
||||||
provide: INITIAL_CONFIG,
|
provide: INITIAL_CONFIG,
|
||||||
|
|
|
@ -74,7 +74,11 @@ export class WebWorkerPlatformLocation extends PlatformLocation {
|
||||||
|
|
||||||
onHashChange(fn: LocationChangeListener): void { this._hashChangeListeners.push(fn); }
|
onHashChange(fn: LocationChangeListener): void { this._hashChangeListeners.push(fn); }
|
||||||
|
|
||||||
get pathname(): string { return this._location ? this._location.pathname ! : '<unknown>'; }
|
get hostname(): string { return this._location ? this._location.host ! : '<unknown>'; }
|
||||||
|
|
||||||
|
get port(): string { return this._location ? this._location.port ! : '<unknown>'; }
|
||||||
|
|
||||||
|
get protocol(): string { return this._location ? this._location.protocol ! : '<unknown>'; }
|
||||||
|
|
||||||
get search(): string { return this._location ? this._location.search : '<unknown>'; }
|
get search(): string { return this._location ? this._location.search : '<unknown>'; }
|
||||||
|
|
||||||
|
|
|
@ -377,7 +377,10 @@ export declare class PercentPipe implements PipeTransform {
|
||||||
|
|
||||||
export declare abstract class PlatformLocation {
|
export declare abstract class PlatformLocation {
|
||||||
abstract readonly hash: string;
|
abstract readonly hash: string;
|
||||||
|
abstract readonly hostname: string;
|
||||||
abstract readonly pathname: string;
|
abstract readonly pathname: string;
|
||||||
|
abstract readonly port: string;
|
||||||
|
abstract readonly protocol: string;
|
||||||
abstract readonly search: string;
|
abstract readonly search: string;
|
||||||
abstract back(): void;
|
abstract back(): void;
|
||||||
abstract forward(): void;
|
abstract forward(): void;
|
||||||
|
|
Loading…
Reference in New Issue