UNPKG

x-ng2-http-interceptor

Version:
395 lines 18.5 kB
var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; import { Headers, Http, RequestMethod } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/empty'; import 'rxjs/add/observable/of'; import 'rxjs/add/observable/throw'; import 'rxjs/add/operator/catch'; import 'rxjs/add/operator/mergeMap'; import { InterceptorResponseWrapper } from './interceptor-response-wrapper'; import { InterceptorRequestBuilderInternal } from './interceptor-request-builder-internal'; import { InterceptorResponseWrapperBuilderInternal } from './interceptor-response-wrapper-builder-internal'; import { InterceptorUtils } from './interceptor-utils'; /** * Wrapper around native angular `Http` service. * Allows you to add `Interceptor`s that lets you do * 1. Transform request before it reaches the actual request, such as, add headers transparently * 2. Transform response, such as stripout the top level object & return the payload (or) raise errors if `response.status` is not `ok` * 3. To short circuit the request flow based on runtime data * 4. To selective caching/log request/responses * 5. Augment the real `Observable<Response>` that native angular `http.request(..)` returns * 6. Store intermediate data that can be shared across the interceptors * 7. Generate handcrafted response incase of error/base of your runtime decision * * The service executes methods in the interceptor chain in the following manner * 1. For each of the listed interceptor, tranforms the request by invoking\ * `beforeRequest(..)` on each interceptor in the same order they are added * 2. Invokes native angular `http.request(..)` with the result of last interceptor's `beforeRequest(..)` response * 3. Invokes `onResponse(..)` on each interceptor in the reverse order they are added * 4. The response from `onResponse(..)` of the final interceptor in the chain would be sent to subscriber */ export var InterceptorService = (function (_super) { __extends(InterceptorService, _super); function InterceptorService(backend, defaultOptions) { _super.call(this, backend, defaultOptions); this.interceptors = []; } /** Parent overrides **/ InterceptorService.prototype.request = function (url, options) { var interceptorOptions; if (!options) { interceptorOptions = {}; } else if (this.representsInterceptorFlavor(options)) { interceptorOptions = options; } else { interceptorOptions = InterceptorUtils.from(options); } interceptorOptions.headers = interceptorOptions.headers || new Headers(); var request = InterceptorRequestBuilderInternal.new() .url(url) .options(interceptorOptions) .sharedData(interceptorOptions.sharedData || {}) .build(); return this.httpRequest(request); }; /** * Performs a request with `get` http method. */ InterceptorService.prototype.get = function (url, options) { options = options || {}; options.method = RequestMethod.Get; options.url = options.url || url; return this.request(url, options); }; /** * Performs a request with `post` http method. */ InterceptorService.prototype.post = function (url, body, options) { options = options || {}; options.method = RequestMethod.Post; options.url = options.url || url; options.body = options.body || body; return this.request(url, options); }; /** * Performs a request with `put` http method. */ InterceptorService.prototype.put = function (url, body, options) { options = options || {}; options.method = RequestMethod.Put; options.url = options.url || url; options.body = options.body || body; return this.request(url, options); }; /** * Performs a request with `delete` http method. */ InterceptorService.prototype.delete = function (url, options) { options = options || {}; options.method = RequestMethod.Delete; options.url = options.url || url; return this.request(url, options); }; /** * Performs a request with `patch` http method. */ InterceptorService.prototype.patch = function (url, body, options) { options = options || {}; options.method = RequestMethod.Patch; options.url = options.url || url; options.body = options.body || body; return this.request(url, options); }; /** * Performs a request with `head` http method. */ InterceptorService.prototype.head = function (url, options) { options = options || {}; options.method = RequestMethod.Head; options.url = options.url || url; return this.request(url, options); }; /** * Performs a request with `options` http method. */ InterceptorService.prototype.options = function (url, options) { options = options || {}; options.method = RequestMethod.Options; options.url = options.url || url; return this.request(url, options); }; /** * Appends this interceptor to the list of interceptors */ InterceptorService.prototype.addInterceptor = function (interceptor) { this.interceptors.push(interceptor); }; Object.defineProperty(InterceptorService.prototype, "realResponseObservableTransformer", { /** * Sets response transformer */ set: function (value) { this._realResponseObservableTransformer = value; }, enumerable: true, configurable: true }); /** Private functions **/ InterceptorService.prototype.httpRequest = function (request) { var _this = this; return this.runBeforeInterceptors(request) .flatMap(function (transformedRequest, _) { var transformedRequestInternal = transformedRequest; var interceptorRequestInternalBuilder = InterceptorRequestBuilderInternal.new(transformedRequestInternal); if (interceptorRequestInternalBuilder.getErr() || interceptorRequestInternalBuilder.getAlreadyShortCircuited()) { var responseWrapper = InterceptorResponseWrapperBuilderInternal .newInternal(_this.interceptors.length, transformedRequestInternal) .build(); return Observable.of(responseWrapper); } else if (interceptorRequestInternalBuilder.getShortCircuitAtCurrentStep()) { var responseWrapper = InterceptorResponseWrapperBuilderInternal .newInternal(_this.interceptors.length, transformedRequestInternal) .build(); return Observable.of(responseWrapper); } var response$ = _super.prototype.request.call(_this, transformedRequest.url, transformedRequest.options); if (_this._realResponseObservableTransformer) { response$ = _this._realResponseObservableTransformer.transform(response$, transformedRequest, new _this.HttpDirect(), _this); } return response$.map(function (response) { return InterceptorResponseWrapperBuilderInternal .newInternal(_this.interceptors.length, transformedRequestInternal) .response(response) .build(); }).catch(function (err) { var responseBuilder = InterceptorResponseWrapperBuilderInternal .newInternal(_this.interceptors.length, transformedRequestInternal) .err(err) .errEncounteredAt(_this.interceptors.length) .errEncounteredInRequestCycle(true); return Observable.of(responseBuilder.build()); }); }) .flatMap(function (responseWrapper, index) { return _this.runAfterInterceptors(responseWrapper); }) .flatMap(function (responseWrapper, index) { if (!responseWrapper.response) { if (responseWrapper.err) { return Observable.throw(responseWrapper.err); } else if (responseWrapper.isShortCircuited()) { return Observable.throw(new Error('Short circuit was triggered, but no short circuit handlers generated any resonse')); } else { return Observable.throw(new Error('Response is empty')); } } return Observable.of(responseWrapper.response); }); }; InterceptorService.prototype.runBeforeInterceptors = function (params) { var request$ = Observable.of(params); var _loop_1 = function(index) { var interceptor = this_1.interceptors[index]; request$ = request$ .flatMap(function (request, _) { var requestInternalBuilder = InterceptorRequestBuilderInternal.new(request); if (requestInternalBuilder.getErr() || requestInternalBuilder.getAlreadyShortCircuited()) { return Observable.of(request); } else if (requestInternalBuilder.getShortCircuitAtCurrentStep()) { var requestBuilder = InterceptorRequestBuilderInternal.new(request) .shortCircuitAtCurrentStep(false) .shortCircuitTriggeredBy(index - 1) // since the last interceptor requested for short circuit .alreadyShortCircuited(true); return Observable.of(requestBuilder.build()); } if (interceptor.beforeRequest !== undefined) { var processedRequest = interceptor.beforeRequest(request, index); var processedRequest$ = void 0; if (!processedRequest) { processedRequest$ = Observable.of(request); } else if (processedRequest instanceof Observable) { processedRequest$ = processedRequest; } else { processedRequest$ = Observable.of(processedRequest); } return processedRequest$ .catch(function (err, caught) { var responseBuilder = InterceptorRequestBuilderInternal.new(request) .err(err) .errEncounteredAt(index); return Observable.of(responseBuilder.build()); }); } return Observable.of(request); }); }; var this_1 = this; for (var index = 0; index < this.interceptors.length; index++) { _loop_1(index); } return request$; }; InterceptorService.prototype.runAfterInterceptors = function (responseWrapper) { var responseWrapper$ = Observable.of(responseWrapper); var startFrom; if (responseWrapper.err) { startFrom = responseWrapper.errEncounteredAt; } else if (responseWrapper.isShortCircuited()) { startFrom = responseWrapper.shortCircuitTriggeredBy; } else { startFrom = this.interceptors.length - 1; } // If error occurred when making actual server call, lets start from last interceptor in the chain if (startFrom === this.interceptors.length) { startFrom = this.interceptors.length - 1; } var _loop_2 = function(index) { var interceptor = this_2.interceptors[index]; responseWrapper$ = responseWrapper$ .flatMap(function (transformedResponseWrapper, _) { if (transformedResponseWrapper.forceRequestCompletion) { if (interceptor.onForceCompleteOrForceReturn !== undefined) { interceptor.onForceCompleteOrForceReturn(transformedResponseWrapper, index); } if (index === 0) { return Observable.empty(); } else { return Observable.of(transformedResponseWrapper); } } else if (transformedResponseWrapper.forceReturnResponse) { if (interceptor.onForceCompleteOrForceReturn !== undefined) { interceptor.onForceCompleteOrForceReturn(transformedResponseWrapper, index); } return Observable.of(transformedResponseWrapper); } var processedResponse; if (transformedResponseWrapper.err) { if (interceptor.onErr !== undefined) { processedResponse = interceptor.onErr(transformedResponseWrapper, index); } } else if (transformedResponseWrapper.isShortCircuited()) { if (interceptor.onShortCircuit !== undefined) { processedResponse = interceptor.onShortCircuit(transformedResponseWrapper, index); } } else if (interceptor.onResponse !== undefined) { processedResponse = interceptor.onResponse(transformedResponseWrapper, index); } var procesedResponseWrapper$; if (!processedResponse) { procesedResponseWrapper$ = Observable.of(transformedResponseWrapper); } else if (processedResponse instanceof InterceptorResponseWrapper) { procesedResponseWrapper$ = Observable.of(processedResponse); } else { procesedResponseWrapper$ = processedResponse; } return procesedResponseWrapper$ .catch(function (err, __) { var responseBuilder = InterceptorResponseWrapperBuilderInternal.newInternal(index, transformedResponseWrapper) .err(err) .errEncounteredAt(index) .errEncounteredInRequestCycle(false); return Observable.of(responseBuilder.build()); }); }); }; var this_2 = this; for (var index = startFrom; index >= 0; index--) { _loop_2(index); } return responseWrapper$; }; /** * Tests whether the passed in object represents interceptor version/native request options */ InterceptorService.prototype.representsInterceptorFlavor = function (options) { return options.sharedData !== undefined && options.sharedData !== null; }; Object.defineProperty(InterceptorService.prototype, "HttpDirect", { /** * Returns an implementation that mirrors angular `Http` interface; * This interface allows the response transformers to make calls directly to HTTP calls * without being interceted by {@code InterceptorService}; i.e `this` */ get: function () { var interceptorService = this; return (function () { function class_1() { } class_1.prototype.request = function (url, options) { return interceptorService.requestNative(url, options); }; class_1.prototype.get = function (url, options) { return interceptorService.getNative(url, options); }; class_1.prototype.post = function (url, body, options) { return interceptorService.postNative(url, body, options); }; class_1.prototype.put = function (url, body, options) { return interceptorService.putNative(url, body, options); }; class_1.prototype.delete = function (url, options) { return interceptorService.deleteNative(url, options); }; class_1.prototype.patch = function (url, body, options) { return interceptorService.patchNative(url, body, options); }; class_1.prototype.head = function (url, options) { return interceptorService.headNative(url, options); }; class_1.prototype.options = function (url, options) { return interceptorService.optionsNative(url, options); }; return class_1; }()); }, enumerable: true, configurable: true }); InterceptorService.prototype.requestNative = function (url, options) { return _super.prototype.request.call(this, url, options); }; InterceptorService.prototype.getNative = function (url, options) { return _super.prototype.get.call(this, url, options); }; InterceptorService.prototype.postNative = function (url, body, options) { return _super.prototype.post.call(this, url, body, options); }; InterceptorService.prototype.putNative = function (url, body, options) { return _super.prototype.put.call(this, url, body, options); }; InterceptorService.prototype.deleteNative = function (url, options) { return _super.prototype.delete.call(this, url, options); }; InterceptorService.prototype.patchNative = function (url, body, options) { return _super.prototype.patch.call(this, url, body, options); }; InterceptorService.prototype.headNative = function (url, options) { return _super.prototype.head.call(this, url, options); }; InterceptorService.prototype.optionsNative = function (url, options) { return _super.prototype.options.call(this, url, options); }; return InterceptorService; }(Http)); //# sourceMappingURL=interceptor-service.js.map