diff --git a/src/axios/cache.ts b/src/axios/cache.ts index 3387ab50..4a9d633b 100644 --- a/src/axios/cache.ts +++ b/src/axios/cache.ts @@ -24,7 +24,7 @@ export function createCache( maxAge: 1000 * 60 * 5, interpretHeader: false, methods: ['get'], - shouldCache: ({ status }) => status >= 200 && status < 300, + cachePredicate: ({ status }) => status >= 200 && status < 300, update: {}, ...options } diff --git a/src/axios/types.ts b/src/axios/types.ts index 62e64218..c90aa5f4 100644 --- a/src/axios/types.ts +++ b/src/axios/types.ts @@ -10,6 +10,7 @@ import { Deferred } from 'src/util/deferred'; import { KeyGenerator } from 'src/util/key-generator'; import { HeaderInterpreter } from '../header'; import { CachedResponse, CacheStorage } from '../storage/types'; +import { CachePredicate } from '../util/cache-predicate'; export type DefaultCacheRequestConfig = AxiosRequestConfig & { cache: CacheProperties; @@ -43,7 +44,7 @@ export type CacheProperties = { * * @default ({ status }) => status >= 200 && status < 300 */ - shouldCache: (response: AxiosResponse) => boolean; + cachePredicate: CachePredicate; /** * Once the request is resolved, this specifies what requests should we change the cache. diff --git a/src/interceptors/response.ts b/src/interceptors/response.ts index 54d9b325..ec8cc8b5 100644 --- a/src/interceptors/response.ts +++ b/src/interceptors/response.ts @@ -1,5 +1,6 @@ import { AxiosCacheInstance } from '../axios/types'; import { updateCache } from '../util/update-cache'; +import {checkPredicateObject} from '../util/cache-predicate' export function applyResponseInterceptor(axios: AxiosCacheInstance): void { axios.interceptors.response.use(async (response) => { @@ -8,11 +9,17 @@ export function applyResponseInterceptor(axios: AxiosCacheInstance): void { updateCache(axios, response.data, response.config.cache.update); } - const shouldCache = response.config.cache?.shouldCache || axios.defaults.cache.shouldCache; + const cachePredicate = response.config.cache?.cachePredicate || axios.defaults.cache.cachePredicate; // Config told that this response should be cached. - if (shouldCache(response)) { - return response; + if (typeof cachePredicate === 'function') { + if(!cachePredicate(response)) { + return response; + } + } else { + if(!checkPredicateObject(response, cachePredicate)) { + return response; + } } const key = axios.generateKey(response.config); diff --git a/src/util/cache-predicate.ts b/src/util/cache-predicate.ts new file mode 100644 index 00000000..3d1f691d --- /dev/null +++ b/src/util/cache-predicate.ts @@ -0,0 +1,63 @@ +import { AxiosResponse } from 'axios'; + +export type CachePredicate = CachePredicateObject | ((response: AxiosResponse) => boolean); + +export type CachePredicateObject = { + /** + * The status predicate, if a tuple is returned, + * the first and seconds value means the interval (inclusive) accepted. + * Can also be a function. + */ + statusCheck?: [start: number, end: number] | ((status: number) => boolean); + + /** + * Matches if the response header container all keys. A tuple also checks for values. + */ + containsHeaders?: (string | [string, string])[]; + + /** + * Check if the desired response matches this predicate. + */ + responseMatch?: (res: any | undefined) => boolean; +}; + +export function checkPredicateObject( + response: AxiosResponse, + { statusCheck, containsHeaders: containsHeader, responseMatch }: CachePredicateObject +): boolean { + if (statusCheck) { + if (typeof statusCheck === 'function') { + if (!statusCheck(response.status)) { + return false; + } + } else { + const [start, end] = statusCheck; + if (response.status <= start || response.status >= end) { + return false; + } + } + } + + if (containsHeader) { + for (const entry of containsHeader) { + if (typeof entry === 'string') { + if (!response.headers[entry]) { + return false; + } + } else { + const [key, value] = entry; + if (!response.headers[key] || response.headers[key] == value) { + return false; + } + } + } + } + + if (responseMatch) { + if (!responseMatch(response.data)) { + return false; + } + } + + return true; +}