UNPKG

p3x-angular-http-cache-interceptor

Version:

🔥 Cache every request in Angular, not only the GET, but all methods of this interceptor, and allows you to interact with the interceptor via specific headers and modify the request, and these specific headers will be not included in the final request

175 lines (166 loc) 7.45 kB
import * as i0 from '@angular/core'; import { InjectionToken, Injectable, Inject, Optional, NgModule } from '@angular/core'; import { HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http'; import { Observable, of } from 'rxjs'; import hash from 'object-hash'; import { tap } from 'rxjs/operators'; // cache headers has to have a x- prefix var CachingHeaders; (function (CachingHeaders) { CachingHeaders["NoCache"] = "x-p3x-no-cache"; CachingHeaders["Cache"] = "x-p3x-cache"; })(CachingHeaders || (CachingHeaders = {})); // cache headers has to have a x- prefix var CachingStore; (function (CachingStore) { CachingStore[CachingStore["Global"] = 0] = "Global"; CachingStore[CachingStore["PerModule"] = 1] = "PerModule"; })(CachingStore || (CachingStore = {})); const P3X_HTTP_CACHE_CONFIG = new InjectionToken('P3X_HTTP_CACHE_CONFIG'); const hashOptions = { algorithm: 'md5', encoding: 'hex' }; const globalCache = new Map(); class HttpCacheInterceptorInterceptor { getCache(key) { if (this.httpCacheConfig.store === CachingStore.Global) { return globalCache.get(key); } else { return this.cachedData.get(key); } } setCache(key, value) { if (this.httpCacheConfig.store === CachingStore.Global) { globalCache.set(key, value); } else { this.cachedData.set(key, value); } } constructor(httpCacheConfigToken) { this.cachedData = new Map(); this.httpCacheConfig = { behavior: CachingHeaders.Cache, store: CachingStore.Global, }; if (httpCacheConfigToken) { this.httpCacheConfig = httpCacheConfigToken; } } httpToKey(httpRequest) { const body = JSON.parse(JSON.stringify(httpRequest.body)); const key = httpRequest.method + '@' + httpRequest.urlWithParams + '@' + hash(httpRequest.params, hashOptions) + '@' + hash(body, hashOptions); return key; } intercept(httpRequest, next) { //console.log(httpRequest) //console.log('has', httpRequest.headers.has(CachingHeaders.NoCache)) //console.log('value', httpRequest.headers.get(CachingHeaders.NoCache)) const forcedCache = httpRequest.headers.get(CachingHeaders.Cache) !== null; const forcedNoneCache = httpRequest.headers.get(CachingHeaders.NoCache) !== null; //console.log('forcedCache', forcedCache, 'forcedNoneCache', forcedNoneCache) let headers = httpRequest.headers.delete(CachingHeaders.NoCache); headers = headers.delete(CachingHeaders.Cache); httpRequest = httpRequest.clone({ headers: headers }); if (forcedCache && forcedNoneCache) { throw new Error('You cannot use cache and non-cache header at once!'); } else if (forcedNoneCache || (this.httpCacheConfig.behavior === CachingHeaders.NoCache && !forcedCache)) { return next.handle(httpRequest); } else if (forcedCache || (this.httpCacheConfig.behavior === CachingHeaders.Cache && !forcedNoneCache)) { // Checked if there is cached data for this URI const key = this.httpToKey(httpRequest); const lastResponse = this.getCache(key); if (lastResponse) { // In case of parallel requests to same URI, // return the request already in progress // otherwise return the last cached data //console.info('http cache interceptor hit cache', key) return (lastResponse instanceof Observable) ? lastResponse : of(lastResponse.clone()); } //console.info('http cache interceptor', key) // If the request of going through for first time // then let the request proceed and cache the response const requestHandle = next.handle(httpRequest).pipe(tap((stateEvent) => { if (stateEvent instanceof HttpResponse) { this.setCache(key, stateEvent.clone()); } })); // Meanwhile cache the request Observable to handle parallel request //this.cachedData.set(key, requestHandle); return requestHandle; } else { console.error(this.httpCacheConfig); console.error(httpRequest.headers); throw new Error('There is a configuration in your setup'); } /* // Also leave scope of resetting already cached data for a URI if (httpRequest.headers.get("reset-cache")) { this.cachedData.delete(httpRequest.urlWithParams); } */ } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: HttpCacheInterceptorInterceptor, deps: [{ token: P3X_HTTP_CACHE_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: HttpCacheInterceptorInterceptor }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: HttpCacheInterceptorInterceptor, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [P3X_HTTP_CACHE_CONFIG] }, { type: Optional }] }] }); class P3XHttpCacheInterceptorModule { static forRoot(httpCacheConfig) { return { ngModule: P3XHttpCacheInterceptorModule, providers: [ { provide: P3X_HTTP_CACHE_CONFIG, useValue: httpCacheConfig } ] }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: P3XHttpCacheInterceptorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.1.4", ngImport: i0, type: P3XHttpCacheInterceptorModule }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: P3XHttpCacheInterceptorModule, providers: [ { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptorInterceptor, multi: true } ] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.4", ngImport: i0, type: P3XHttpCacheInterceptorModule, decorators: [{ type: NgModule, args: [{ declarations: [], imports: [], providers: [ { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptorInterceptor, multi: true } ], exports: [] }] }] }); /* * Public API Surface of angular-http-cache-interceptor */ /** * Generated bundle index. Do not edit. */ export { CachingHeaders, CachingStore, P3XHttpCacheInterceptorModule, P3X_HTTP_CACHE_CONFIG }; //# sourceMappingURL=p3x-angular-http-cache-interceptor.mjs.map