@@ -110,6 +110,44 @@ function getExpirationTtl(
110110 }
111111}
112112
113+ // https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.1
114+ const utcDateRegexp =
115+ / ^ ( M o n | T u e | W e d | T h u | F r i | S a t | S u n ) , \d \d ( J a n | F e b | M a r | A p r | M a y | J u n | J u l | A u g | S e p | O c t | N o v | D e c ) \d \d \d \d \d \d : \d \d : \d \d G M T $ / ;
116+ function parseUTCDate ( value : string ) : number {
117+ return utcDateRegexp . test ( value ) ? Date . parse ( value ) : NaN ;
118+ }
119+
120+ function getMatchResponse (
121+ reqHeaders : Headers ,
122+ resStatus : number ,
123+ resHeaders : Headers ,
124+ resBody : Uint8Array
125+ ) : Response {
126+ // If `If-Modified-Since` is set, perform a conditional request
127+ const reqIfModifiedSinceHeader = reqHeaders . get ( "If-Modified-Since" ) ;
128+ const resLastModifiedHeader = resHeaders . get ( "Last-Modified" ) ;
129+ if ( reqIfModifiedSinceHeader !== null && resLastModifiedHeader !== null ) {
130+ const reqIfModifiedSince = parseUTCDate ( reqIfModifiedSinceHeader ) ;
131+ const resLastModified = parseUTCDate ( resLastModifiedHeader ) ;
132+ // Comparison of NaN's (invalid dates), will always result in `false`
133+ if ( resLastModified <= reqIfModifiedSince ) {
134+ return new Response ( null , {
135+ status : 304 , // Not Modified
136+ headers : resHeaders ,
137+ } ) ;
138+ }
139+ }
140+
141+ // If `Range` is set, return a partial response
142+ const reqRangeHeader = reqHeaders . get ( "Range" ) ;
143+ if ( reqRangeHeader !== null ) {
144+ return _getRangeResponse ( reqRangeHeader , resStatus , resHeaders , resBody ) ;
145+ }
146+
147+ // Otherwise, return the full response
148+ return new Response ( resBody , { status : resStatus , headers : resHeaders } ) ;
149+ }
150+
113151export interface InternalCacheOptions {
114152 formDataFiles ?: boolean ;
115153 clock ?: Clock ;
@@ -221,24 +259,12 @@ export class Cache implements CacheInterface {
221259
222260 // Returning a @miniflare /core Response so we don't need to convert
223261 // BaseResponse to one when dispatching fetch events
224- let res : Response ;
225- const rangeHeader = req . headers . get ( "Range" ) ;
226- if ( rangeHeader === null ) {
227- // If this wasn't a `Range` request, return the full response...
228- res = new Response ( cached . value , {
229- status : cached . metadata . status ,
230- headers,
231- } ) ;
232- } else {
233- // ...otherwise, return a partial response
234- res = _getRangeResponse (
235- rangeHeader ,
236- cached . metadata . status ,
237- headers ,
238- cached . value
239- ) ;
240- }
241-
262+ let res = getMatchResponse (
263+ req . headers ,
264+ cached . metadata . status ,
265+ headers ,
266+ cached . value
267+ ) ;
242268 if ( ! this . #formDataFiles) res = withStringFormDataFiles ( res ) ;
243269 return withImmutableHeaders ( res ) ;
244270 }
0 commit comments