@angular/http
Version:
Angular - the http service
286 lines • 11.3 kB
JavaScript
/**
* @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.
* *
*/
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.
* *
*/
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';
* 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());
* }
* }
* ```
*/
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