Skip to content

Commit de053a3

Browse files
nab0y4enkogithub-actions[bot]
authored andcommitted
Use lowercase header names when reading expiry (h/t @nab0y4enko) (#13626)
GitOrigin-RevId: ac9bf77bfb3f16446ecdd8f16e293f8dedc0ed08
1 parent 8f59665 commit de053a3

5 files changed

Lines changed: 78 additions & 14 deletions

File tree

src/util/tile_request_cache.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export function cachePut(request: Request, response: Response, requestTime: numb
6060
cacheOpen();
6161
if (sharedCache == null) return;
6262

63-
const cacheControl = parseCacheControl(response.headers.get('Cache-Control') || '');
63+
const cacheControl = parseCacheControl(response.headers.get('cache-control') || '');
6464
if (cacheControl['no-store']) return;
6565

6666
const options: ResponseOptions = {
@@ -75,7 +75,7 @@ export function cachePut(request: Request, response: Response, requestTime: numb
7575
options.headers.set('Expires', new Date(requestTime + cacheControl['max-age'] * 1000).toUTCString());
7676
}
7777

78-
const expires = options.headers.get('Expires');
78+
const expires = options.headers.get('expires');
7979
if (!expires) return;
8080

8181
const timeUntilExpiry = new Date(expires).getTime() - requestTime;
@@ -137,8 +137,8 @@ export function cacheGet(
137137

138138
function isFresh(response: Response) {
139139
if (!response) return false;
140-
const expires = new Date(response.headers.get('Expires') || 0);
141-
const cacheControl = parseCacheControl(response.headers.get('Cache-Control') || '');
140+
const expires = new Date(response.headers.get('expires') || 0);
141+
const cacheControl = parseCacheControl(response.headers.get('cache-control') || '');
142142
return Number(expires) > Date.now() && !cacheControl['no-cache'];
143143
}
144144

src/util/util.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,8 +668,8 @@ export function parseCacheControl(cacheControl: string): Record<string, number>
668668

669669
export function getExpiryDataFromHeaders(responseHeaders: Headers | Map<string, string> | undefined) {
670670
if (!responseHeaders) return {cacheControl: undefined, expires: undefined};
671-
const cacheControl = responseHeaders.get('Cache-Control');
672-
const expires = responseHeaders.get('Expires');
671+
const cacheControl = responseHeaders.get('cache-control');
672+
const expires = responseHeaders.get('expires');
673673
return {cacheControl, expires};
674674
}
675675

test/unit/source/vector_tile_worker_source.test.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ import VectorTileWorkerSource from '../../../src/source/vector_tile_worker_sourc
77
import StyleLayerIndex from '../../../src/style/style_layer_index';
88
import perf from '../../../src/util/performance';
99
import {getProjection} from '../../../src/geo/projection/index';
10-
import rawTileData from '../../fixtures/mbsv5-6-18-23.vector.pbf?arraybuffer';
10+
import rawTileDataImport from '../../fixtures/mbsv5-6-18-23.vector.pbf?arraybuffer';
1111

12+
import type {LoadVectorDataCallback} from '../../../src/source/load_vector_tile';
13+
14+
const rawTileData = rawTileDataImport as ArrayBuffer;
1215
const actor = {send: () => {}};
1316

1417
test('VectorTileWorkerSource#abortTile aborts pending request', () => {
@@ -202,13 +205,45 @@ test('VectorTileWorkerSource#reloadTile does not reparse tiles with no vectorTil
202205
expect(callback).toHaveBeenCalledTimes(1);
203206
});
204207

208+
test('VectorTileWorkerSource#loadTile forwards cache headers from response headers Map', () => {
209+
const headers = new Headers();
210+
headers.set('Cache-Control', 'max-age=30');
211+
headers.set('Expires', 'Thu, 01 Jan 2099 00:00:00 GMT');
212+
213+
function loadVectorData(params, callback: LoadVectorDataCallback) {
214+
return callback(null, {
215+
vectorTile: new VectorTile(new Protobuf(rawTileData)),
216+
rawData: rawTileData,
217+
responseHeaders: new Map(headers.entries())
218+
});
219+
}
220+
221+
const layerIndex = new StyleLayerIndex([{
222+
id: 'test',
223+
source: 'source',
224+
'source-layer': 'test',
225+
type: 'fill'
226+
}]);
227+
228+
const source = new VectorTileWorkerSource(actor, layerIndex, [], [], true, loadVectorData);
229+
230+
source.loadTile({
231+
source: 'source',
232+
uid: 0,
233+
tileID: {overscaledZ: 0, wrap: 0, canonical: {x: 0, y: 0, z: 0, w: 0}},
234+
projection: getProjection({name: 'mercator'}),
235+
request: {url: 'http://localhost:2900/faketile.pbf'}
236+
}, (err, res) => {
237+
expect(err).toBeFalsy();
238+
expect(res.cacheControl).toBe('max-age=30');
239+
expect(res.expires).toBe('Thu, 01 Jan 2099 00:00:00 GMT');
240+
});
241+
});
242+
205243
test('VectorTileWorkerSource provides resource timing information', () => {
206-
function loadVectorData(params, callback) {
207-
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
244+
function loadVectorData(params, callback: LoadVectorDataCallback) {
208245
return callback(null, {
209-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
210246
vectorTile: new VectorTile(new Protobuf(rawTileData)),
211-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
212247
rawData: rawTileData,
213248
cacheControl: null,
214249
expires: null

test/unit/util/tile_request_cache.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ describe('tile_request_cache', () => {
6060
const cachedResponse = {
6161
headers: {get: vi.fn().mockImplementation((name) => {
6262
switch (name) {
63-
case 'Expires':
63+
case 'expires':
6464
return '2300-01-01';
65-
case 'Cache-Control':
65+
case 'cache-control':
6666
return null;
6767
}
6868
})},

test/unit/util/util.test.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// @ts-nocheck
33
import Point from '@mapbox/point-geometry';
44
import {describe, test, expect} from '../../util/vitest';
5-
import {mapValue, degToRad, radToDeg, easeCubicInOut, getAABBPointSquareDist, furthestTileCorner, keysDifference, pick, uniqueId, bindAll, asyncAll, clamp, smoothstep, wrap, bezier, mapObject, filterObject, deepEqual, clone, arraysIntersect, isCounterClockwise, parseCacheControl, uuid, validateUuid, nextPowerOfTwo, isPowerOfTwo, bufferConvexPolygon, prevPowerOfTwo, shortestAngle, _resetSafariCheckForTest, isSafariWithAntialiasingBug} from '../../../src/util/util';
5+
import {mapValue, degToRad, radToDeg, easeCubicInOut, getAABBPointSquareDist, furthestTileCorner, keysDifference, pick, uniqueId, bindAll, asyncAll, clamp, smoothstep, wrap, bezier, mapObject, filterObject, deepEqual, clone, arraysIntersect, isCounterClockwise, parseCacheControl, getExpiryDataFromHeaders, uuid, validateUuid, nextPowerOfTwo, isPowerOfTwo, bufferConvexPolygon, prevPowerOfTwo, shortestAngle, _resetSafariCheckForTest, isSafariWithAntialiasingBug} from '../../../src/util/util';
66

77
const EPSILON = 1e-8;
88

@@ -368,6 +368,35 @@ describe('util', () => {
368368
});
369369
});
370370

371+
describe('getExpiryDataFromHeaders', () => {
372+
test('returns undefined values when responseHeaders is undefined', () => {
373+
expect(getExpiryDataFromHeaders(undefined)).toEqual({
374+
cacheControl: undefined,
375+
expires: undefined
376+
});
377+
});
378+
379+
test('reads cache headers from a Fetch API Headers object', () => {
380+
const headers = new Headers();
381+
headers.set('Cache-Control', 'max-age=60');
382+
headers.set('Expires', 'Thu, 01 Jan 2099 00:00:00 GMT');
383+
384+
const result = getExpiryDataFromHeaders(headers);
385+
expect(result.cacheControl).toBe('max-age=60');
386+
expect(result.expires).toBe('Thu, 01 Jan 2099 00:00:00 GMT');
387+
});
388+
389+
test('reads cache headers from a Map serialized via Headers.entries()', () => {
390+
const headers = new Headers();
391+
headers.set('Cache-Control', 'max-age=30');
392+
headers.set('Expires', 'Thu, 01 Jan 2099 00:00:00 GMT');
393+
394+
const result = getExpiryDataFromHeaders(new Map(headers.entries()));
395+
expect(result.cacheControl).toBe('max-age=30');
396+
expect(result.expires).toBe('Thu, 01 Jan 2099 00:00:00 GMT');
397+
});
398+
});
399+
371400
test('validateUuid', () => {
372401
expect(validateUuid(uuid())).toBeTruthy();
373402
expect(validateUuid(uuid().substr(0, 10))).toBeFalsy();

0 commit comments

Comments
 (0)