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
JavaScript
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