diff --git a/src/utils/request.ts b/src/utils/request.ts index f5293a8..56fcf09 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -30,13 +30,7 @@ export function parseUrl(request: Request): URL | undefined { } export function parseConditionalHeaders(headers: Headers): ConditionalHeaders { - const ifModifiedSince = headers.has('if-modified-since') - ? new Date(headers.get('if-modified-since')!) - : undefined; - - if (ifModifiedSince instanceof Date) { - ifModifiedSince.setSeconds(ifModifiedSince.getSeconds() + 1); - } + const ifModifiedSince = getDateFromHeader(headers.get('if-modified-since')); const ifMatch = headers.has('if-match') ? headers.get('if-match')!.replaceAll('"', '') @@ -46,9 +40,9 @@ export function parseConditionalHeaders(headers: Headers): ConditionalHeaders { ? headers.get('if-none-match')!.replaceAll('"', '') : undefined; - const ifUnmodifiedSince = headers.has('if-unmodified-since') - ? new Date(headers.get('if-unmodified-since')!) - : undefined; + const ifUnmodifiedSince = getDateFromHeader( + headers.get('if-unmodified-since') + ); const range = headers.has('range') ? parseRangeHeader(headers.get('range')!) @@ -63,6 +57,15 @@ export function parseConditionalHeaders(headers: Headers): ConditionalHeaders { }; } +function getDateFromHeader(dateString: string | null): Date | undefined { + if (dateString === null) { + return undefined; + } + + const date = new Date(dateString); + return !isNaN(date.getTime()) ? date : undefined; +} + /** * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range * @returns undefined if header is invalid diff --git a/tests/e2e/file.test.ts b/tests/e2e/file.test.ts index 64ea892..9a5fb40 100644 --- a/tests/e2e/file.test.ts +++ b/tests/e2e/file.test.ts @@ -78,11 +78,14 @@ describe('File Tests', () => { assert.strictEqual(res.status, 200); assert.strictEqual(res.headers.has('last-modified'), true); + const date = new Date(res.headers.get('last-modified')!); + date.setSeconds(date.getSeconds() + 1); + // Make sure it returns a 304 when If-Modified-Since // >= file last modified res = await mf.dispatchFetch(`${url}dist/index.json`, { headers: { - 'if-modified-since': res.headers.get('last-modified')!, + 'if-modified-since': date.toUTCString(), }, }); assert.strictEqual(res.status, 304); diff --git a/tests/unit/utils/request.test.ts b/tests/unit/utils/request.test.ts index bab0398..dba7372 100644 --- a/tests/unit/utils/request.test.ts +++ b/tests/unit/utils/request.test.ts @@ -1,6 +1,9 @@ import assert from 'node:assert'; import { describe, it } from 'node:test'; -import { parseRangeHeader } from '../../../src/utils/request'; +import { + parseConditionalHeaders, + parseRangeHeader, +} from '../../../src/utils/request'; describe('parseRangeHeader', () => { it('`bytes=0-10`', () => { @@ -49,3 +52,20 @@ describe('parseRangeHeader', () => { assert.strictEqual(result, undefined); }); }); + +describe('parseConditionalHeaders', () => { + it('invalid dates', () => { + const headers = new Headers({ + 'if-modified-since': 'asd', + 'if-unmodified-since': 'asd', + }); + + assert.deepStrictEqual(parseConditionalHeaders(headers), { + ifMatch: undefined, + ifNoneMatch: undefined, + ifModifiedSince: undefined, + ifUnmodifiedSince: undefined, + range: undefined, + }); + }); +});