/** * @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 */ import { Injectable } from '@angular/core'; import { __platform_browser_private__ } from '@angular/platform-browser'; import { Observable } from 'rxjs/Observable'; import { ResponseOptions } from '../base_response_options'; import { ContentType, RequestMethod, ResponseContentType, ResponseType } from '../enums'; import { Headers } from '../headers'; import { getResponseURL, isSuccess } from '../http_utils'; import { XSRFStrategy } from '../interfaces'; import { Response } from '../static_response'; import { BrowserXhr } from './browser_xhr'; var /** @type {?} */ XSSI_PREFIX = /^\)\]\}',?\n/; /** * Creates connections using `XMLHttpRequest`. Given a fully-qualified * request, an `XHRConnection` will immediately create an `XMLHttpRequest` object and send the * request. * * This class would typically not be created or interacted with directly inside applications, though * the {\@link MockConnection} may be interacted with in tests. * * \@experimental */ export var XHRConnection = (function () { /** * @param {?} req * @param {?} browserXHR * @param {?=} baseResponseOptions */ function XHRConnection(req, browserXHR, baseResponseOptions) { var _this = this; this.request = req; this.response = new Observable(function (responseObserver) { var _xhr = browserXHR.build(); _xhr.open(RequestMethod[req.method].toUpperCase(), req.url); if (req.withCredentials != null) { _xhr.withCredentials = req.withCredentials; } // load event handler var onLoad = function () { // normalize IE9 bug (http://bugs.jquery.com/ticket/1450) var status = _xhr.status === 1223 ? 204 : _xhr.status; var body = null; // HTTP 204 means no content if (status !== 204) { // responseText is the old-school way of retrieving response (supported by IE8 & 9) // response/responseType properties were introduced in ResourceLoader Level2 spec // (supported by IE10) body = (typeof _xhr.response === 'undefined') ? _xhr.responseText : _xhr.response; // Implicitly strip a potential XSSI prefix. if (typeof body === 'string') { body = body.replace(XSSI_PREFIX, ''); } } // fix status code when it is 0 (0 status is undocumented). // Occurs when accessing file resources or on Android 4.1 stock browser // while retrieving files from application cache. if (status === 0) { status = body ? 200 : 0; } var headers = Headers.fromResponseHeaderString(_xhr.getAllResponseHeaders()); // IE 9 does not provide the way to get URL of response var url = getResponseURL(_xhr) || req.url; var statusText = _xhr.statusText || 'OK'; var responseOptions = new ResponseOptions({ body: body, status: status, headers: headers, statusText: statusText, url: url }); if (baseResponseOptions != null) { responseOptions = baseResponseOptions.merge(responseOptions); } var response = new Response(responseOptions); response.ok = isSuccess(status); if (response.ok) { responseObserver.next(response); // TODO(gdi2290): defer complete if array buffer until done responseObserver.complete(); return; } responseObserver.error(response); }; // error event handler var onError = function (err) { var responseOptions = new ResponseOptions({ body: err, type: ResponseType.Error, status: _xhr.status, statusText: _xhr.statusText, }); if (baseResponseOptions != null) { responseOptions = baseResponseOptions.merge(responseOptions); } responseObserver.error(new Response(responseOptions)); }; _this.setDetectedContentType(req, _xhr); if (req.headers == null) { req.headers = new Headers(); } if (!req.headers.has('Accept')) { req.headers.append('Accept', 'application/json, text/plain, */*'); } req.headers.forEach(function (values, name) { return _xhr.setRequestHeader(name, values.join(',')); }); // Select the correct buffer type to store the response if (req.responseType != null && _xhr.responseType != null) { switch (req.responseType) { case ResponseContentType.ArrayBuffer: _xhr.responseType = 'arraybuffer'; break; case ResponseContentType.Json: _xhr.responseType = 'json'; break; case ResponseContentType.Text: _xhr.responseType = 'text'; break; case ResponseContentType.Blob: _xhr.responseType = 'blob'; break; default: throw new Error('The selected responseType is not supported'); } } _xhr.addEventListener('load', onLoad); _xhr.addEventListener('error', onError); _xhr.send(_this.request.getBody()); return function () { _xhr.removeEventListener('load', onLoad); _xhr.removeEventListener('error', onError); _xhr.abort(); }; }); } /** * @param {?} req * @param {?} _xhr * @return {?} */ XHRConnection.prototype.setDetectedContentType = function (req /** TODO Request */, _xhr /** XMLHttpRequest */) { // Skip if a custom Content-Type header is provided if (req.headers != null && req.headers.get('Content-Type') != null) { return; } // Set the detected content type switch (req.contentType) { case ContentType.NONE: break; case ContentType.JSON: _xhr.setRequestHeader('content-type', 'application/json'); break; case ContentType.FORM: _xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); break; case ContentType.TEXT: _xhr.setRequestHeader('content-type', 'text/plain'); break; case ContentType.BLOB: var /** @type {?} */ blob = req.blob(); if (blob.type) { _xhr.setRequestHeader('content-type', blob.type); } break; } }; return XHRConnection; }()); function XHRConnection_tsickle_Closure_declarations() { /** @type {?} */ XHRConnection.prototype.request; /** * Response {\@link EventEmitter} which emits a single {\@link Response} value on load event of * `XMLHttpRequest`. * @type {?} */ XHRConnection.prototype.response; /** @type {?} */ XHRConnection.prototype.readyState; } /** * `XSRFConfiguration` sets up Cross Site Request Forgery (XSRF) protection for the application * using a cookie. See {\@link https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)} * for more information on XSRF. * * Applications can configure custom cookie and header names by binding an instance of this class * with different `cookieName` and `headerName` values. See the main HTTP documentation for more * details. * * \@experimental */ export var CookieXSRFStrategy = (function () { /** * @param {?=} _cookieName * @param {?=} _headerName */ function CookieXSRFStrategy(_cookieName, _headerName) { if (_cookieName === void 0) { _cookieName = 'XSRF-TOKEN'; } if (_headerName === void 0) { _headerName = 'X-XSRF-TOKEN'; } this._cookieName = _cookieName; this._headerName = _headerName; } /** * @param {?} req * @return {?} */ CookieXSRFStrategy.prototype.configureRequest = function (req) { var /** @type {?} */ xsrfToken = __platform_browser_private__.getDOM().getCookie(this._cookieName); if (xsrfToken) { req.headers.set(this._headerName, xsrfToken); } }; return CookieXSRFStrategy; }()); function CookieXSRFStrategy_tsickle_Closure_declarations() { /** @type {?} */ CookieXSRFStrategy.prototype._cookieName; /** @type {?} */ CookieXSRFStrategy.prototype._headerName; } /** * Creates {\@link XHRConnection} instances. * * This class would typically not be used by end users, but could be * overridden if a different backend implementation should be used, * such as in a node backend. * * ### Example * * ``` * import {Http, MyNodeBackend, HTTP_PROVIDERS, BaseRequestOptions} from '\@angular/http'; * \@Component({ * viewProviders: [ * HTTP_PROVIDERS, * {provide: Http, useFactory: (backend, options) => { * return new Http(backend, options); * }, deps: [MyNodeBackend, BaseRequestOptions]}] * }) * class MyComponent { * constructor(http:Http) { * http.request('people.json').subscribe(res => this.people = res.json()); * } * } * ``` * \@experimental */ export var XHRBackend = (function () { /** * @param {?} _browserXHR * @param {?} _baseResponseOptions * @param {?} _xsrfStrategy */ function XHRBackend(_browserXHR, _baseResponseOptions, _xsrfStrategy) { this._browserXHR = _browserXHR; this._baseResponseOptions = _baseResponseOptions; this._xsrfStrategy = _xsrfStrategy; } /** * @param {?} request * @return {?} */ XHRBackend.prototype.createConnection = function (request) { this._xsrfStrategy.configureRequest(request); return new XHRConnection(request, this._browserXHR, this._baseResponseOptions); }; XHRBackend.decorators = [ { type: Injectable }, ]; /** @nocollapse */ XHRBackend.ctorParameters = function () { return [ { type: BrowserXhr, }, { type: ResponseOptions, }, { type: XSRFStrategy, }, ]; }; return XHRBackend; }()); function XHRBackend_tsickle_Closure_declarations() { /** @type {?} */ XHRBackend.decorators; /** * @nocollapse * @type {?} */ XHRBackend.ctorParameters; /** @type {?} */ XHRBackend.prototype._browserXHR; /** @type {?} */ XHRBackend.prototype._baseResponseOptions; /** @type {?} */ XHRBackend.prototype._xsrfStrategy; } //# sourceMappingURL=xhr_backend.js.map