88import '@angular/compiler' ;
99
1010import { PlatformLocation , ɵgetDOM as getDOM } from '@angular/common' ;
11- import { Component , destroyPlatform } from '@angular/core' ;
11+ import { destroyPlatform } from '@angular/core' ;
1212import { INITIAL_CONFIG , platformServer } from '@angular/platform-server' ;
13- import { bootstrapApplication } from '@angular/platform-browser' ;
1413
1514( function ( ) {
1615 if ( getDOM ( ) . supportsDOMEvents ) return ; // NODE only
1716
1817 describe ( 'PlatformLocation' , ( ) => {
19- @Component ( {
20- selector : 'app' ,
21- template : `Works!` ,
22- } )
23- class LocationApp { }
24-
2518 beforeEach ( ( ) => {
2619 destroyPlatform ( ) ;
2720 } ) ;
@@ -34,15 +27,8 @@ import {bootstrapApplication} from '@angular/platform-browser';
3427 const platform = platformServer ( [
3528 { provide : INITIAL_CONFIG , useValue : { document : '<app></app>' } } ,
3629 ] ) ;
37- const appRef = await bootstrapApplication (
38- LocationApp ,
39- {
40- providers : [ { provide : INITIAL_CONFIG , useValue : { document : '<app></app>' } } ] ,
41- } ,
42- { platformRef : platform } ,
43- ) ;
4430
45- const location = appRef . injector . get ( PlatformLocation ) ;
31+ const location = platform . injector . get ( PlatformLocation ) ;
4632 expect ( location . pathname ) . toBe ( '/' ) ;
4733 platform . destroy ( ) ;
4834 } ) ;
@@ -57,23 +43,7 @@ import {bootstrapApplication} from '@angular/platform-browser';
5743 } ,
5844 ] ) ;
5945
60- const appRef = await bootstrapApplication (
61- LocationApp ,
62- {
63- providers : [
64- {
65- provide : INITIAL_CONFIG ,
66- useValue : {
67- document : '<app></app>' ,
68- url : 'http://test.com/deep/path?query#hash' ,
69- } ,
70- } ,
71- ] ,
72- } ,
73- { platformRef : platform } ,
74- ) ;
75-
76- const location = appRef . injector . get ( PlatformLocation ) ;
46+ const location = platform . injector . get ( PlatformLocation ) ;
7747 expect ( location . pathname ) . toBe ( '/deep/path' ) ;
7848 expect ( location . search ) . toBe ( '?query' ) ;
7949 expect ( location . hash ) . toBe ( '#hash' ) ;
@@ -90,23 +60,7 @@ import {bootstrapApplication} from '@angular/platform-browser';
9060 } ,
9161 ] ) ;
9262
93- const appRef = await bootstrapApplication (
94- LocationApp ,
95- {
96- providers : [
97- {
98- provide : INITIAL_CONFIG ,
99- useValue : {
100- document : '<app></app>' ,
101- url : 'http://test.com:80/deep/path?query#hash' ,
102- } ,
103- } ,
104- ] ,
105- } ,
106- { platformRef : platform } ,
107- ) ;
108-
109- const location = appRef . injector . get ( PlatformLocation ) ;
63+ const location = platform . injector . get ( PlatformLocation ) ;
11064 expect ( location . hostname ) . toBe ( 'test.com' ) ;
11165 expect ( location . protocol ) . toBe ( 'http:' ) ;
11266 expect ( location . port ) . toBe ( '' ) ;
@@ -126,23 +80,7 @@ import {bootstrapApplication} from '@angular/platform-browser';
12680 } ,
12781 ] ) ;
12882
129- const appRef = await bootstrapApplication (
130- LocationApp ,
131- {
132- providers : [
133- {
134- provide : INITIAL_CONFIG ,
135- useValue : {
136- document : '<app></app>' ,
137- url : 'http://test.com/deep/path' ,
138- } ,
139- } ,
140- ] ,
141- } ,
142- { platformRef : platform } ,
143- ) ;
144-
145- const location = appRef . injector . get ( PlatformLocation ) ;
83+ const location = platform . injector . get ( PlatformLocation ) ;
14684 expect ( location . pathname ) . toBe ( '/deep/path' ) ;
14785 expect ( location . search ) . toBe ( '' ) ;
14886 expect ( location . hash ) . toBe ( '' ) ;
@@ -153,14 +91,7 @@ import {bootstrapApplication} from '@angular/platform-browser';
15391 { provide : INITIAL_CONFIG , useValue : { document : '<app></app>' } } ,
15492 ] ) ;
15593
156- const appRef = await bootstrapApplication (
157- LocationApp ,
158- {
159- providers : [ { provide : INITIAL_CONFIG , useValue : { document : '<app></app>' } } ] ,
160- } ,
161- { platformRef : platform } ,
162- ) ;
163- const location = appRef . injector . get ( PlatformLocation ) ;
94+ const location = platform . injector . get ( PlatformLocation ) ;
16495 location . pushState ( null , 'Test' , '/foo#bar' ) ;
16596 expect ( location . pathname ) . toBe ( '/foo' ) ;
16697 expect ( location . hash ) . toBe ( '#bar' ) ;
@@ -178,22 +109,7 @@ import {bootstrapApplication} from '@angular/platform-browser';
178109 } ,
179110 ] ) ;
180111
181- const appRef = await bootstrapApplication (
182- LocationApp ,
183- {
184- providers : [
185- {
186- provide : INITIAL_CONFIG ,
187- useValue : {
188- document : '<app></app>' ,
189- url : 'http://test.com/deep/path?query#hash' ,
190- } ,
191- } ,
192- ] ,
193- } ,
194- { platformRef : platform } ,
195- ) ;
196- const location = appRef . injector . get ( PlatformLocation ) ;
112+ const location = platform . injector . get ( PlatformLocation ) ;
197113 location . replaceState ( null , 'Test' , '/foo#bar' ) ;
198114 expect ( location . pathname ) . toBe ( '/foo' ) ;
199115 expect ( location . hash ) . toBe ( '#bar' ) ;
@@ -206,24 +122,42 @@ import {bootstrapApplication} from '@angular/platform-browser';
206122 const platform = platformServer ( [
207123 { provide : INITIAL_CONFIG , useValue : { document : '<app></app>' } } ,
208124 ] ) ;
209- bootstrapApplication (
210- LocationApp ,
211- {
212- providers : [ { provide : INITIAL_CONFIG , useValue : { document : '<app></app>' } } ] ,
213- } ,
214- { platformRef : platform } ,
215- ) . then ( ( appRef ) => {
216- const location : PlatformLocation = appRef . injector . get ( PlatformLocation ) ;
217- expect ( location . pathname ) . toBe ( '/' ) ;
218- location . onHashChange ( ( e : any ) => {
219- expect ( e . type ) . toBe ( 'hashchange' ) ;
220- expect ( e . oldUrl ) . toBe ( '/' ) ;
221- expect ( e . newUrl ) . toBe ( '/foo#bar' ) ;
222- platform . destroy ( ) ;
223- done ( ) ;
224- } ) ;
225- location . pushState ( null , 'Test' , '/foo#bar' ) ;
125+ const location = platform . injector . get ( PlatformLocation ) ;
126+
127+ expect ( location . pathname ) . toBe ( '/' ) ;
128+ location . onHashChange ( ( e : any ) => {
129+ expect ( e . type ) . toBe ( 'hashchange' ) ;
130+ expect ( e . oldUrl ) . toBe ( '/' ) ;
131+ expect ( e . newUrl ) . toBe ( '/foo#bar' ) ;
132+ platform . destroy ( ) ;
133+ done ( ) ;
226134 } ) ;
135+ location . pushState ( null , 'Test' , '/foo#bar' ) ;
136+ } ) ;
137+
138+ it ( 'neutralizes hostname hijack attempts' , async ( ) => {
139+ const urls = [ '/\\attacker.com/deep/path' , '//attacker.com/deep/path' ] ;
140+
141+ for ( const url of urls ) {
142+ const platform = platformServer ( [
143+ {
144+ provide : INITIAL_CONFIG ,
145+ useValue : {
146+ document : '' ,
147+ // This should be treated as relative URL.
148+ // Example: `req.url: '//attacker.com/deep/path'` where request
149+ // to express server is 'http://localhost:4200//attacker.com/deep/path'.
150+ url,
151+ } ,
152+ } ,
153+ ] ) ;
154+
155+ const location = platform . injector . get ( PlatformLocation ) ;
156+ platform . destroy ( ) ;
157+
158+ expect ( location . hostname ) . withContext ( `hostname for URL: "${ url } "` ) . toBe ( '' ) ;
159+ expect ( location . pathname ) . withContext ( `pathname for URL: "${ url } "` ) . toBe ( url ) ;
160+ }
227161 } ) ;
228162 } ) ;
229163} ) ( ) ;
0 commit comments