fix: support max-stale on header interpreter (#543)

This commit is contained in:
arthurfiorette 2023-06-09 13:04:29 -03:00
parent 82182bf7f8
commit 683dbe0f22
No known key found for this signature in database
GPG Key ID: 9D190CD53C53C555
5 changed files with 53 additions and 10 deletions

View File

@ -8,7 +8,7 @@ export const defaultHeaderInterpreter: HeaderInterpreter = (headers) => {
const cacheControl: unknown = headers[Header.CacheControl];
if (cacheControl) {
const { noCache, noStore, maxAge, immutable, staleWhileRevalidate } = parse(
const { noCache, noStore, maxAge, maxStale, immutable, staleWhileRevalidate } = parse(
String(cacheControl)
);
@ -19,7 +19,8 @@ export const defaultHeaderInterpreter: HeaderInterpreter = (headers) => {
if (immutable) {
// 1 year is sufficient, as Infinity may cause problems with certain storages.
// It might not be the best way, but a year is better than none.
// It might not be the best way, but a year is better than none. Facebook shows
// that a browser session stays at the most 1 month.
return {
cache: 1000 * 60 * 60 * 24 * 365
};
@ -33,8 +34,18 @@ export const defaultHeaderInterpreter: HeaderInterpreter = (headers) => {
? // If age is present, we must subtract it from maxAge
(maxAge - Number(age)) * 1000
: maxAge * 1000,
// Already out of date, for cache can be saved, but must be requested again
stale: staleWhileRevalidate !== undefined ? staleWhileRevalidate * 1000 : 0
// Already out of date, must be requested again
stale:
// I couldn't find any documentation about who should be used, as they
// are not meant to overlap each other. But, as we cannot request in the
// background, as the stale-while-revalidate says, and we just increase
// its staleTtl when its present, max-stale is being preferred over
// stale-while-revalidate.
maxStale !== undefined
? maxStale * 1000
: staleWhileRevalidate !== undefined
? staleWhileRevalidate * 1000
: undefined
};
}
}

View File

@ -196,6 +196,7 @@ export function defaultRequestInterceptor(axios: AxiosCacheInstance) {
}
// Hydrates any UI temporarily, if cache is available
/* istanbul ignore if 'really hard to test' */
if (cache.data) {
await config.cache.hydrate?.(cache);
}

View File

@ -28,7 +28,7 @@ describe('test Cache-Control header', () => {
});
// 10 Seconds in milliseconds
expect(result).toEqual({ cache: 10 * 1000, stale: 0 });
expect(result).toEqual({ cache: 10 * 1000, stale: undefined });
});
it('tests with max-age of 0', () => {
@ -36,7 +36,7 @@ describe('test Cache-Control header', () => {
[Header.CacheControl]: 'max-age=0'
});
expect(result).toEqual({ cache: 0, stale: 0 });
expect(result).toEqual({ cache: 0, stale:undefined });
});
it('tests stale values with age', () => {

View File

@ -23,7 +23,7 @@ describe('tests header interpreter', () => {
[Header.Age]: '3'
});
expect(result).toEqual({ cache: 7 * 1000, stale: 0 });
expect(result).toEqual({ cache: 7 * 1000, stale: undefined });
});
it('tests with expires and cache-control present', () => {
@ -34,7 +34,7 @@ describe('tests header interpreter', () => {
// expires should be ignored
// 10 Seconds in milliseconds
expect(result).toEqual({ cache: 10 * 1000, stale: 0 });
expect(result).toEqual({ cache: 10 * 1000, stale: undefined });
});
it('tests with immutable', () => {
@ -75,4 +75,34 @@ describe('tests header interpreter', () => {
expect(result.cached).toBe(true);
});
it('tests header interpreter stale with staleWhileRevalidate and maxStale', () => {
// only staleWhileRevalidate
expect(
defaultHeaderInterpreter({
[Header.CacheControl]: 'max-age=10, stale-while-revalidate=5'
})
).toEqual({ cache: 10 * 1000, stale: 5 * 1000 });
// only maxStale
expect(
defaultHeaderInterpreter({
[Header.CacheControl]: 'max-age=10, max-stale=4'
})
).toEqual({ cache: 10 * 1000, stale: 4 * 1000 });
// both should use max-stale
expect(
defaultHeaderInterpreter({
[Header.CacheControl]: 'max-age=10, stale-while-revalidate=5, max-stale=4'
})
).toEqual({ cache: 10 * 1000, stale: 4 * 1000 });
// none should return undefined
expect(
defaultHeaderInterpreter({
[Header.CacheControl]: 'max-age=10'
})
).toEqual({ cache: 10 * 1000, stale: undefined });
});
});

View File

@ -19,6 +19,7 @@ export function mockAxios(
const should304: unknown =
config.headers?.[Header.IfNoneMatch] || config.headers?.[Header.IfModifiedSince];
const status = should304 ? 304 : 200;
const statusText = should304 ? '304 Not Modified' : '200 OK';
if (config.validateStatus?.(status) === false) {
throw {
@ -28,7 +29,7 @@ export function mockAxios(
response: {
data: true,
status,
statusText: should304 ? '304 Not Modified' : '200 OK',
statusText,
headers: {
...responseHeaders,
// Random header for every request made
@ -43,7 +44,7 @@ export function mockAxios(
return {
data: true,
status,
statusText: should304 ? '304 Not Modified' : '200 OK',
statusText,
headers: {
...responseHeaders,
// Random header for every request made