fix(ajax): return cached status and headers

This commit is contained in:
Lars den Bakker 2021-03-31 20:16:05 +02:00
parent c1a81fe4cc
commit 468223a09f
4 changed files with 47 additions and 19 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ajax': patch
---
return cached status and headers

View file

@ -157,9 +157,9 @@ In the example below, we do not allow you to write digits.
```js preview-story ```js preview-story
export const preprocessors = () => { export const preprocessors = () => {
const preprocess = (value) => { const preprocess = value => {
return value.replace(/[0-9]/g, ''); return value.replace(/[0-9]/g, '');
} };
return html` return html`
<lion-input <lion-input
label="Date Example" label="Date Example"

View file

@ -16,11 +16,14 @@ class Cache {
this.cacheConfig = {}; this.cacheConfig = {};
/** /**
* @type {{[url: string]: {expires: number, data: object} }} * @type {{[url: string]: {expires: number, response: CacheResponse} }}
* @protected * @private
*/ */
this._cacheObject = {}; this._cacheObject = {};
/** @type {{ [url: string]: { promise: Promise<void>, resolve: (v?: any) => void } }} */ /**
* @type {{ [url: string]: { promise: Promise<void>, resolve: (v?: any) => void } }}
* @private
*/
this._pendingRequests = {}; this._pendingRequests = {};
} }
@ -55,13 +58,13 @@ class Cache {
/** /**
* Store an item in the cache * Store an item in the cache
* @param {string} url key by which the cache is stored * @param {string} url key by which the cache is stored
* @param {object} data the cached object * @param {Response} response the cached response
*/ */
set(url, data) { set(url, response) {
this._validateCache(); this._validateCache();
this._cacheObject[url] = { this._cacheObject[url] = {
expires: new Date().getTime(), expires: new Date().getTime(),
data, response,
}; };
} }
@ -69,6 +72,7 @@ class Cache {
* Retrieve an item from the cache * Retrieve an item from the cache
* @param {string} url key by which the cache is stored * @param {string} url key by which the cache is stored
* @param {number} timeToLive maximum time to allow cache to live * @param {number} timeToLive maximum time to allow cache to live
* @returns {CacheResponse | false}
*/ */
get(url, timeToLive) { get(url, timeToLive) {
this._validateCache(); this._validateCache();
@ -82,7 +86,7 @@ class Cache {
if (timeToLive !== null && cacheAge > timeToLive) { if (timeToLive !== null && cacheAge > timeToLive) {
return false; return false;
} }
return cacheResult.data; return cacheResult.response;
} }
/** /**
@ -260,7 +264,7 @@ export const cacheRequestInterceptorFactory = (getCacheIdentifier, globalCacheOp
const validatedInitialCacheOptions = validateOptions(globalCacheOptions); const validatedInitialCacheOptions = validateOptions(globalCacheOptions);
return /** @param {CacheRequest} cacheRequest */ async cacheRequest => { return /** @param {CacheRequest} cacheRequest */ async cacheRequest => {
const { method, status, statusText, headers } = cacheRequest; const { method } = cacheRequest;
const cacheOptions = composeCacheOptions( const cacheOptions = composeCacheOptions(
validatedInitialCacheOptions, validatedInitialCacheOptions,
@ -311,13 +315,7 @@ export const cacheRequestInterceptorFactory = (getCacheIdentifier, globalCacheOp
cacheRequest.cacheOptions = { useCache: false }; cacheRequest.cacheOptions = { useCache: false };
} }
const init = /** @type {LionRequestInit} */ ({ const response = /** @type {CacheResponse} */ cacheResponse.clone();
status,
statusText,
headers,
});
const response = /** @type {CacheResponse} */ (new Response(cacheResponse, init));
response.request = cacheRequest; response.request = cacheRequest;
response.fromCache = true; response.fromCache = true;
return response; return response;
@ -373,8 +371,7 @@ export const cacheResponseInterceptorFactory = (getCacheIdentifier, globalCacheO
cacheOptions.methods.indexOf(cacheResponse.request.method.toLowerCase()) > -1 cacheOptions.methods.indexOf(cacheResponse.request.method.toLowerCase()) > -1
) { ) {
// store the response data in the cache and mark request as resolved // store the response data in the cache and mark request as resolved
const responseBody = await cacheResponse.clone().text(); currentCache.set(cacheId, cacheResponse.clone());
currentCache.set(cacheId, responseBody);
} }
currentCache.resolvePendingRequest(cacheId); currentCache.resolvePendingRequest(cacheId);

View file

@ -491,5 +491,31 @@ describe('ajax cache', () => {
ajaxRequestSpy.restore(); ajaxRequestSpy.restore();
removeCacheInterceptors(ajax, indexes); removeCacheInterceptors(ajax, indexes);
}); });
it('preserves status and headers when returning cached response', async () => {
newCacheId();
fetchStub.returns(
Promise.resolve(
new Response('mock response', { status: 206, headers: { 'x-foo': 'x-bar' } }),
),
);
const indexes = addCacheInterceptors(ajax, {
useCache: true,
timeToLive: 100,
});
const ajaxRequestSpy = spy(ajax, 'request');
const response1 = await ajax.request('/test');
const response2 = await ajax.request('/test');
expect(fetchStub.callCount).to.equal(1);
expect(response1.status).to.equal(206);
expect(response1.headers.get('x-foo')).to.equal('x-bar');
expect(response2.status).to.equal(206);
expect(response2.headers.get('x-foo')).to.equal('x-bar');
ajaxRequestSpy.restore();
removeCacheInterceptors(ajax, indexes);
});
}); });
}); });