{"version":3,"file":"common-http.umd.js","sources":["../../../../packages/common/http/src/module.ts","../../../../packages/common/http/src/xsrf.ts","../../../../packages/common/http/src/xhr.ts","../../../../packages/common/http/src/jsonp.ts","../../../../packages/common/http/src/interceptor.ts","../../../../packages/common/http/src/client.ts","../../../../packages/common/http/src/response.ts","../../../../packages/common/http/src/request.ts","../../../../packages/common/http/src/headers.ts","../../../../packages/common/http/src/params.ts","../../../../packages/common/http/src/backend.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {Inject, ModuleWithProviders, NgModule, Optional} from '@angular/core';\n\nimport {HttpBackend, HttpHandler} from './backend';\nimport {HttpClient} from './client';\nimport {HTTP_INTERCEPTORS, HttpInterceptor, HttpInterceptorHandler, NoopInterceptor} from './interceptor';\nimport {JsonpCallbackContext, JsonpClientBackend, JsonpInterceptor} from './jsonp';\nimport {BrowserXhr, HttpXhrBackend, XhrFactory} from './xhr';\nimport {HttpXsrfCookieExtractor, HttpXsrfInterceptor, HttpXsrfTokenExtractor, XSRF_COOKIE_NAME, XSRF_HEADER_NAME} from './xsrf';\n/**\n * Constructs an `HttpHandler` that applies a bunch of `HttpInterceptor`s\n * to a request before passing it to the given `HttpBackend`.\n * \n * Meant to be used as a factory function within `HttpClientModule`.\n * \n * \\@experimental\n * @param {?} backend\n * @param {?=} interceptors\n * @return {?}\n */\nexport function interceptingHandler(\n backend: HttpBackend, interceptors: HttpInterceptor[] | null = []): HttpHandler {\n if (!interceptors) {\n return backend;\n }\n return interceptors.reduceRight(\n (next, interceptor) => new HttpInterceptorHandler(next, interceptor), backend);\n}\n/**\n * Factory function that determines where to store JSONP callbacks.\n * \n * Ordinarily JSONP callbacks are stored on the `window` object, but this may not exist\n * in test environments. In that case, callbacks are stored on an anonymous object instead.\n * \n * \\@experimental\n * @return {?}\n */\nexport function jsonpCallbackContext(): Object {\n if (typeof window === 'object') {\n return window;\n }\n return {};\n}\n/**\n * `NgModule` which adds XSRF protection support to outgoing requests.\n * \n * Provided the server supports a cookie-based XSRF protection system, this\n * module can be used directly to configure XSRF protection with the correct\n * cookie and header names.\n * \n * If no such names are provided, the default is to use `X-XSRF-TOKEN` for\n * the header name and `XSRF-TOKEN` for the cookie name.\n * \n * \\@experimental\n */\nexport class HttpClientXsrfModule {\n/**\n * Disable the default XSRF protection.\n * @return {?}\n */\nstatic disable(): ModuleWithProviders {\n return {\n ngModule: HttpClientXsrfModule,\n providers: [\n {provide: HttpXsrfInterceptor, useClass: NoopInterceptor},\n ],\n };\n }\n/**\n * Configure XSRF protection to use the given cookie name or header name,\n * or the default names (as described above) if not provided.\n * @param {?=} options\n * @return {?}\n */\nstatic withOptions(options: {\n cookieName?: string,\n headerName?: string,\n } = {}): ModuleWithProviders {\n return {\n ngModule: HttpClientXsrfModule,\n providers: [\n options.cookieName ? {provide: XSRF_COOKIE_NAME, useValue: options.cookieName} : [],\n options.headerName ? {provide: XSRF_HEADER_NAME, useValue: options.headerName} : [],\n ],\n };\n }\nstatic decorators: DecoratorInvocation[] = [\n{ type: NgModule, args: [{\n providers: [\n HttpXsrfInterceptor,\n {provide: HTTP_INTERCEPTORS, useExisting: HttpXsrfInterceptor, multi: true},\n {provide: HttpXsrfTokenExtractor, useClass: HttpXsrfCookieExtractor},\n {provide: XSRF_COOKIE_NAME, useValue: 'XSRF-TOKEN'},\n {provide: XSRF_HEADER_NAME, useValue: 'X-XSRF-TOKEN'},\n ],\n}, ] },\n];\n/**\n * @nocollapse\n */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n];\n}\n\nfunction HttpClientXsrfModule_tsickle_Closure_declarations() {\n/** @type {?} */\nHttpClientXsrfModule.decorators;\n/**\n * @nocollapse\n * @type {?}\n */\nHttpClientXsrfModule.ctorParameters;\n}\n\n/**\n * `NgModule` which provides the `HttpClient` and associated services.\n * \n * Interceptors can be added to the chain behind `HttpClient` by binding them\n * to the multiprovider for `HTTP_INTERCEPTORS`.\n * \n * \\@experimental\n */\nexport class HttpClientModule {\nstatic decorators: DecoratorInvocation[] = [\n{ type: NgModule, args: [{\n imports: [\n HttpClientXsrfModule.withOptions({\n cookieName: 'XSRF-TOKEN',\n headerName: 'X-XSRF-TOKEN',\n }),\n ],\n providers: [\n HttpClient,\n // HttpHandler is the backend + interceptors and is constructed\n // using the interceptingHandler factory function.\n {\n provide: HttpHandler,\n useFactory: interceptingHandler,\n deps: [HttpBackend, [new Optional(), new Inject(HTTP_INTERCEPTORS)]],\n },\n HttpXhrBackend,\n {provide: HttpBackend, useExisting: HttpXhrBackend},\n BrowserXhr,\n {provide: XhrFactory, useExisting: BrowserXhr},\n ],\n}, ] },\n];\n/**\n * @nocollapse\n */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n];\n}\n\nfunction HttpClientModule_tsickle_Closure_declarations() {\n/** @type {?} */\nHttpClientModule.decorators;\n/**\n * @nocollapse\n * @type {?}\n */\nHttpClientModule.ctorParameters;\n}\n\n/**\n * `NgModule` which enables JSONP support in `HttpClient`.\n * \n * Without this module, Jsonp requests will reach the backend\n * with method JSONP, where they'll be rejected.\n * \n * \\@experimental\n */\nexport class HttpClientJsonpModule {\nstatic decorators: DecoratorInvocation[] = [\n{ type: NgModule, args: [{\n providers: [\n JsonpClientBackend,\n {provide: JsonpCallbackContext, useFactory: jsonpCallbackContext},\n {provide: HTTP_INTERCEPTORS, useClass: JsonpInterceptor, multi: true},\n ],\n}, ] },\n];\n/**\n * @nocollapse\n */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n];\n}\n\nfunction HttpClientJsonpModule_tsickle_Closure_declarations() {\n/** @type {?} */\nHttpClientJsonpModule.decorators;\n/**\n * @nocollapse\n * @type {?}\n */\nHttpClientJsonpModule.ctorParameters;\n}\n\n\ninterface DecoratorInvocation {\n type: Function;\n args?: any[];\n}\n","/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {DOCUMENT, ɵparseCookieValue as parseCookieValue} from '@angular/common';\nimport {Inject, Injectable, InjectionToken, PLATFORM_ID} from '@angular/core';\nimport {Observable} from 'rxjs/Observable';\n\nimport {HttpHandler} from './backend';\nimport {HttpInterceptor} from './interceptor';\nimport {HttpRequest} from './request';\nimport {HttpEvent} from './response';\n\nexport const /** @type {?} */ XSRF_COOKIE_NAME = new InjectionToken('XSRF_COOKIE_NAME');\nexport const /** @type {?} */ XSRF_HEADER_NAME = new InjectionToken('XSRF_HEADER_NAME');\n/**\n * Retrieves the current XSRF token to use with the next outgoing request.\n * \n * \\@experimental\n * @abstract\n */\nexport abstract class HttpXsrfTokenExtractor {\n/**\n * Get the XSRF token to use with an outgoing request.\n * \n * Will be called for every request, so the token may change between requests.\n * @abstract\n * @return {?}\n */\ngetToken() {}\n}\n/**\n * `HttpXsrfTokenExtractor` which retrieves the token from a cookie.\n */\nexport class HttpXsrfCookieExtractor implements HttpXsrfTokenExtractor {\nprivate lastCookieString: string = '';\nprivate lastToken: string|null = null;\n/**\n * \\@internal for testing\n */\nparseCount: number = 0;\n/**\n * @param {?} doc\n * @param {?} platform\n * @param {?} cookieName\n */\nconstructor(\nprivate doc: any,\nprivate platform: string,\nprivate cookieName: string) {}\n/**\n * @return {?}\n */\ngetToken(): string|null {\n if (this.platform === 'server') {\n return null;\n }\n const /** @type {?} */ cookieString = this.doc.cookie || '';\n if (cookieString !== this.lastCookieString) {\n this.parseCount++;\n this.lastToken = parseCookieValue(cookieString, this.cookieName);\n this.lastCookieString = cookieString;\n }\n return this.lastToken;\n }\nstatic decorators: DecoratorInvocation[] = [\n{ type: Injectable },\n];\n/**\n * @nocollapse\n */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n{type: undefined, decorators: [{ type: Inject, args: [DOCUMENT, ] }, ]},\n{type: undefined, decorators: [{ type: Inject, args: [PLATFORM_ID, ] }, ]},\n{type: undefined, decorators: [{ type: Inject, args: [XSRF_COOKIE_NAME, ] }, ]},\n];\n}\n\nfunction HttpXsrfCookieExtractor_tsickle_Closure_declarations() {\n/** @type {?} */\nHttpXsrfCookieExtractor.decorators;\n/**\n * @nocollapse\n * @type {?}\n */\nHttpXsrfCookieExtractor.ctorParameters;\n/** @type {?} */\nHttpXsrfCookieExtractor.prototype.lastCookieString;\n/** @type {?} */\nHttpXsrfCookieExtractor.prototype.lastToken;\n/**\n * \\@internal for testing\n * @type {?}\n */\nHttpXsrfCookieExtractor.prototype.parseCount;\n/** @type {?} */\nHttpXsrfCookieExtractor.prototype.doc;\n/** @type {?} */\nHttpXsrfCookieExtractor.prototype.platform;\n/** @type {?} */\nHttpXsrfCookieExtractor.prototype.cookieName;\n}\n\n/**\n * `HttpInterceptor` which adds an XSRF token to eligible outgoing requests.\n */\nexport class HttpXsrfInterceptor implements HttpInterceptor {\n/**\n * @param {?} tokenService\n * @param {?} headerName\n */\nconstructor(\nprivate tokenService: HttpXsrfTokenExtractor,\nprivate headerName: string) {}\n/**\n * @param {?} req\n * @param {?} next\n * @return {?}\n */\nintercept(req: HttpRequest, next: HttpHandler): Observable> {\n const /** @type {?} */ lcUrl = req.url.toLowerCase();\n // Skip both non-mutating requests and absolute URLs.\n // Non-mutating requests don't require a token, and absolute URLs require special handling\n // anyway as the cookie set\n // on our origin is not the same as the token expected by another origin.\n if (req.method === 'GET' || req.method === 'HEAD' || lcUrl.startsWith('http://') ||\n lcUrl.startsWith('https://')) {\n return next.handle(req);\n }\n const /** @type {?} */ token = this.tokenService.getToken();\n\n // Be careful not to overwrite an existing header of the same name.\n if (token !== null && !req.headers.has(this.headerName)) {\n req = req.clone({headers: req.headers.set(this.headerName, token)});\n }\n return next.handle(req);\n }\nstatic decorators: DecoratorInvocation[] = [\n{ type: Injectable },\n];\n/**\n * @nocollapse\n */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n{type: HttpXsrfTokenExtractor, },\n{type: undefined, decorators: [{ type: Inject, args: [XSRF_HEADER_NAME, ] }, ]},\n];\n}\n\nfunction HttpXsrfInterceptor_tsickle_Closure_declarations() {\n/** @type {?} */\nHttpXsrfInterceptor.decorators;\n/**\n * @nocollapse\n * @type {?}\n */\nHttpXsrfInterceptor.ctorParameters;\n/** @type {?} */\nHttpXsrfInterceptor.prototype.tokenService;\n/** @type {?} */\nHttpXsrfInterceptor.prototype.headerName;\n}\n\n\ninterface DecoratorInvocation {\n type: Function;\n args?: any[];\n}\n","/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {Injectable} from '@angular/core';\nimport {Observable} from 'rxjs/Observable';\nimport {Observer} from 'rxjs/Observer';\n\nimport {HttpBackend} from './backend';\nimport {HttpHeaders} from './headers';\nimport {HttpRequest} from './request';\nimport {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpJsonParseError, HttpResponse, HttpUploadProgressEvent} from './response';\n\nconst /** @type {?} */ XSSI_PREFIX = /^\\)\\]\\}',?\\n/;\n/**\n * Determine an appropriate URL for the response, by checking either\n * XMLHttpRequest.responseURL or the X-Request-URL header.\n * @param {?} xhr\n * @return {?}\n */\nfunction getResponseUrl(xhr: any): string|null {\n if ('responseURL' in xhr && xhr.responseURL) {\n return xhr.responseURL;\n }\n if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {\n return xhr.getResponseHeader('X-Request-URL');\n }\n return null;\n}\n/**\n * A wrapper around the `XMLHttpRequest` constructor.\n * \n * \\@experimental\n * @abstract\n */\nexport abstract class XhrFactory {\n/**\n * @abstract\n * @return {?}\n */\nbuild() {} }\n/**\n * A factory for \\@{link HttpXhrBackend} that uses the `XMLHttpRequest` browser API.\n * \n * \\@experimental\n */\nexport class BrowserXhr implements XhrFactory {\nconstructor() {}\n/**\n * @return {?}\n */\nbuild(): any { return /** @type {?} */(( (new XMLHttpRequest()))); }\nstatic decorators: DecoratorInvocation[] = [\n{ type: Injectable },\n];\n/**\n * @nocollapse\n */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n];\n}\n\nfunction BrowserXhr_tsickle_Closure_declarations() {\n/** @type {?} */\nBrowserXhr.decorators;\n/**\n * @nocollapse\n * @type {?}\n */\nBrowserXhr.ctorParameters;\n}\n\n\n/**\n * Tracks a response from the server that does not yet have a body.\n */\ninterface PartialResponse {\n headers: HttpHeaders;\n status: number;\n statusText: string;\n url: string;\n}\n/**\n * An `HttpBackend` which uses the XMLHttpRequest API to send\n * requests to a backend server.\n * \n * \\@experimental\n */\nexport class HttpXhrBackend implements HttpBackend {\n/**\n * @param {?} xhrFactory\n */\nconstructor(private xhrFactory: XhrFactory) {}\n/**\n * Process a request and return a stream of response events.\n * @param {?} req\n * @return {?}\n */\nhandle(req: HttpRequest): Observable> {\n // Quick check to give a better error message when a user attempts to use\n // HttpClient.jsonp() without installing the JsonpClientModule\n if (req.method === 'JSONP') {\n throw new Error(`Attempted to construct Jsonp request without JsonpClientModule installed.`);\n }\n\n // Everything happens on Observable subscription.\n return new Observable((observer: Observer>) => {\n // Start by setting up the XHR object with request method, URL, and withCredentials flag.\n const /** @type {?} */ xhr = this.xhrFactory.build();\n xhr.open(req.method, req.urlWithParams);\n if (!!req.withCredentials) {\n xhr.withCredentials = true;\n }\n\n // Add all the requested headers.\n req.headers.forEach((name, values) => xhr.setRequestHeader(name, values.join(',')));\n\n // Add an Accept header if one isn't present already.\n if (!req.headers.has('Accept')) {\n xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');\n }\n\n // Auto-detect the Content-Type header if one isn't present already.\n if (!req.headers.has('Content-Type')) {\n const /** @type {?} */ detectedType = req.detectContentTypeHeader();\n // Sometimes Content-Type detection fails.\n if (detectedType !== null) {\n xhr.setRequestHeader('Content-Type', detectedType);\n }\n }\n\n // Set the responseType if one was requested.\n if (req.responseType) {\n const /** @type {?} */ responseType = req.responseType.toLowerCase();\n\n // JSON responses need to be processed as text. This is because if the server\n // returns an XSSI-prefixed JSON response, the browser will fail to parse it,\n // xhr.response will be null, and xhr.responseText cannot be accessed to\n // retrieve the prefixed JSON data in order to strip the prefix. Thus, all JSON\n // is parsed by first requesting text and then applying JSON.parse.\n xhr.responseType = /** @type {?} */(( ((responseType !== 'json') ? responseType : 'text') as any));\n }\n\n // Serialize the request body if one is present. If not, this will be set to null.\n const /** @type {?} */ reqBody = req.serializeBody();\n\n // If progress events are enabled, response headers will be delivered\n // in two events - the HttpHeaderResponse event and the full HttpResponse\n // event. However, since response headers don't change in between these\n // two events, it doesn't make sense to parse them twice. So headerResponse\n // caches the data extracted from the response whenever it's first parsed,\n // to ensure parsing isn't duplicated.\n let /** @type {?} */ headerResponse: HttpHeaderResponse|null = null;\n\n // partialFromXhr extracts the HttpHeaderResponse from the current XMLHttpRequest\n // state, and memoizes it into headerResponse.\n const /** @type {?} */ partialFromXhr = (): HttpHeaderResponse => {\n if (headerResponse !== null) {\n return headerResponse;\n }\n\n // Read status and normalize an IE9 bug (http://bugs.jquery.com/ticket/1450).\n const /** @type {?} */ status: number = xhr.status === 1223 ? 204 : xhr.status;\n const /** @type {?} */ statusText = xhr.statusText || 'OK';\n\n // Parse headers from XMLHttpRequest - this step is lazy.\n const /** @type {?} */ headers = new HttpHeaders(xhr.getAllResponseHeaders());\n\n // Read the response URL from the XMLHttpResponse instance and fall back on the\n // request URL.\n const /** @type {?} */ url = getResponseUrl(xhr) || req.url;\n\n // Construct the HttpHeaderResponse and memoize it.\n headerResponse = new HttpHeaderResponse({headers, status, statusText, url});\n return headerResponse;\n };\n\n // Next, a few closures are defined for the various events which XMLHttpRequest can\n // emit. This allows them to be unregistered as event listeners later.\n\n // First up is the load event, which represents a response being fully available.\n const /** @type {?} */ onLoad = () => {\n // Read response state from the memoized partial data.\n let {headers, status, statusText, url} = partialFromXhr();\n\n // The body will be read out if present.\n let /** @type {?} */ body: any|null = null;\n\n if (status !== 204) {\n // Use XMLHttpRequest.response if set, responseText otherwise.\n body = (typeof xhr.response === 'undefined') ? xhr.responseText : xhr.response;\n }\n\n // Normalize another potential bug (this one comes from CORS).\n if (status === 0) {\n status = !!body ? 200 : 0;\n }\n\n // ok determines whether the response will be transmitted on the event or\n // error channel. Unsuccessful status codes (not 2xx) will always be errors,\n // but a successful status code can still result in an error if the user\n // asked for JSON data and the body cannot be parsed as such.\n let /** @type {?} */ ok = status >= 200 && status < 300;\n\n // Check whether the body needs to be parsed as JSON (in many cases the browser\n // will have done that already).\n if (ok && req.responseType === 'json' && typeof body === 'string') {\n // Attempt the parse. If it fails, a parse error should be delivered to the user.\n body = body.replace(XSSI_PREFIX, '');\n try {\n body = JSON.parse(body);\n } catch ( /** @type {?} */error) {\n // Even though the response status was 2xx, this is still an error.\n ok = false;\n // The parse error contains the text of the body that failed to parse.\n body = /** @type {?} */(( { error, text: body } as HttpJsonParseError));\n }\n } else if (!ok && req.responseType === 'json' && typeof body === 'string') {\n try {\n // Attempt to parse the body as JSON.\n body = JSON.parse(body);\n } catch ( /** @type {?} */error) {\n // Cannot be certain that the body was meant to be parsed as JSON.\n // Leave the body as a string.\n }\n }\n\n if (ok) {\n // A successful response is delivered on the event stream.\n observer.next(new HttpResponse({\n body,\n headers,\n status,\n statusText,\n url: url || undefined,\n }));\n // The full body has been received and delivered, no further events\n // are possible. This request is complete.\n observer.complete();\n } else {\n // An unsuccessful request is delivered on the error channel.\n observer.error(new HttpErrorResponse({\n // The error in this case is the response body (error from the server).\n error: body,\n headers,\n status,\n statusText,\n url: url || undefined,\n }));\n }\n };\n\n // The onError callback is called when something goes wrong at the network level.\n // Connection timeout, DNS error, offline, etc. These are actual errors, and are\n // transmitted on the error channel.\n const /** @type {?} */ onError = (error: ErrorEvent) => {\n const /** @type {?} */ res = new HttpErrorResponse({\n error,\n status: xhr.status || 0,\n statusText: xhr.statusText || 'Unknown Error',\n });\n observer.error(res);\n };\n\n // The sentHeaders flag tracks whether the HttpResponseHeaders event\n // has been sent on the stream. This is necessary to track if progress\n // is enabled since the event will be sent on only the first download\n // progerss event.\n let /** @type {?} */ sentHeaders = false;\n\n // The download progress event handler, which is only registered if\n // progress events are enabled.\n const /** @type {?} */ onDownProgress = (event: ProgressEvent) => {\n // Send the HttpResponseHeaders event if it hasn't been sent already.\n if (!sentHeaders) {\n observer.next(partialFromXhr());\n sentHeaders = true;\n }\n\n // Start building the download progress event to deliver on the response\n // event stream.\n let /** @type {?} */ progressEvent: HttpDownloadProgressEvent = {\n type: HttpEventType.DownloadProgress,\n loaded: event.loaded,\n };\n\n // Set the total number of bytes in the event if it's available.\n if (event.lengthComputable) {\n progressEvent.total = event.total;\n }\n\n // If the request was for text content and a partial response is\n // available on XMLHttpRequest, include it in the progress event\n // to allow for streaming reads.\n if (req.responseType === 'text' && !!xhr.responseText) {\n progressEvent.partialText = xhr.responseText;\n }\n\n // Finally, fire the event.\n observer.next(progressEvent);\n };\n\n // The upload progress event handler, which is only registered if\n // progress events are enabled.\n const /** @type {?} */ onUpProgress = (event: ProgressEvent) => {\n // Upload progress events are simpler. Begin building the progress\n // event.\n let /** @type {?} */ progress: HttpUploadProgressEvent = {\n type: HttpEventType.UploadProgress,\n loaded: event.loaded,\n };\n\n // If the total number of bytes being uploaded is available, include\n // it.\n if (event.lengthComputable) {\n progress.total = event.total;\n }\n\n // Send the event.\n observer.next(progress);\n };\n\n // By default, register for load and error events.\n xhr.addEventListener('load', onLoad);\n xhr.addEventListener('error', onError);\n\n // Progress events are only enabled if requested.\n if (req.reportProgress) {\n // Download progress is always enabled if requested.\n xhr.addEventListener('progress', onDownProgress);\n\n // Upload progress depends on whether there is a body to upload.\n if (reqBody !== null && xhr.upload) {\n xhr.upload.addEventListener('progress', onUpProgress);\n }\n }\n\n // Fire the request, and notify the event stream that it was fired.\n xhr.send(reqBody);\n observer.next({type: HttpEventType.Sent});\n\n // This is the return from the Observable function, which is the\n // request cancellation handler.\n return () => {\n // On a cancellation, remove all registered event listeners.\n xhr.removeEventListener('error', onError);\n xhr.removeEventListener('load', onLoad);\n if (req.reportProgress) {\n xhr.removeEventListener('progress', onDownProgress);\n if (reqBody !== null && xhr.upload) {\n xhr.upload.removeEventListener('progress', onUpProgress);\n }\n }\n\n // Finally, abort the in-flight request.\n xhr.abort();\n };\n });\n }\nstatic decorators: DecoratorInvocation[] = [\n{ type: Injectable },\n];\n/**\n * @nocollapse\n */\nstatic ctorParameters: () => ({type: any, decorators?: DecoratorInvocation[]}|null)[] = () => [\n{type: XhrFactory, },\n];\n}\n\nfunction HttpXhrBackend_tsickle_Closure_declarations() {\n/** @type {?} */\nHttpXhrBackend.decorators;\n/**\n * @nocollapse\n * @type {?}\n */\nHttpXhrBackend.ctorParameters;\n/** @type {?} */\nHttpXhrBackend.prototype.xhrFactory;\n}\n\n\ninterface DecoratorInvocation {\n type: Function;\n args?: any[];\n}\n","/**\n * @license\n * Copyright Google Inc. All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\n\nimport {DOCUMENT} from '@angular/common';\nimport {Inject, Injectable, InjectionToken} from '@angular/core';\nimport {Observable} from 'rxjs/Observable';\nimport {Observer} from 'rxjs/Observer';\n\nimport {HttpBackend, HttpHandler} from './backend';\nimport {HttpRequest} from './request';\nimport {HttpErrorResponse, HttpEvent, HttpEventType, HttpResponse} from './response';\n\n// Every request made through JSONP needs a callback name that's unique across the\n// whole page. Each request is assigned an id and the callback name is constructed\n// from that. The next id to be assigned is tracked in a global variable here that\n// is shared among all applications on the page.\nlet /** @type {?} */ nextRequestId: number = 0;\n\n// Error text given when a JSONP script is injected, but doesn't invoke the callback\n// passed in its URL.\nexport const /** @type {?} */ JSONP_ERR_NO_CALLBACK = 'JSONP injected script did not invoke callback.';\n\n// Error text given when a request is passed to the JsonpClientBackend that doesn't\n// have a request method JSONP.\nexport const /** @type {?} */ JSONP_ERR_WRONG_METHOD = 'JSONP requests must use JSONP request method.';\nexport const /** @type {?} */ JSONP_ERR_WRONG_RESPONSE_TYPE = 'JSONP requests must use Json response type.';\n/**\n * DI token/abstract type representing a map of JSONP callbacks.\n * \n * In the browser, this should always be the `window` object.\n * \n * \\@experimental\n * @abstract\n */\nexport abstract class JsonpCallbackContext { [key: string]: (data: any) => void; }\n/**\n * `HttpBackend` that only processes `HttpRequest` with the JSONP method,\n * by performing JSONP style requests.\n * \n * \\@experimental\n */\nexport class JsonpClientBackend implements HttpBackend {\n/**\n * @param {?} callbackMap\n * @param {?} document\n */\nconstructor(private callbackMap: JsonpCallbackContext,\nprivate document: any) {}\n/**\n * Get the name of the next callback method, by incrementing the global `nextRequestId`.\n * @return {?}\n */\nprivate nextCallback(): string { return `ng_jsonp_callback_${nextRequestId++}`; }\n/**\n * Process a JSONP request and return an event stream of the results.\n * @param {?} req\n * @return {?}\n */\nhandle(req: HttpRequest): Observable> {\n // Firstly, check both the method and response type. If either doesn't match\n // then the request was improperly routed here and cannot be handled.\n if (req.method !== 'JSONP') {\n throw new Error(JSONP_ERR_WRONG_METHOD);\n } else if (req.responseType !== 'json') {\n throw new Error(JSONP_ERR_WRONG_RESPONSE_TYPE);\n }\n\n // Everything else happens inside the Observable boundary.\n return new Observable>((observer: Observer>) => {\n // The first step to make a request is to generate the callback name, and replace the\n // callback placeholder in the URL with the name. Care has to be taken here to ensure\n // a trailing &, if matched, gets inserted back into the URL in the correct place.\n const /** @type {?} */ callback = this.nextCallback();\n const /** @type {?} */ url = req.urlWithParams.replace(/=JSONP_CALLBACK(&|$)/, `=${callback}$1`);\n\n // Construct the