fix(service-worker): cache opaque responses in data groups with freshness strategy (#30977)

Previously, (presummably due to a typo) the `okToCacheOpaque` argument
of `DataGroup#cacheResponse()` was essentially never taken into account
(since opaque responses have a non-200 status code and thus `res.ok` is
always false).

This commit fixes the typo, which allows opaque responses to be cached
when `okToCacheOpaque` is true (i.e. in data groups using the
`freshness` strategy).

Fixes #30968

PR Close #30977
This commit is contained in:
George Kalpakas
2019-06-24 15:04:13 +03:00
committed by Alex Rickabaugh
parent 2d38623974
commit d7be38f84b
2 changed files with 32 additions and 5 deletions

View File

@ -481,10 +481,10 @@ export class DataGroup {
* If the request times out on the server, an error will be returned but the real network * If the request times out on the server, an error will be returned but the real network
* request will still be running in the background, to be cached when it completes. * request will still be running in the background, to be cached when it completes.
*/ */
private async cacheResponse( private async cacheResponse(req: Request, res: Response, lru: LruList, okToCacheOpaque = false):
req: Request, res: Response, lru: LruList, okToCacheOpaque: boolean = false): Promise<void> { Promise<void> {
// Only cache successful responses. // Only cache successful responses.
if (!res.ok || (okToCacheOpaque && res.type === 'opaque')) { if (!(res.ok || (okToCacheOpaque && res.type === 'opaque'))) {
return; return;
} }

View File

@ -150,6 +150,14 @@ import {SwTestHarness, SwTestHarnessBuilder} from '../testing/scope';
server.assertNoOtherRequests(); server.assertNoOtherRequests();
}); });
it('does not cache opaque responses', async() => {
expect(await makeNoCorsRequest(scope, '/api/test')).toBe('');
server.assertSawRequestFor('/api/test');
expect(await makeNoCorsRequest(scope, '/api/test')).toBe('');
server.assertSawRequestFor('/api/test');
});
it('refreshes after awhile', async() => { it('refreshes after awhile', async() => {
expect(await makeRequest(scope, '/api/test')).toEqual('version 1'); expect(await makeRequest(scope, '/api/test')).toEqual('version 1');
server.clearRequests(); server.clearRequests();
@ -199,6 +207,16 @@ import {SwTestHarness, SwTestHarnessBuilder} from '../testing/scope';
serverUpdate.assertNoOtherRequests(); serverUpdate.assertNoOtherRequests();
}); });
it('caches opaque responses', async() => {
expect(await makeNoCorsRequest(scope, '/fresh/data')).toBe('');
server.assertSawRequestFor('/fresh/data');
server.online = false;
expect(await makeRequest(scope, '/fresh/data')).toBe('');
server.assertNoOtherRequests();
});
it('falls back on the cache when server times out', async() => { it('falls back on the cache when server times out', async() => {
expect(await makeRequest(scope, '/fresh/data')).toEqual('this is fresh data'); expect(await makeRequest(scope, '/fresh/data')).toEqual('this is fresh data');
server.assertSawRequestFor('/fresh/data'); server.assertSawRequestFor('/fresh/data');
@ -250,9 +268,18 @@ function makeRequest(scope: SwTestHarness, url: string, clientId?: string): Prom
return done.then(() => resTextPromise); return done.then(() => resTextPromise);
} }
function makeNoCorsRequest(
scope: SwTestHarness, url: string, clientId?: string): Promise<String|null> {
const req = new MockRequest(url, {mode: 'no-cors'});
const [resTextPromise, done] = makePendingRequest(scope, req, clientId);
return done.then(() => resTextPromise);
}
function makePendingRequest( function makePendingRequest(
scope: SwTestHarness, url: string, clientId?: string): [Promise<string|null>, Promise<void>] { scope: SwTestHarness, urlOrReq: string | MockRequest,
const [resPromise, done] = scope.handleFetch(new MockRequest(url), clientId || 'default'); clientId?: string): [Promise<string|null>, Promise<void>] {
const req = (typeof urlOrReq === 'string') ? new MockRequest(urlOrReq) : urlOrReq;
const [resPromise, done] = scope.handleFetch(req, clientId || 'default');
return [ return [
resPromise.then<string|null>(res => res ? res.text() : null), resPromise.then<string|null>(res => res ? res.text() : null),
done, done,