| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @license | 
					
						
							|  |  |  |  * Copyright Google Inc. All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Use of this source code is governed by an MIT-style license that can be | 
					
						
							|  |  |  |  * found in the LICENSE file at https://angular.io/license
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-19 19:41:12 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  | const xhr2: any = require('xhr2'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-19 19:41:12 -05:00
										 |  |  | import {Injectable, Injector, Provider} from '@angular/core'; | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-19 19:41:12 -05:00
										 |  |  | import {HttpEvent, HttpRequest, HttpHandler, HttpBackend, XhrFactory, ɵHttpInterceptingHandler as HttpInterceptingHandler} from '@angular/common/http'; | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-27 17:06:06 -05:00
										 |  |  | import {Observable, Observer, Subscription} from 'rxjs'; | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | @Injectable() | 
					
						
							| 
									
										
										
										
											2019-03-19 19:41:12 -05:00
										 |  |  | export class ServerXhr implements XhrFactory { | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  |   build(): XMLHttpRequest { return new xhr2.XMLHttpRequest(); } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  | export abstract class ZoneMacroTaskWrapper<S, R> { | 
					
						
							|  |  |  |   wrap(request: S): Observable<R> { | 
					
						
							|  |  |  |     return new Observable((observer: Observer<R>) => { | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:41 -07:00
										 |  |  |       let task: Task = null !; | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  |       let scheduled: boolean = false; | 
					
						
							| 
									
										
										
										
											2017-03-24 09:59:41 -07:00
										 |  |  |       let sub: Subscription|null = null; | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  |       let savedResult: any = null; | 
					
						
							|  |  |  |       let savedError: any = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const scheduleTask = (_task: Task) => { | 
					
						
							|  |  |  |         task = _task; | 
					
						
							|  |  |  |         scheduled = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |         const delegate = this.delegate(request); | 
					
						
							|  |  |  |         sub = delegate.subscribe( | 
					
						
							|  |  |  |             res => savedResult = res, | 
					
						
							|  |  |  |             err => { | 
					
						
							|  |  |  |               if (!scheduled) { | 
					
						
							|  |  |  |                 throw new Error( | 
					
						
							|  |  |  |                     'An http observable was completed twice. This shouldn\'t happen, please file a bug.'); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               savedError = err; | 
					
						
							|  |  |  |               scheduled = false; | 
					
						
							|  |  |  |               task.invoke(); | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |             () => { | 
					
						
							|  |  |  |               if (!scheduled) { | 
					
						
							|  |  |  |                 throw new Error( | 
					
						
							|  |  |  |                     'An http observable was completed twice. This shouldn\'t happen, please file a bug.'); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               scheduled = false; | 
					
						
							|  |  |  |               task.invoke(); | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const cancelTask = (_task: Task) => { | 
					
						
							|  |  |  |         if (!scheduled) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         scheduled = false; | 
					
						
							|  |  |  |         if (sub) { | 
					
						
							|  |  |  |           sub.unsubscribe(); | 
					
						
							|  |  |  |           sub = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const onComplete = () => { | 
					
						
							|  |  |  |         if (savedError !== null) { | 
					
						
							|  |  |  |           observer.error(savedError); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           observer.next(savedResult); | 
					
						
							|  |  |  |           observer.complete(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |       // MockBackend for Http is synchronous, which means that if scheduleTask is by
 | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  |       // scheduleMacroTask, the request will hit MockBackend and the response will be
 | 
					
						
							|  |  |  |       // sent, causing task.invoke() to be called.
 | 
					
						
							|  |  |  |       const _task = Zone.current.scheduleMacroTask( | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |           'ZoneMacroTaskWrapper.subscribe', onComplete, {}, () => null, cancelTask); | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  |       scheduleTask(_task); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return () => { | 
					
						
							|  |  |  |         if (scheduled && task) { | 
					
						
							|  |  |  |           task.zone.cancelTask(task); | 
					
						
							|  |  |  |           scheduled = false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (sub) { | 
					
						
							|  |  |  |           sub.unsubscribe(); | 
					
						
							|  |  |  |           sub = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |   protected abstract delegate(request: S): Observable<R>; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export class ZoneClientBackend extends | 
					
						
							| 
									
										
										
										
											2017-07-18 12:45:47 -07:00
										 |  |  |     ZoneMacroTaskWrapper<HttpRequest<any>, HttpEvent<any>> implements HttpBackend { | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |   constructor(private backend: HttpBackend) { super(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 12:45:47 -07:00
										 |  |  |   handle(request: HttpRequest<any>): Observable<HttpEvent<any>> { return this.wrap(request); } | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-18 12:45:47 -07:00
										 |  |  |   protected delegate(request: HttpRequest<any>): Observable<HttpEvent<any>> { | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |     return this.backend.handle(request); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-31 10:35:51 -07:00
										 |  |  | export function zoneWrappedInterceptingHandler(backend: HttpBackend, injector: Injector) { | 
					
						
							|  |  |  |   const realBackend: HttpBackend = new HttpInterceptingHandler(backend, injector); | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |   return new ZoneClientBackend(realBackend); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  | export const SERVER_HTTP_PROVIDERS: Provider[] = [ | 
					
						
							| 
									
										
										
										
											2017-07-18 12:45:47 -07:00
										 |  |  |   {provide: XhrFactory, useClass: ServerXhr}, { | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |     provide: HttpHandler, | 
					
						
							|  |  |  |     useFactory: zoneWrappedInterceptingHandler, | 
					
						
							| 
									
										
										
										
											2018-05-31 10:35:51 -07:00
										 |  |  |     deps: [HttpBackend, Injector] | 
					
						
							| 
									
										
										
										
											2017-03-22 17:13:24 -07:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-02-10 17:00:27 -08:00
										 |  |  | ]; |