fix(router): strip base href from URLs when navigating
This commit is contained in:
		
							parent
							
								
									84dc6ae76b
								
							
						
					
					
						commit
						853d1de6ec
					
				
							
								
								
									
										2
									
								
								modules/angular2/router.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								modules/angular2/router.js
									
									
									
									
										vendored
									
									
								
							| @ -13,6 +13,7 @@ export {RouteParams} from './src/router/instruction'; | ||||
| export * from './src/router/route_config_annotation'; | ||||
| export * from './src/router/route_config_decorator'; | ||||
| 
 | ||||
| import {BrowserLocation} from './src/router/browser_location'; | ||||
| import {Router, RootRouter} from './src/router/router'; | ||||
| import {RouteRegistry} from './src/router/route_registry'; | ||||
| import {Pipeline} from './src/router/pipeline'; | ||||
| @ -23,6 +24,7 @@ import {bind} from './di'; | ||||
| export var routerInjectables:List = [ | ||||
|   RouteRegistry, | ||||
|   Pipeline, | ||||
|   BrowserLocation, | ||||
|   Location, | ||||
|   bind(Router).toFactory((registry, pipeline, location, meta) => { | ||||
|     return new RootRouter(registry, pipeline, location, meta.type); | ||||
|  | ||||
							
								
								
									
										36
									
								
								modules/angular2/src/router/browser_location.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								modules/angular2/src/router/browser_location.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| 
 | ||||
| export class BrowserLocation { | ||||
|   _location; | ||||
|   _history; | ||||
|   _baseHref:string; | ||||
|   constructor() { | ||||
|     this._location = DOM.getLocation(); | ||||
|     this._history = DOM.getHistory(); | ||||
|     this._baseHref = DOM.getBaseHref(); | ||||
|   } | ||||
| 
 | ||||
|   onPopState(fn) { | ||||
|     DOM.getGlobalEventTarget('window').addEventListener('popstate', fn, false); | ||||
|   } | ||||
| 
 | ||||
|   getBaseHref() { | ||||
|     return this._baseHref; | ||||
|   } | ||||
| 
 | ||||
|   path() { | ||||
|     return this._location.pathname; | ||||
|   } | ||||
| 
 | ||||
|   pushState(state:any, title:string, url:string) { | ||||
|     this._history.pushState(state, title, url); | ||||
|   } | ||||
| 
 | ||||
|   forward() { | ||||
|     this._history.forward(); | ||||
|   } | ||||
| 
 | ||||
|   back() { | ||||
|     this._history.back(); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										47
									
								
								modules/angular2/src/router/location.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								modules/angular2/src/router/location.js
									
									
									
									
										vendored
									
									
								
							| @ -1,40 +1,63 @@ | ||||
| import {DOM} from 'angular2/src/dom/dom_adapter'; | ||||
| import {BrowserLocation} from './browser_location'; | ||||
| import {StringWrapper} from 'angular2/src/facade/lang'; | ||||
| import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async'; | ||||
| 
 | ||||
| export class Location { | ||||
|   _location; | ||||
|   _subject:EventEmitter; | ||||
|   _history; | ||||
|   constructor() { | ||||
|   _browserLocation:BrowserLocation; | ||||
|   _baseHref:string; | ||||
|   constructor(browserLocation:BrowserLocation) { | ||||
|     this._subject = new EventEmitter(); | ||||
|     this._location = DOM.getLocation(); | ||||
|     this._history = DOM.getHistory(); | ||||
|     DOM.getGlobalEventTarget('window').addEventListener('popstate', (_) => this._onPopState(_), false); | ||||
|     this._browserLocation = browserLocation; | ||||
|     this._baseHref = stripIndexHtml(this._browserLocation.getBaseHref()); | ||||
|     this._browserLocation.onPopState((_) => this._onPopState(_)); | ||||
|   } | ||||
| 
 | ||||
|   _onPopState(_) { | ||||
|     ObservableWrapper.callNext(this._subject, { | ||||
|       'url': this._location.pathname | ||||
|       'url': this.path() | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   path() { | ||||
|     return this._location.pathname; | ||||
|     return this.normalize(this._browserLocation.path()); | ||||
|   } | ||||
| 
 | ||||
|   normalize(url) { | ||||
|     return this._stripBaseHref(stripIndexHtml(url)); | ||||
|   } | ||||
| 
 | ||||
|   _stripBaseHref(url) { | ||||
|     if (this._baseHref.length > 0 && StringWrapper.startsWith(url, this._baseHref)) { | ||||
|       return StringWrapper.substring(url, this._baseHref.length); | ||||
|     } | ||||
|     return url; | ||||
|   } | ||||
| 
 | ||||
|   go(url:string) { | ||||
|     this._history.pushState(null, null, url); | ||||
|     url = this._stripBaseHref(url); | ||||
|     this._browserLocation.pushState(null, null, url); | ||||
|   } | ||||
| 
 | ||||
|   forward() { | ||||
|     this._history.forward(); | ||||
|     this._browserLocation.forward(); | ||||
|   } | ||||
| 
 | ||||
|   back() { | ||||
|     this._history.back() | ||||
|     this._browserLocation.back(); | ||||
|   } | ||||
| 
 | ||||
|   subscribe(onNext, onThrow = null, onReturn = null) { | ||||
|     ObservableWrapper.subscribe(this._subject, onNext, onThrow, onReturn); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| function stripIndexHtml(url) { | ||||
|   // '/index.html'.length == 11
 | ||||
|   if (url.length > 10 && StringWrapper.substring(url, url.length - 11) == '/index.html') { | ||||
|     return StringWrapper.substring(url, 0, url.length - 11); | ||||
|   } | ||||
|   return url; | ||||
| } | ||||
|  | ||||
							
								
								
									
										85
									
								
								modules/angular2/test/router/location_spec.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								modules/angular2/test/router/location_spec.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,85 @@ | ||||
| import { | ||||
|   AsyncTestCompleter, | ||||
|   describe, | ||||
|   proxy, | ||||
|   it, iit, | ||||
|   ddescribe, expect, | ||||
|   inject, beforeEach, beforeEachBindings, | ||||
|   SpyObject} from 'angular2/test_lib'; | ||||
| import {IMPLEMENTS} from 'angular2/src/facade/lang'; | ||||
| import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async'; | ||||
| 
 | ||||
| import {BrowserLocation} from 'angular2/src/router/browser_location'; | ||||
| import {Location} from 'angular2/src/router/location'; | ||||
| 
 | ||||
| export function main() { | ||||
| 
 | ||||
|   describe('Location', () => { | ||||
| 
 | ||||
|     var browserLocation, location; | ||||
| 
 | ||||
|     beforeEach(() => { | ||||
|       browserLocation = new DummyBrowserLocation(); | ||||
|       browserLocation.spy('pushState'); | ||||
|       browserLocation.baseHref = '/my/app'; | ||||
|       location = new Location(browserLocation); | ||||
|     }); | ||||
| 
 | ||||
|     it('should normalize urls on navigate', () => { | ||||
|       location.go('/my/app/user/btford'); | ||||
|       expect(browserLocation.spy('pushState')).toHaveBeenCalledWith(null, null, '/user/btford'); | ||||
|     }); | ||||
| 
 | ||||
|     it('should remove index.html from base href', () => { | ||||
|       browserLocation.baseHref = '/my/app/index.html'; | ||||
|       location = new Location(browserLocation); | ||||
|       location.go('/my/app/user/btford'); | ||||
|       expect(browserLocation.spy('pushState')).toHaveBeenCalledWith(null, null, '/user/btford'); | ||||
|     }); | ||||
| 
 | ||||
|     it('should normalize urls on popstate', inject([AsyncTestCompleter], (async) => { | ||||
|       browserLocation.simulatePopState('/my/app/user/btford'); | ||||
|       location.subscribe((ev) => { | ||||
|         expect(ev['url']).toEqual('/user/btford'); | ||||
|         async.done(); | ||||
|       }) | ||||
|     })); | ||||
| 
 | ||||
|     it('should normalize location path', () => { | ||||
|       browserLocation.internalPath = '/my/app/user/btford'; | ||||
|       expect(location.path()).toEqual('/user/btford'); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| @proxy | ||||
| @IMPLEMENTS(BrowserLocation) | ||||
| class DummyBrowserLocation extends SpyObject { | ||||
|   baseHref; | ||||
|   internalPath; | ||||
|   _subject:EventEmitter; | ||||
|   constructor() { | ||||
|     super(); | ||||
|     this.internalPath = '/'; | ||||
|     this._subject = new EventEmitter(); | ||||
|   } | ||||
| 
 | ||||
|   simulatePopState(url) { | ||||
|     this.internalPath = url; | ||||
|     ObservableWrapper.callNext(this._subject, null); | ||||
|   } | ||||
| 
 | ||||
|   path() { | ||||
|     return this.internalPath; | ||||
|   } | ||||
| 
 | ||||
|   onPopState(fn) { | ||||
|     ObservableWrapper.subscribe(this._subject, fn); | ||||
|   } | ||||
| 
 | ||||
|   getBaseHref() { | ||||
|     return this.baseHref; | ||||
|   } | ||||
| 
 | ||||
|   noSuchMethod(m){return super.noSuchMethod(m);} | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user