Skip to content

Commit

Permalink
feat(common): add APIs to read component pieces of URL (#30055)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jasonaden authored and benlesh committed Apr 24, 2019
1 parent b44b143 commit b635fe8
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 2 deletions.
3 changes: 3 additions & 0 deletions packages/common/src/location/platform_location.ts
Expand Up @@ -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;
Expand Down
Expand Up @@ -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; }
Expand Down
11 changes: 10 additions & 1 deletion packages/platform-server/src/location.ts
Expand Up @@ -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 || '',
Expand All @@ -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 = '';
Expand All @@ -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;
Expand Down
16 changes: 16 additions & 0 deletions packages/platform-server/test/integration_spec.ts
Expand Up @@ -516,6 +516,22 @@ class HiddenModule {
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', () => {
platformDynamicServer([{
provide: INITIAL_CONFIG,
Expand Down
Expand Up @@ -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 ! : '<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>'; }

Expand Down
3 changes: 3 additions & 0 deletions tools/public_api_guard/common/common.d.ts
Expand Up @@ -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;
Expand Down

0 comments on commit b635fe8

Please sign in to comment.