From b635fe80cc38177c8e405f56bf289924096893a1 Mon Sep 17 00:00:00 2001 From: Jason Aden Date: Mon, 11 Feb 2019 10:56:50 -0800 Subject: [PATCH] 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 --- .../common/src/location/platform_location.ts | 3 +++ .../location/browser_platform_location.ts | 3 +++ packages/platform-server/src/location.ts | 11 ++++++++++- .../platform-server/test/integration_spec.ts | 16 ++++++++++++++++ .../src/web_workers/worker/platform_location.ts | 6 +++++- tools/public_api_guard/common/common.d.ts | 3 +++ 6 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/common/src/location/platform_location.ts b/packages/common/src/location/platform_location.ts index 01acc29951..0b0472dfb6 100644 --- a/packages/common/src/location/platform_location.ts +++ b/packages/common/src/location/platform_location.ts @@ -35,6 +35,9 @@ export abstract class PlatformLocation { abstract onPopState(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 search(): string; abstract get hash(): string; diff --git a/packages/platform-browser/src/browser/location/browser_platform_location.ts b/packages/platform-browser/src/browser/location/browser_platform_location.ts index 55e1a72895..82e7a69b90 100644 --- a/packages/platform-browser/src/browser/location/browser_platform_location.ts +++ b/packages/platform-browser/src/browser/location/browser_platform_location.ts @@ -49,6 +49,9 @@ export class BrowserPlatformLocation extends PlatformLocation { 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 search(): string { return this.location.search; } get hash(): string { return this.location.hash; } diff --git a/packages/platform-server/src/location.ts b/packages/platform-server/src/location.ts index 7b39a07368..98525a7f98 100644 --- a/packages/platform-server/src/location.ts +++ b/packages/platform-server/src/location.ts @@ -14,9 +14,12 @@ import * as url from 'url'; 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); return { + hostname: parsedUrl.hostname || '', + protocol: parsedUrl.protocol || '', + port: parsedUrl.port || '', pathname: parsedUrl.pathname || '', search: parsedUrl.search || '', hash: parsedUrl.hash || '', @@ -29,6 +32,9 @@ function parseUrl(urlStr: string): {pathname: string, search: string, hash: stri */ @Injectable() export class ServerPlatformLocation implements PlatformLocation { + public readonly hostname: string = '/'; + public readonly protocol: string = '/'; + public readonly port: string = '/'; public readonly pathname: string = '/'; public readonly search: string = ''; public readonly hash: string = ''; @@ -39,6 +45,9 @@ export class ServerPlatformLocation implements PlatformLocation { const config = _config as PlatformConfig | null; if (!!config && !!config.url) { const parsedUrl = parseUrl(config.url); + this.hostname = parsedUrl.hostname; + this.protocol = parsedUrl.protocol; + this.port = parsedUrl.port; this.pathname = parsedUrl.pathname; this.search = parsedUrl.search; this.hash = parsedUrl.hash; diff --git a/packages/platform-server/test/integration_spec.ts b/packages/platform-server/test/integration_spec.ts index 59f4b4fb0f..56f46a609a 100644 --- a/packages/platform-server/test/integration_spec.ts +++ b/packages/platform-server/test/integration_spec.ts @@ -516,6 +516,22 @@ class HiddenModule { expect(location.hash).toBe('#hash'); }); }); + it('parses component pieces of a URL', () => { + platformDynamicServer([{ + provide: INITIAL_CONFIG, + useValue: {document: '', 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', () => { platformDynamicServer([{ provide: INITIAL_CONFIG, diff --git a/packages/platform-webworker/src/web_workers/worker/platform_location.ts b/packages/platform-webworker/src/web_workers/worker/platform_location.ts index 5592497d6c..d63085a673 100644 --- a/packages/platform-webworker/src/web_workers/worker/platform_location.ts +++ b/packages/platform-webworker/src/web_workers/worker/platform_location.ts @@ -74,7 +74,11 @@ export class WebWorkerPlatformLocation extends PlatformLocation { onHashChange(fn: LocationChangeListener): void { this._hashChangeListeners.push(fn); } - get pathname(): string { return this._location ? this._location.pathname ! : ''; } + get hostname(): string { return this._location ? this._location.host ! : ''; } + + get port(): string { return this._location ? this._location.port ! : ''; } + + get protocol(): string { return this._location ? this._location.protocol ! : ''; } get search(): string { return this._location ? this._location.search : ''; } diff --git a/tools/public_api_guard/common/common.d.ts b/tools/public_api_guard/common/common.d.ts index 8a74b36296..e21a375cff 100644 --- a/tools/public_api_guard/common/common.d.ts +++ b/tools/public_api_guard/common/common.d.ts @@ -377,7 +377,10 @@ export declare class PercentPipe implements PipeTransform { export declare abstract class PlatformLocation { abstract readonly hash: string; + abstract readonly hostname: string; abstract readonly pathname: string; + abstract readonly port: string; + abstract readonly protocol: string; abstract readonly search: string; abstract back(): void; abstract forward(): void;