UNPKG

ng-http-caching

Version:

Cache for HTTP requests in Angular application.

1 lines 50.7 kB
{"version":3,"file":"ng-http-caching.mjs","sources":["../../../projects/ng-http-caching/src/lib/storage/ng-http-caching-memory-storage.ts","../../../projects/ng-http-caching/src/lib/ng-http-caching.service.ts","../../../projects/ng-http-caching/src/lib/ng-http-caching-interceptor.service.ts","../../../projects/ng-http-caching/src/lib/ng-http-caching.module.ts","../../../projects/ng-http-caching/src/lib/ng-http-caching-provider.ts","../../../projects/ng-http-caching/src/lib/storage/ng-http-caching-browser-storage.ts","../../../projects/ng-http-caching/src/lib/storage/ng-http-caching-local-storage.ts","../../../projects/ng-http-caching/src/lib/storage/ng-http-caching-session-storage.ts","../../../projects/ng-http-caching/src/public-api.ts","../../../projects/ng-http-caching/src/ng-http-caching.ts"],"sourcesContent":["import { NgHttpCachingStorageInterface } from './ng-http-caching-storage.interface';\r\nimport { NgHttpCachingEntry } from '../ng-http-caching.service';\r\n\r\nexport class NgHttpCachingMemoryStorage extends Map<string, NgHttpCachingEntry<any, any>> implements NgHttpCachingStorageInterface { }\r\n","import { Injectable, InjectionToken, VERSION, isDevMode, inject } from '@angular/core';\r\nimport { HttpRequest, HttpResponse, HttpEvent, HttpContextToken, HttpContext, HttpHeaders } from '@angular/common/http';\r\nimport { Observable } from 'rxjs/internal/Observable';\r\nimport { NgHttpCachingStorageInterface } from './storage/ng-http-caching-storage.interface';\r\nimport { NgHttpCachingMemoryStorage } from './storage/ng-http-caching-memory-storage';\r\n\r\nexport type NgHttpCachingContext = Pick<NgHttpCachingConfig, 'getKey' | 'isCacheable' | 'isExpired' | 'isValid'>;\r\n\r\nexport const NG_HTTP_CACHING_CONTEXT = new HttpContextToken<NgHttpCachingContext>(() => ({}));\r\n\r\nexport const withNgHttpCachingContext = (value: NgHttpCachingContext, context: HttpContext = new HttpContext()) => context.set(NG_HTTP_CACHING_CONTEXT, value)\r\n\r\nexport const checkCacheHeaders = (headers: HttpHeaders): boolean => {\r\n // check Cache-Control\r\n const cacheControlHeader = headers.get('cache-control');\r\n if (cacheControlHeader) {\r\n const cacheControl = cacheControlHeader.toLowerCase();\r\n if (cacheControl.includes('no-store')) {\r\n return false;\r\n } else if (cacheControl.includes('no-cache')) {\r\n return false;\r\n } else {\r\n return true;\r\n }\r\n }\r\n\r\n // check Expires header Expires if response is without Cache-Control\r\n const expiresHeader = headers.get('expires');\r\n if (expiresHeader) {\r\n const expires = Date.parse(expiresHeader);\r\n if (!isNaN(expires)) {\r\n return expires > Date.now();\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\nexport interface NgHttpCachingEntry<K = any, T = any> {\r\n /**\r\n * URL\r\n */\r\n url: string;\r\n /**\r\n * HttpResponse\r\n */\r\n response: HttpResponse<T>;\r\n /**\r\n * HttpRequest\r\n */\r\n request: HttpRequest<K>;\r\n /**\r\n * Timestamp of add to cache time\r\n */\r\n addedTime: number;\r\n /**\r\n * Cache version\r\n */\r\n version: string;\r\n}\r\n\r\nexport const NG_HTTP_CACHING_CONFIG = new InjectionToken<NgHttpCachingContext>(\r\n 'ng-http-caching.config'\r\n);\r\n\r\nexport enum NgHttpCachingStrategy {\r\n /**\r\n * All request are cacheable if HTTP method is into `allowedMethod`\r\n */\r\n ALLOW_ALL = 'ALLOW_ALL',\r\n /**\r\n * Only the request with `X-NG-HTTP-CACHING-ALLOW-CACHE` header are cacheable if HTTP method is into `allowedMethod`\r\n */\r\n DISALLOW_ALL = 'DISALLOW_ALL'\r\n}\r\n\r\nexport enum NgHttpCachingHeaders {\r\n /**\r\n * Request is cacheable if HTTP method is into `allowedMethod`\r\n */\r\n ALLOW_CACHE = 'X-NG-HTTP-CACHING-ALLOW-CACHE',\r\n /**\r\n * Request isn't cacheable\r\n */\r\n DISALLOW_CACHE = 'X-NG-HTTP-CACHING-DISALLOW-CACHE',\r\n /**\r\n * Specific cache lifetime for the request\r\n */\r\n LIFETIME = 'X-NG-HTTP-CACHING-LIFETIME',\r\n /**\r\n * You can tag multiple request by adding this header with the same tag and \r\n * using `NgHttpCachingService.clearCacheByTag(tag: string)` for delete all the tagged request\r\n */\r\n TAG = 'X-NG-HTTP-CACHING-TAG'\r\n}\r\n\r\nexport const NgHttpCachingHeadersList = Object.values(NgHttpCachingHeaders);\r\n\r\nexport const NG_HTTP_CACHING_SECOND_IN_MS = 1000;\r\nexport const NG_HTTP_CACHING_MINUTE_IN_MS = NG_HTTP_CACHING_SECOND_IN_MS * 60;\r\nexport const NG_HTTP_CACHING_HOUR_IN_MS = NG_HTTP_CACHING_MINUTE_IN_MS * 60;\r\nexport const NG_HTTP_CACHING_DAY_IN_MS = NG_HTTP_CACHING_HOUR_IN_MS * 24;\r\nexport const NG_HTTP_CACHING_WEEK_IN_MS = NG_HTTP_CACHING_DAY_IN_MS * 7;\r\nexport const NG_HTTP_CACHING_MONTH_IN_MS = NG_HTTP_CACHING_DAY_IN_MS * 30;\r\nexport const NG_HTTP_CACHING_YEAR_IN_MS = NG_HTTP_CACHING_DAY_IN_MS * 365;\r\n\r\nexport interface NgHttpCachingConfig {\r\n /**\r\n * Set the cache store. You can implement your custom store by implement the `NgHttpCachingStorageInterface` interface, eg.:\r\n */\r\n store?: NgHttpCachingStorageInterface;\r\n /**\r\n * Number of millisecond that a response is stored in the cache. \r\n * You can set specific \"lifetime\" for each request by add the header `X-NG-HTTP-CACHING-LIFETIME` (see example below).\r\n */\r\n lifetime?: number;\r\n /**\r\n * Array of allowed HTTP methods to cache. \r\n * You can allow multiple methods, eg.: `['GET', 'POST', 'PUT', 'DELETE', 'HEAD']` or \r\n * allow all methods by: `['ALL']`. If `allowedMethod` is an empty array (`[]`), no response are cached.\r\n * *Warning!* `NgHttpCaching` use the full url (url with query parameters) as unique key for the cached response,\r\n * this is correct for the `GET` request but is _potentially_ wrong for other type of request (eg. `POST`, `PUT`). \r\n * You can set a different \"key\" by customizing the `getKey` config method (see `getKey` section).\r\n */\r\n allowedMethod?: string[];\r\n /**\r\n * Set the cache strategy, possible strategies are:\r\n * - `NgHttpCachingStrategy.ALLOW_ALL`: All request are cacheable if HTTP method is into `allowedMethod`;\r\n * - `NgHttpCachingStrategy.DISALLOW_ALL`: Only the request with `X-NG-HTTP-CACHING-ALLOW-CACHE` header are cacheable if HTTP method is into `allowedMethod`;\r\n */\r\n cacheStrategy?: NgHttpCachingStrategy;\r\n /**\r\n * Cache version. When you have a breaking change, change the version, and it'll delete the current cache automatically.\r\n * The default value is Angular major version (eg. 13), in this way, the cache is invalidated on every Angular upgrade.\r\n */\r\n version?: string;\r\n /**\r\n * If true response headers cache-control and expires are respected.\r\n */\r\n checkResponseHeaders?: boolean;\r\n /**\r\n * If this function return `true` the request is expired and a new request is send to backend, if return `false` isn't expired. \r\n * If the result is `undefined`, the normal behaviour is provided.\r\n */\r\n isExpired?: <K, T>(entry: NgHttpCachingEntry<K, T>) => boolean | undefined | void;\r\n /**\r\n * If this function return `true` the request is cacheable, if return `false` isn't cacheable. \r\n * If the result is `undefined`, the normal behaviour is provided.\r\n */\r\n isCacheable?: <K>(req: HttpRequest<K>) => boolean | undefined | void;\r\n /**\r\n * This function return the unique key (`string`) for store the response into the cache. \r\n * If the result is `undefined`, the normal behaviour is provided.\r\n */\r\n getKey?: <K>(req: HttpRequest<K>) => string | undefined | void;\r\n /**\r\n * If this function return `true` the cache entry is valid and can be stored, if return `false` isn't valid. \r\n * If the result is `undefined`, the normal behaviour is provided.\r\n */\r\n isValid?: <K, T>(entry: NgHttpCachingEntry<K, T>) => boolean | undefined | void;\r\n}\r\n\r\nexport interface NgHttpCachingDefaultConfig extends NgHttpCachingConfig {\r\n store: NgHttpCachingStorageInterface;\r\n lifetime: number;\r\n allowedMethod: string[];\r\n cacheStrategy: NgHttpCachingStrategy;\r\n version: string;\r\n checkResponseHeaders: boolean;\r\n}\r\n\r\nexport const NgHttpCachingConfigDefault: Readonly<NgHttpCachingDefaultConfig> = {\r\n store: new NgHttpCachingMemoryStorage(),\r\n lifetime: NG_HTTP_CACHING_HOUR_IN_MS,\r\n version: VERSION.major,\r\n allowedMethod: ['GET', 'HEAD'],\r\n cacheStrategy: NgHttpCachingStrategy.ALLOW_ALL,\r\n checkResponseHeaders: false\r\n};\r\n\r\n@Injectable()\r\nexport class NgHttpCachingService {\r\n\r\n private readonly queue = new Map<string, Observable<HttpEvent<any>>>();\r\n\r\n private readonly config: NgHttpCachingDefaultConfig;\r\n\r\n private gcLock = false;\r\n\r\n private devMode: boolean = isDevMode();\r\n\r\n constructor() {\r\n const config: Readonly<NgHttpCachingConfig | null> = inject(NG_HTTP_CACHING_CONFIG, { optional: true });\r\n if (config) {\r\n this.config = { ...NgHttpCachingConfigDefault, ...config };\r\n } else {\r\n this.config = { ...NgHttpCachingConfigDefault };\r\n }\r\n // start cache clean\r\n this.runGc();\r\n }\r\n\r\n /**\r\n * Return the config\r\n */\r\n getConfig(): Readonly<NgHttpCachingConfig> {\r\n return this.config;\r\n }\r\n\r\n /**\r\n * Return the queue map\r\n */\r\n getQueue(): Readonly<Map<string, Observable<HttpEvent<any>>>> {\r\n return this.queue;\r\n }\r\n\r\n /**\r\n * Return the cache store\r\n */\r\n getStore(): Readonly<NgHttpCachingStorageInterface> {\r\n return this.config.store;\r\n }\r\n\r\n /**\r\n * Return response from cache\r\n */\r\n getFromCache<K, T>(req: HttpRequest<K>): Readonly<HttpResponse<T>> | undefined {\r\n const key: string = this.getKey(req);\r\n const cached: NgHttpCachingEntry<K, T> | undefined = this.config.store.get<K, T>(key);\r\n\r\n if (!cached) {\r\n return undefined;\r\n }\r\n\r\n if (this.isExpired(cached)) {\r\n this.clearCacheByKey(key);\r\n return undefined;\r\n }\r\n\r\n return this.deepFreeze(cached.response);\r\n }\r\n\r\n /**\r\n * Add response to cache\r\n */\r\n addToCache<K, T>(req: HttpRequest<K>, res: HttpResponse<T>): boolean {\r\n const entry: NgHttpCachingEntry<K, T> = {\r\n url: req.urlWithParams,\r\n response: res,\r\n request: req,\r\n addedTime: Date.now(),\r\n version: this.config.version,\r\n };\r\n if (this.isValid(entry)) {\r\n const key: string = this.getKey(req);\r\n this.config.store.set(key, entry);\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Delete response from cache\r\n */\r\n deleteFromCache<K>(req: HttpRequest<K>): boolean {\r\n const key: string = this.getKey(req);\r\n return this.clearCacheByKey(key);\r\n }\r\n\r\n /**\r\n * Clear the cache\r\n */\r\n clearCache(): void {\r\n this.config.store.clear();\r\n }\r\n\r\n /**\r\n * Clear the cache by key\r\n */\r\n clearCacheByKey(key: string): boolean {\r\n return this.config.store.delete(key);\r\n }\r\n\r\n /**\r\n * Clear the cache by keys\r\n */\r\n clearCacheByKeys(keys: Array<string>): number {\r\n let counter = 0;\r\n if (keys) {\r\n for (const key of keys) {\r\n if (this.clearCacheByKey(key)) {\r\n counter++;\r\n }\r\n }\r\n }\r\n return counter;\r\n }\r\n\r\n /**\r\n * Clear the cache by regex\r\n */\r\n clearCacheByRegex<K, T>(regex: RegExp): number {\r\n const keys: Array<string> = [];\r\n this.config.store.forEach<K, T>((_: NgHttpCachingEntry<K, T>, key: string) => {\r\n if (regex.test(key)) {\r\n keys.push(key);\r\n }\r\n });\r\n return this.clearCacheByKeys(keys);\r\n }\r\n\r\n /**\r\n * Clear the cache by TAG\r\n */\r\n clearCacheByTag<K, T>(tag: string): number {\r\n const keys: Array<string> = [];\r\n this.config.store.forEach<K, T>((entry: NgHttpCachingEntry<K, T>, key: string) => {\r\n const tagHeader = entry.request.headers.get(NgHttpCachingHeaders.TAG);\r\n if (tagHeader && tagHeader.split(',').includes(tag)) {\r\n keys.push(key);\r\n }\r\n });\r\n return this.clearCacheByKeys(keys);\r\n }\r\n\r\n /**\r\n * Run garbage collector (delete expired cache entry)\r\n */\r\n runGc<K, T>(): boolean {\r\n if (this.gcLock) {\r\n return false;\r\n }\r\n this.gcLock = true;\r\n const keys: Array<string> = [];\r\n this.config.store.forEach<K, T>((entry: NgHttpCachingEntry<K, T>, key: string) => {\r\n if (this.isExpired(entry)) {\r\n keys.push(key);\r\n }\r\n });\r\n this.clearCacheByKeys(keys);\r\n this.gcLock = false;\r\n return true;\r\n }\r\n\r\n /**\r\n * Return true if cache entry is expired\r\n */\r\n isExpired<K, T>(entry: NgHttpCachingEntry<K, T>): boolean {\r\n // if user provide custom method, use it\r\n const context = entry.request.context.get(NG_HTTP_CACHING_CONTEXT);\r\n if (typeof context?.isExpired === 'function') {\r\n const result = context.isExpired(entry);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // if user provide custom method, use it\r\n if (typeof this.config.isExpired === 'function') {\r\n const result = this.config.isExpired(entry);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // if version change, always expire\r\n if (this.config.version !== entry.version) {\r\n return true;\r\n }\r\n // config/default lifetime\r\n let lifetime: number = this.config.lifetime;\r\n // request has own lifetime\r\n const headerLifetime = entry.request.headers.get(NgHttpCachingHeaders.LIFETIME);\r\n if (headerLifetime) {\r\n lifetime = +headerLifetime;\r\n }\r\n // never expire if 0\r\n if (lifetime === 0) {\r\n return false;\r\n }\r\n // wrong lifetime\r\n if (lifetime < 0 || isNaN(lifetime)) {\r\n throw new Error('lifetime must be greater than or equal 0');\r\n }\r\n return entry.addedTime + lifetime < Date.now();\r\n }\r\n\r\n /**\r\n * Return true if cache entry is valid for store in the cache\r\n * Default behaviour is whether the status code falls in the 2xx range and response headers cache-control and expires allow cache.\r\n */\r\n isValid<K, T>(entry: NgHttpCachingEntry<K, T>): boolean {\r\n const context = entry.request.context.get(NG_HTTP_CACHING_CONTEXT);\r\n // if user provide custom method, use it\r\n if (typeof context.isValid === 'function') {\r\n const result = context.isValid(entry);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // if user provide custom method, use it\r\n if (typeof this.config.isValid === 'function') {\r\n const result = this.config.isValid(entry);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // different version\r\n if (this.config.version !== entry.version) {\r\n return false;\r\n }\r\n\r\n let fromHeader = true;\r\n if (this.config.checkResponseHeaders) {\r\n // check if response headers allow cache\r\n fromHeader = checkCacheHeaders(entry.response.headers);\r\n }\r\n return entry.response.ok && fromHeader;\r\n }\r\n\r\n /**\r\n * Return true if the request is cacheable\r\n */\r\n isCacheable<K>(req: HttpRequest<K>): boolean {\r\n const context = req.context.get(NG_HTTP_CACHING_CONTEXT);\r\n // if user provide custom method, use it\r\n if (typeof context?.isCacheable === 'function') {\r\n const result = context.isCacheable(req);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // if user provide custom method, use it\r\n if (typeof this.config.isCacheable === 'function') {\r\n const result = this.config.isCacheable(req);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // request has disallow cache header\r\n if (req.headers.has(NgHttpCachingHeaders.DISALLOW_CACHE)) {\r\n return false;\r\n }\r\n // strategy is disallow all...\r\n if (this.config.cacheStrategy === NgHttpCachingStrategy.DISALLOW_ALL) {\r\n // request isn't allowed if come without allow header\r\n if (!req.headers.has(NgHttpCachingHeaders.ALLOW_CACHE)) {\r\n return false;\r\n }\r\n }\r\n // if allowed method is only ALL, allow all http methods\r\n if (this.config.allowedMethod.length === 1) {\r\n if (this.config.allowedMethod[0] === 'ALL') {\r\n return true;\r\n }\r\n }\r\n // request is allowed if method is in allowedMethod\r\n return this.config.allowedMethod.indexOf(req.method) !== -1;\r\n }\r\n\r\n /**\r\n * Return the cache key.\r\n * Default key is http method plus url with query parameters, eg.:\r\n * `GET@https://github.com/nigrosimone/ng-http-caching`\r\n */\r\n getKey<K>(req: HttpRequest<K>): string {\r\n // if user provide custom method, use it\r\n const context = req.context.get(NG_HTTP_CACHING_CONTEXT);\r\n if (typeof context.getKey === 'function') {\r\n const result = context.getKey(req);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // if user provide custom method, use it\r\n if (typeof this.config.getKey === 'function') {\r\n const result = this.config.getKey(req);\r\n // if result is undefined, normal behaviour is provided\r\n if (result !== undefined) {\r\n return result;\r\n }\r\n }\r\n // default key is req.method plus url with query parameters\r\n return req.method + '@' + req.urlWithParams;\r\n }\r\n\r\n /**\r\n * Return observable from cache\r\n */\r\n getFromQueue<K, T>(req: HttpRequest<K>): Observable<HttpEvent<T>> | undefined {\r\n const key: string = this.getKey(req);\r\n const cached: Observable<HttpEvent<T>> | undefined = this.queue.get(key);\r\n\r\n if (!cached) {\r\n return undefined;\r\n }\r\n\r\n return cached;\r\n }\r\n\r\n /**\r\n * Add observable to cache\r\n */\r\n addToQueue<K, T>(req: HttpRequest<K>, obs: Observable<HttpEvent<T>>): void {\r\n const key: string = this.getKey(req);\r\n this.queue.set(key, obs);\r\n }\r\n\r\n /**\r\n * Delete observable from cache\r\n */\r\n deleteFromQueue<K>(req: HttpRequest<K>): boolean {\r\n const key: string = this.getKey(req);\r\n return this.queue.delete(key);\r\n }\r\n\r\n /**\r\n * Recursively Object.freeze simple Javascript structures consisting of plain objects, arrays, and primitives.\r\n * Make the data immutable.\r\n * @returns immutable object\r\n */\r\n private deepFreeze<S>(object: S): Readonly<S> {\r\n // No freezing in production (for better performance).\r\n if (!this.devMode || !object || typeof object !== 'object') {\r\n return object as Readonly<S>;\r\n }\r\n\r\n // When already frozen, we assume its children are frozen (for better performance).\r\n // This should be true if you always use `deepFreeze` to freeze objects.\r\n //\r\n // Note that Object.isFrozen will also return `true` for primitives (numbers,\r\n // strings, booleans, undefined, null), so there is no need to check for\r\n // those explicitly.\r\n if (Object.isFrozen(object)) {\r\n return object as Readonly<S>;\r\n }\r\n\r\n // At this point we know that we're dealing with either an array or plain object, so\r\n // just freeze it and recurse on its values.\r\n Object.freeze(object);\r\n Object.keys(object).forEach(key => this.deepFreeze((object as any)[key]));\r\n\r\n return object as Readonly<S>;\r\n }\r\n}\r\n","import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';\r\nimport { inject, Injectable } from '@angular/core';\r\nimport { asyncScheduler, Observable, of, scheduled } from 'rxjs';\r\nimport { tap, finalize, shareReplay } from 'rxjs/operators';\r\nimport { NgHttpCachingService, NgHttpCachingHeadersList } from './ng-http-caching.service';\r\n\r\n@Injectable()\r\nexport class NgHttpCachingInterceptorService implements HttpInterceptor {\r\n\r\n private readonly cacheService: NgHttpCachingService = inject(NgHttpCachingService);\r\n\r\n intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\r\n // run garbage collector\r\n this.cacheService.runGc();\r\n\r\n // Don't cache if it's not cacheable\r\n if (!this.cacheService.isCacheable(req)) {\r\n return this.sendRequest(req, next);\r\n }\r\n\r\n // Checked if there is pending response for this request\r\n const cachedObservable: Observable<HttpEvent<any>> | undefined = this.cacheService.getFromQueue(req);\r\n if (cachedObservable) {\r\n // console.log('cachedObservable',cachedObservable);\r\n return cachedObservable;\r\n }\r\n\r\n // Checked if there is cached response for this request\r\n const cachedResponse: HttpResponse<any> | undefined = this.cacheService.getFromCache(req);\r\n if (cachedResponse) {\r\n // console.log('cachedResponse');\r\n return scheduled(of(cachedResponse.clone()), asyncScheduler);\r\n }\r\n\r\n // If the request of going through for first time\r\n // then let the request proceed and cache the response\r\n // console.log('sendRequest', req);\r\n const shared = this.sendRequest(req, next).pipe(\r\n tap(event => {\r\n if (event instanceof HttpResponse) {\r\n this.cacheService.addToCache(req, event.clone());\r\n }\r\n }),\r\n finalize(() => {\r\n // delete pending request\r\n this.cacheService.deleteFromQueue(req);\r\n }),\r\n shareReplay()\r\n );\r\n\r\n // add pending request to queue for cache parallel request\r\n this.cacheService.addToQueue(req, shared);\r\n\r\n return shared;\r\n }\r\n\r\n /**\r\n * Send http request (next handler)\r\n */\r\n sendRequest(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {\r\n let cloned: HttpRequest<any> = req.clone();\r\n // trim custom headers before send request\r\n NgHttpCachingHeadersList.forEach(ngHttpCachingHeaders => {\r\n if (cloned.headers.has(ngHttpCachingHeaders)) {\r\n cloned = cloned.clone({ headers: cloned.headers.delete(ngHttpCachingHeaders) });\r\n }\r\n });\r\n return next.handle(cloned);\r\n }\r\n}\r\n","import { NgModule, ModuleWithProviders } from '@angular/core';\r\nimport { HTTP_INTERCEPTORS } from '@angular/common/http';\r\nimport {\r\n NG_HTTP_CACHING_CONFIG,\r\n NgHttpCachingConfig,\r\n NgHttpCachingService,\r\n} from './ng-http-caching.service';\r\nimport { NgHttpCachingInterceptorService } from './ng-http-caching-interceptor.service';\r\n\r\n@NgModule({\r\n providers: [\r\n NgHttpCachingService,\r\n NgHttpCachingInterceptorService,\r\n {\r\n provide: HTTP_INTERCEPTORS,\r\n useClass: NgHttpCachingInterceptorService,\r\n multi: true,\r\n },\r\n ]\r\n})\r\nexport class NgHttpCachingModule {\r\n static forRoot(\r\n ngHttpCachingConfig?: NgHttpCachingConfig\r\n ): ModuleWithProviders<NgHttpCachingModule> {\r\n return {\r\n ngModule: NgHttpCachingModule,\r\n providers: [\r\n {\r\n provide: NG_HTTP_CACHING_CONFIG,\r\n useValue: ngHttpCachingConfig,\r\n },\r\n ],\r\n };\r\n }\r\n}\r\n","import { EnvironmentProviders, makeEnvironmentProviders } from \"@angular/core\";\r\nimport { HTTP_INTERCEPTORS } from \"@angular/common/http\";\r\nimport { NgHttpCachingInterceptorService } from \"./ng-http-caching-interceptor.service\";\r\nimport { NG_HTTP_CACHING_CONFIG, NgHttpCachingConfig, NgHttpCachingService } from \"./ng-http-caching.service\";\r\n\r\nexport function provideNgHttpCaching(ngHttpCachingConfig?: NgHttpCachingConfig) {\r\n const providers: EnvironmentProviders[] = [];\r\n if (ngHttpCachingConfig) {\r\n providers.push(makeEnvironmentProviders([{\r\n provide: NG_HTTP_CACHING_CONFIG,\r\n useValue: ngHttpCachingConfig,\r\n }]));\r\n }\r\n providers.push(makeEnvironmentProviders([\r\n NgHttpCachingService,\r\n {\r\n provide: HTTP_INTERCEPTORS,\r\n useClass: NgHttpCachingInterceptorService,\r\n multi: true,\r\n },\r\n NgHttpCachingInterceptorService\r\n ]));\r\n return providers;\r\n}\r\n","import { NgHttpCachingStorageInterface } from './ng-http-caching-storage.interface';\r\nimport { NgHttpCachingEntry } from '../ng-http-caching.service';\r\nimport { HttpHeaders, HttpParams, HttpRequest, HttpResponse } from '@angular/common/http';\r\n\r\nconst KEY_PREFIX = 'NgHttpCaching::';\r\n\r\nexport interface NgHttpCachingStorageEntry {\r\n url: string;\r\n response: string;\r\n request: string;\r\n addedTime: number;\r\n version: string;\r\n}\r\n\r\nexport const serializeRequest = (req: HttpRequest<any>): string => {\r\n const request = req.clone(); // Make a clone, useful for doing destructive things\r\n return JSON.stringify({\r\n headers: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer\r\n request.headers.keys().map( // Get all of the headers\r\n (key: string) => [key, request.headers.getAll(key)] // Get all of the corresponding values for the headers\r\n )\r\n ),\r\n method: request.method, // The Request Method, e.g. GET, POST, DELETE\r\n url: request.url, // The URL\r\n params: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer\r\n request.headers.keys().map( // Get all of the headers\r\n (key: string) => [key, request.headers.getAll(key)] // Get all of the corresponding values for the headers\r\n )\r\n ), // The request parameters\r\n withCredentials: request.withCredentials, // Whether credentials are being sent\r\n responseType: request.responseType, // The response type\r\n body: request.serializeBody() // Serialize the body, all well and good since we are working on a clone\r\n });\r\n}\r\n\r\nexport const serializeResponse = (res: HttpResponse<any>): string => {\r\n const response = res.clone();\r\n return JSON.stringify({\r\n headers: Object.fromEntries( // Just a helper to make this into an object, not really required but makes the output nicer\r\n response.headers.keys().map( // Get all of the headers\r\n (key: string) => [key, response.headers.getAll(key)] // Get all of the corresponding values for the headers\r\n )\r\n ),\r\n status: response.status,\r\n statusText: response.statusText,\r\n url: response.url,\r\n body: response.body // Serialize the body, all well and good since we are working on a clone\r\n });\r\n}\r\n\r\nexport const deserializeRequest = <T = any>(req: string): HttpRequest<T> => {\r\n const request = JSON.parse(req);\r\n const headers = new HttpHeaders(request.headers);\r\n const params = new HttpParams(); // Probably some way to make this a one-liner, but alas, there are no good docs\r\n for (const parameter in request.params) {\r\n request.params[parameter].forEach((paramValue: string) => params.append(parameter, paramValue));\r\n }\r\n return new HttpRequest(request.method, request.url, request.body, {\r\n headers,\r\n params,\r\n responseType: request.responseType,\r\n withCredentials: request.withCredentials\r\n });\r\n}\r\n\r\nexport const deserializeResponse = <T = any>(res: string): HttpResponse<T> => {\r\n const response = JSON.parse(res);\r\n return new HttpResponse<T>({\r\n url: response.url,\r\n headers: new HttpHeaders(response.headers),\r\n body: response.body,\r\n status: response.status,\r\n statusText: response.statusText,\r\n });\r\n}\r\n\r\nexport class NgHttpCachingBrowserStorage implements NgHttpCachingStorageInterface {\r\n\r\n constructor(private storage: Storage) { }\r\n\r\n get size(): number {\r\n let count = 0;\r\n for (let i = 0, e = this.storage.length; i < e; i++) {\r\n const key = this.storage.key(i);\r\n if (key && key.startsWith(KEY_PREFIX)) {\r\n count++;\r\n }\r\n }\r\n return count;\r\n }\r\n\r\n clear(): void {\r\n for (let i = this.storage.length; i >= 0; i--) {\r\n const key = this.storage.key(i);\r\n if (key && key.startsWith(KEY_PREFIX)) {\r\n this.storage.removeItem(key);\r\n }\r\n }\r\n }\r\n\r\n delete(key: string): boolean {\r\n if (!key) {\r\n return false;\r\n }\r\n if (!key.startsWith(KEY_PREFIX)) {\r\n key = KEY_PREFIX + key;\r\n }\r\n this.storage.removeItem(key);\r\n return true;\r\n }\r\n\r\n forEach(callbackfn: (value: NgHttpCachingEntry, key: string) => void): void {\r\n // iterate this.storage\r\n for (let i = 0, e = this.storage.length; i < e; i++) {\r\n const keyWithPrefix = this.storage.key(i);\r\n if (keyWithPrefix && keyWithPrefix.startsWith(KEY_PREFIX)) {\r\n const value = this.get(keyWithPrefix);\r\n if (value) {\r\n const keyWithoutPrefix = keyWithPrefix.substring(KEY_PREFIX.length);\r\n callbackfn(value, keyWithoutPrefix);\r\n }\r\n }\r\n }\r\n }\r\n\r\n get(key: string): Readonly<NgHttpCachingEntry> | undefined {\r\n if (!key) {\r\n return undefined;\r\n }\r\n if (!key.startsWith(KEY_PREFIX)) {\r\n key = KEY_PREFIX + key;\r\n }\r\n const item = this.storage.getItem(key);\r\n if (item) {\r\n const parsedItem: NgHttpCachingStorageEntry = JSON.parse(item);\r\n return this.deserialize(parsedItem);\r\n }\r\n return undefined;\r\n }\r\n\r\n has(key: string): boolean {\r\n if (!key) {\r\n return false;\r\n }\r\n if (!key.startsWith(KEY_PREFIX)) {\r\n key = KEY_PREFIX + key;\r\n }\r\n return !!this.storage.getItem(key);\r\n }\r\n\r\n set(key: string, value: NgHttpCachingEntry): void {\r\n if (!key) {\r\n return;\r\n }\r\n if (!key.startsWith(KEY_PREFIX)) {\r\n key = KEY_PREFIX + key;\r\n }\r\n const unParsedItem: NgHttpCachingStorageEntry = this.serialize(value);\r\n this.storage.setItem(key, JSON.stringify(unParsedItem));\r\n }\r\n\r\n protected serialize(value: NgHttpCachingEntry): NgHttpCachingStorageEntry {\r\n return {\r\n url: value.url,\r\n response: serializeResponse(value.response),\r\n request: serializeRequest(value.request),\r\n addedTime: value.addedTime,\r\n version: value.version\r\n };\r\n }\r\n\r\n protected deserialize(value: NgHttpCachingStorageEntry): NgHttpCachingEntry {\r\n return {\r\n url: value.url,\r\n response: deserializeResponse(value.response),\r\n request: deserializeRequest(value.request),\r\n addedTime: value.addedTime,\r\n version: value.version\r\n };\r\n }\r\n}\r\n\r\n","import { NgHttpCachingBrowserStorage } from './ng-http-caching-browser-storage';\r\n\r\nexport class NgHttpCachingLocalStorage extends NgHttpCachingBrowserStorage {\r\n\r\n constructor() {\r\n super(localStorage);\r\n }\r\n}\r\n\r\nexport const withNgHttpCachingLocalStorage = () => new NgHttpCachingLocalStorage();","import { NgHttpCachingBrowserStorage } from './ng-http-caching-browser-storage';\r\n\r\nexport class NgHttpCachingSessionStorage extends NgHttpCachingBrowserStorage {\r\n\r\n constructor() {\r\n super(sessionStorage);\r\n }\r\n}\r\n\r\nexport const withNgHttpCachingSessionStorage = () => new NgHttpCachingSessionStorage();","/*\r\n * Public API Surface of ng-http-caching\r\n */\r\nexport * from './lib/ng-http-caching-interceptor.service';\r\nexport * from './lib/ng-http-caching.service';\r\nexport * from './lib/ng-http-caching.module';\r\nexport * from './lib/ng-http-caching-provider';\r\nexport * from './lib/storage/ng-http-caching-storage.interface';\r\nexport * from './lib/storage/ng-http-caching-memory-storage';\r\nexport * from './lib/storage/ng-http-caching-local-storage';\r\nexport * from './lib/storage/ng-http-caching-session-storage';\r\nexport * from './lib/storage/ng-http-caching-browser-storage';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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