fix(ajax): return cached status and headers
This commit is contained in:
parent
c1a81fe4cc
commit
468223a09f
4 changed files with 47 additions and 19 deletions
5
.changeset/lucky-games-poke.md
Normal file
5
.changeset/lucky-games-poke.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@lion/ajax': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
return cached status and headers
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue