ng-http-interceptor
Version:
> Http Interceptor library for Angular
533 lines (515 loc) • 14.9 kB
JavaScript
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/mergeMap';
import { Injectable, NgModule } from '@angular/core';
import { ConnectionBackend, Headers, Http, HttpModule, RequestOptions, XHRBackend } from '@angular/http';
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class InterceptableStoreFactory {
/**
* @template D
* @return {?}
*/
createStore() {
return new InterceptableStore();
}
}
InterceptableStoreFactory.decorators = [
{ type: Injectable },
];
/** @nocollapse */
InterceptableStoreFactory.ctorParameters = () => [];
const DEFAULT_URL_STORE = '/';
class InterceptableStore {
constructor() {
this.storeMatcher = {};
this.stores = {};
this.activeStore = DEFAULT_URL_STORE;
}
/**
* @return {?}
*/
get store() {
return this._getStoreSafely(this.activeStore);
}
/**
* @param {?} interceptor
* @return {?}
*/
addInterceptor(interceptor) {
this.store.push(interceptor);
return this;
}
/**
* @param {?} interceptor
* @return {?}
*/
removeInterceptor(interceptor) {
const /** @type {?} */ idx = this.store.indexOf(interceptor);
if (idx === -1) {
return this;
}
this.store.splice(idx, 1);
return this;
}
/**
* @param {?=} interceptors
* @return {?}
*/
clearInterceptors(interceptors = []) {
if (interceptors.length > 0) {
interceptors.forEach(i => this.removeInterceptor(i));
}
else {
this.store.splice(0);
}
return this;
}
/**
* @param {?=} url
* @return {?}
*/
setActiveStore(url = DEFAULT_URL_STORE) {
this.activeStore = String(url);
if (url instanceof RegExp) {
this.storeMatcher[this.activeStore] = url;
}
return this;
}
/**
* @param {?=} key
* @return {?}
*/
getStore(key = DEFAULT_URL_STORE) {
return this._getStoreSafely(key);
}
/**
* @param {?=} url
* @return {?}
*/
getMatchedStores(url = DEFAULT_URL_STORE) {
const /** @type {?} */ backedUrl = `/${url.replace('/', '\\/')}/`; // Use it for direct string matching
return Object.keys(this.stores)
.filter(k => k === url || k === backedUrl || (this.storeMatcher[k] && this.storeMatcher[k].test(url)))
.filter((k, i, arr) => k !== DEFAULT_URL_STORE && arr.indexOf(k) === i)
.map(k => this.getStore(k))
.reduce((stores, store) => [...stores, ...store], this.getStore(DEFAULT_URL_STORE));
}
/**
* @param {?} key
* @return {?}
*/
_getStoreSafely(key) {
return (this.stores[key] || (this.stores[key] = []));
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class HttpInterceptorService {
/**
* @param {?} store
*/
constructor(store) {
this.store = store;
this._requestStore = this.store.createStore();
this._responseStore = this.store.createStore();
}
/**
* @param {?} res
* @return {?}
*/
static wrapInObservable(res) {
return res instanceof Observable ? res : Observable.of(res);
}
/**
* @param {?=} url
* @return {?}
*/
request(url = DEFAULT_URL_STORE) {
return this._requestStore.setActiveStore(url);
}
/**
* @param {?=} url
* @return {?}
*/
response(url = DEFAULT_URL_STORE) {
return this._responseStore.setActiveStore(url);
}
/**
* @param {?} url
* @param {?} method
* @param {?} data
* @param {?=} context
* @return {?}
*/
_interceptRequest(url, method, data, context) {
return this._requestStore.getMatchedStores(url).reduce((o, i) => o.flatMap(d => {
if (!d) {
return Observable.of(d);
}
return HttpInterceptorService.wrapInObservable(i(d, method, context));
}), Observable.of(data));
}
/**
* @param {?} url
* @param {?} method
* @param {?} response
* @param {?=} context
* @return {?}
*/
_interceptResponse(url, method, response, context) {
return this._responseStore.getMatchedStores(url).reduce((o, i) => i(o, method, context), response);
}
}
HttpInterceptorService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
HttpInterceptorService.ctorParameters = () => [
{ type: InterceptableStoreFactory, },
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
const SAFE_PROXY_TRAPS = ['get', 'set', 'apply'];
/**
* @param {?} ref
* @return {?}
*/
function identityFactory_(ref) {
return ref;
}
/**
* @param {?} provide
* @param {?} obj
* @return {?}
*/
function identityFactory(provide, obj) {
return {
provide,
useFactory: identityFactory_,
deps: [obj]
};
}
/**
* @param {?} handler
* @return {?}
*/
function safeProxyHandler_(handler) {
const /** @type {?} */ safeHandler = {};
SAFE_PROXY_TRAPS
.filter(trap => typeof handler[trap] === 'function')
.forEach(trap => safeHandler[trap] = handler[trap].bind(handler));
return safeHandler;
}
/**
* @param {?} obj
* @param {?} handler
* @return {?}
*/
function safeProxy(obj, handler) {
return new Proxy(obj, safeProxyHandler_(handler));
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class InterceptableHttpProxyService {
/**
* @param {?} http
* @param {?} httpInterceptorService
*/
constructor(http, httpInterceptorService) {
this.http = http;
this.httpInterceptorService = httpInterceptorService;
}
/**
* @param {?} url
* @return {?}
*/
static _extractUrl(url) {
const /** @type {?} */ dirtyUrl = url[0];
return typeof dirtyUrl === 'object' && 'url' in dirtyUrl ? dirtyUrl.url : dirtyUrl;
}
/**
* @param {?} target
* @param {?} p
* @param {?} receiver
* @return {?}
*/
get(target, p, receiver) {
InterceptableHttpProxyService._callStack.push(/** @type {?} */ (p));
return receiver;
}
/**
* @param {?} target
* @param {?} thisArg
* @param {?=} argArray
* @return {?}
*/
apply(target, thisArg, argArray) {
const /** @type {?} */ method = InterceptableHttpProxyService._callStack.pop();
// Comply with strict null checks
if (!method) {
return Observable.empty();
}
// create a object without prototype as the context object
const /** @type {?} */ context = Object.create(null);
return this.httpInterceptorService
._interceptRequest(InterceptableHttpProxyService._extractUrl(argArray), method, argArray, context)
.switchMap(args => {
// Check for request cancellation
if (!args) {
return Observable.empty();
}
const /** @type {?} */ response = this.http[method].apply(this.http, args);
return this.httpInterceptorService._interceptResponse(InterceptableHttpProxyService._extractUrl(args), method, response, context);
});
}
}
InterceptableHttpProxyService._callStack = [];
InterceptableHttpProxyService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
InterceptableHttpProxyService.ctorParameters = () => [
{ type: Http, },
{ type: HttpInterceptorService, },
];
const _proxyTarget = () => null;
// Make sure all Http methods are known for Proxy Polyfill
Object.keys(Http.prototype).forEach(method => _proxyTarget[method] = `Http.${method}`);
/**
* @param {?} http
* @param {?} interceptor
* @return {?}
*/
function _proxyFactory(http, interceptor) {
return safeProxy(_proxyTarget, new InterceptableHttpProxyService(http, interceptor));
}
/**
* @param {?} backend
* @param {?} options
* @param {?} interceptor
* @return {?}
*/
function proxyFactory(backend, options, interceptor) {
return _proxyFactory(new Http(backend, options), interceptor);
}
const InterceptableHttpProxyProviders = [
{
provide: Http,
useFactory: proxyFactory,
deps: [XHRBackend, RequestOptions, HttpInterceptorService]
},
identityFactory(InterceptableHttpProxyService, Http),
];
const InterceptableHttpProxyNoOverrideProviders = [
{
provide: InterceptableHttpProxyService,
useFactory: _proxyFactory,
deps: [Http, HttpInterceptorService]
}
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
class InterceptableHttp extends Http {
/**
* @param {?} _backend
* @param {?} _defaultOptions
*/
constructor(_backend, _defaultOptions) {
super(_backend, _defaultOptions);
}
}
InterceptableHttp.decorators = [
{ type: Injectable },
];
/** @nocollapse */
InterceptableHttp.ctorParameters = () => [
{ type: ConnectionBackend, },
{ type: RequestOptions, },
];
const InterceptableHttpProviders = [
identityFactory(InterceptableHttp, InterceptableHttpProxyService)
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
const SharedProviders = [
InterceptableStoreFactory,
HttpInterceptorService,
...InterceptableHttpProviders
];
const HTTP_INTERCEPTOR_PROVIDER = [
...SharedProviders,
...InterceptableHttpProxyProviders
];
const HTTP_INTERCEPTOR_NO_OVERRIDE_PROVIDER = [
...SharedProviders,
...InterceptableHttpProxyNoOverrideProviders
];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* \@module
* \@description
* Library provides Http Interceptor Service for Angular 2 application
* By default overrides angular's Http service
* To keep original Http service use with {\@see HttpInterceptorModule.noOverrideHttp()}
*/
class HttpInterceptorModule {
/**
* Keeps original Http service and adds InterceptableHttp service
* Requests made by Http service will not be intercepted - only those made by InterceptableHttp
* @return {?}
*/
static noOverrideHttp() {
return {
ngModule: HttpInterceptorNoOverrideModule
};
}
}
HttpInterceptorModule.decorators = [
{ type: NgModule, args: [{
imports: [HttpModule],
providers: [HTTP_INTERCEPTOR_PROVIDER]
},] },
];
/** @nocollapse */
HttpInterceptorModule.ctorParameters = () => [];
class HttpInterceptorNoOverrideModule {
}
HttpInterceptorNoOverrideModule.decorators = [
{ type: NgModule, args: [{
imports: [HttpModule],
providers: [HTTP_INTERCEPTOR_NO_OVERRIDE_PROVIDER]
},] },
];
/** @nocollapse */
HttpInterceptorNoOverrideModule.ctorParameters = () => [];
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* \@description
* Gets index of {\@link RequestOptions} in http data array for specified `method`.
* @param {?} method - Http method
* @return {?}
*/
function getHttpOptionsIdx(method) {
switch (method) {
case 'post':
case 'put':
case 'patch':
return 2;
default:
return 1;
}
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* \@description
* Gets http {\@link RequestOptions} from data array.
* If no options found and `alwaysOriginal = false` - returns new {\@link RequestOptions}.
* @param {?} data - Array of http data
* @param {?} method - Http method
* @param {?=} alwaysOriginal - `false` by default
* @return {?}
*/
function getHttpOptions(data, method, alwaysOriginal = false) {
return alwaysOriginal ?
data[getHttpOptionsIdx(method)] :
data[getHttpOptionsIdx(method)] || new RequestOptions();
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* \@description
* Gets {\@link RequestOptions} and it's index location in data array.
* If no options found and `alwaysOriginal = false` - creates new {\@link RequestOptions}.
* @param {?} data - Array of http data
* @param {?} method - Http method
* @param {?=} alwaysOriginal - `false` by default
* @return {?}
*/
function getHttpOptionsAndIdx(data, method, alwaysOriginal = false) {
return {
options: /** @type {?} */ (getHttpOptions(data, method, alwaysOriginal)),
idx: getHttpOptionsIdx(method)
};
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* \@description
* Gets {\@link Headers} from data array.
* If no {\@link RequestOptions} found - creates it and updates original data array.
* If no {\@link Headers} found - creates it and sets to {\@link RequestOptions}.
* @param {?} data - Array of http data
* @param {?} method - Http method
* @return {?}
*/
function getHttpHeadersOrInit(data, method) {
const { options, idx } = getHttpOptionsAndIdx(data, method);
let /** @type {?} */ headers = options.headers;
// Create and update Headers
if (!options.headers) {
headers = new Headers();
options.headers = headers;
}
// Set Options back
data[idx] = options;
return headers;
}
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* @module
* @description
* Library provides Http Interceptor Service for Angular 2 application
* By default overrides angular's Http service
* To keep original Http service use with {@see HttpInterceptorModule.noOverrideHttp()}
*/
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
/**
* Generated bundle index. Do not edit.
*/
export { HttpInterceptorModule, HttpInterceptorNoOverrideModule, InterceptableHttp, InterceptableHttpProviders, HttpInterceptorService, getHttpOptions, getHttpOptionsIdx, getHttpOptionsAndIdx, getHttpHeadersOrInit, InterceptableHttpProxyNoOverrideProviders as ɵm, InterceptableHttpProxyProviders as ɵl, InterceptableHttpProxyService as ɵh, _proxyFactory as ɵj, _proxyTarget as ɵi, proxyFactory as ɵk, InterceptableStoreFactory as ɵc, HTTP_INTERCEPTOR_NO_OVERRIDE_PROVIDER as ɵb, HTTP_INTERCEPTOR_PROVIDER as ɵa, identityFactory as ɵe, identityFactory_ as ɵd, safeProxy as ɵg, safeProxyHandler_ as ɵf };