refactor: externalized the header interceptor

This commit is contained in:
Hazork 2021-09-11 10:21:53 -03:00
parent 2c49a49a63
commit ce2b7ecb4b
6 changed files with 50 additions and 5 deletions

View File

@ -2,8 +2,9 @@ import { AxiosInstance } from 'axios';
import { applyRequestInterceptor } from '../interceptors/request';
import { applyResponseInterceptor } from '../interceptors/response';
import { MemoryStorage } from '../storage/memory';
import { defaultHeaderInterpreter } from '../header';
import { defaultKeyGenerator } from '../util/key-generator';
import { AxiosCacheInstance, CacheInstance, CacheProperties } from './types';
import CacheInstance, { AxiosCacheInstance, CacheProperties } from './types';
export function createCache(
axios: AxiosInstance,
@ -14,7 +15,8 @@ export function createCache(
axiosCache.storage = options.storage || new MemoryStorage();
axiosCache.generateKey = options.generateKey || defaultKeyGenerator;
axiosCache.waiting = options.waiting || {};
axiosCache.interpretHeader = options.interpretHeader || defaultHeaderInterpreter;
// CacheRequestConfig values
axiosCache.defaults = {
...axios.defaults,

View File

@ -7,6 +7,7 @@ import type {
Method
} from 'axios';
import { Deferred } from 'src/util/deferred';
import { HeaderInterpreter } from '../header';
import { CachedResponse, CacheStorage } from '../storage/types';
export type DefaultCacheRequestConfig = AxiosRequestConfig & {
@ -78,7 +79,7 @@ export type CacheRequestConfig = AxiosRequestConfig & {
cache?: Partial<CacheProperties>;
};
export interface CacheInstance {
export default interface CacheInstance {
/**
* The storage to save the cache data.
*
@ -97,6 +98,12 @@ export interface CacheInstance {
* A simple object that holds all deferred objects until it is resolved.
*/
waiting: Record<string, Deferred<CachedResponse>>;
/**
* The function to parse and interpret response headers.
* Only used if cache.interpretHeader is true.
*/
interpretHeader: HeaderInterpreter;
}
/**

2
src/header/index.ts Normal file
View File

@ -0,0 +1,2 @@
export * from './interpreter';
export * from './types';

23
src/header/interpreter.ts Normal file
View File

@ -0,0 +1,23 @@
import { parse } from '@tusbar/cache-control';
import { HeaderInterpreter } from './types';
export const defaultHeaderInterpreter: HeaderInterpreter = (headers) => {
const cacheControl = headers?.['cache-control'];
if (!cacheControl) {
return undefined;
}
const { noCache, noStore, maxAge } = parse(cacheControl);
// Header told that this response should not be cached.
if (noCache || noStore) {
return false;
}
if (!maxAge) {
return undefined;
}
return Date.now() + maxAge * 1000;
};

12
src/header/types.ts Normal file
View File

@ -0,0 +1,12 @@
/**
* Interpret the cache control header, if present.
*
* @param header the header object to interpret.
*
* @returns `false` if cache should not be used. `undefined` when provided
* headers was not enough to determine a valid value. Or a `number` containing
* the number of **seconds** to cache the response.
*/
export type HeaderInterpreter = (
headers: Record<string, string> | undefined
) => false | undefined | number;

View File

@ -1,5 +1,4 @@
import { AxiosCacheInstance } from '../axios/types';
import { interpretCacheHeader } from './util/interpret-header';
import { updateCache } from '../util/update-cache';
export function applyResponseInterceptor(axios: AxiosCacheInstance) {
@ -28,7 +27,7 @@ export function applyResponseInterceptor(axios: AxiosCacheInstance) {
let shouldCache = true;
if (response.config.cache?.interpretHeader) {
const expirationTime = interpretCacheHeader(response.headers['cache-control']);
const expirationTime = axios.interpretHeader(response.headers['cache-control']);
// Header told that this response should not be cached.
if (expirationTime === false) {