@@ -139,7 +139,7 @@ fn load_lookup_options(
139139 memory : & wiggle:: GuestMemory < ' _ > ,
140140 mut options_mask : types:: CacheLookupOptionsMask ,
141141 options : wiggle:: GuestPtr < types:: CacheLookupOptions > ,
142- ) -> Result < HeaderMap , Error > {
142+ ) -> Result < ( HeaderMap , bool ) , Error > {
143143 let options = memory. read ( options) ?;
144144 let headers = if options_mask. contains ( types:: CacheLookupOptionsMask :: REQUEST_HEADERS ) {
145145 let handle = options. request_headers ;
@@ -158,11 +158,15 @@ fn load_lookup_options(
158158 } ) ;
159159 }
160160
161+ let always_use_requested_range =
162+ options_mask. contains ( types:: CacheLookupOptionsMask :: ALWAYS_USE_REQUESTED_RANGE ) ;
163+ options_mask &= !types:: CacheLookupOptionsMask :: ALWAYS_USE_REQUESTED_RANGE ;
164+
161165 if !options_mask. is_empty ( ) {
162166 return Err ( Error :: NotAvailable ( "unknown cache lookup option" ) ) ;
163167 }
164168
165- Ok ( headers)
169+ Ok ( ( headers, always_use_requested_range ) )
166170}
167171
168172#[ allow( unused_variables) ]
@@ -175,13 +179,17 @@ impl FastlyCache for Session {
175179 options_mask : types:: CacheLookupOptionsMask ,
176180 options : wiggle:: GuestPtr < types:: CacheLookupOptions > ,
177181 ) -> Result < types:: CacheHandle , Error > {
178- let headers = load_lookup_options ( self , memory, options_mask, options) ?;
182+ let ( headers, always_use_requested_range) =
183+ load_lookup_options ( self , memory, options_mask, options) ?;
179184 let key = load_cache_key ( memory, cache_key) ?;
180185 let cache = Arc :: clone ( self . cache ( ) ) ;
181186
182- let task = PeekableTask :: spawn ( Box :: pin (
183- async move { Ok ( cache. lookup ( & key, & headers) . await ) } ,
184- ) )
187+ let task = PeekableTask :: spawn ( Box :: pin ( async move {
188+ Ok ( cache
189+ . lookup ( & key, & headers)
190+ . await
191+ . with_always_use_requested_range ( always_use_requested_range) )
192+ } ) )
185193 . await ;
186194 let task = PendingCacheTask :: new ( task) ;
187195 let handle = self . insert_cache_op ( task) ;
@@ -330,20 +338,27 @@ impl FastlyCache for Session {
330338 options_mask : types:: CacheLookupOptionsMask ,
331339 options : wiggle:: GuestPtr < types:: CacheLookupOptions > ,
332340 ) -> Result < types:: CacheBusyHandle , Error > {
333- let headers = load_lookup_options ( self , memory, options_mask, options) ?;
341+ let ( headers, always_use_requested_range) =
342+ load_lookup_options ( self , memory, options_mask, options) ?;
334343 let key = load_cache_key ( memory, cache_key) ?;
335344 let cache = Arc :: clone ( self . cache ( ) ) ;
336345
337346 // Look up once, joining the transaction only if obligated:
338- let e = cache. transaction_lookup ( & key, & headers, false ) . await ;
347+ let e = cache
348+ . transaction_lookup ( & key, & headers, false )
349+ . await
350+ . with_always_use_requested_range ( always_use_requested_range) ;
339351 let ready = e. found ( ) . is_some ( ) || e. go_get ( ) . is_some ( ) ;
340352 // If we already got _something_, we can provide an already-complete PeekableTask.
341353 // Otherwise we need to spawn it and let it block in the background.
342354 let task = if ready {
343355 PeekableTask :: complete ( e)
344356 } else {
345357 PeekableTask :: spawn ( Box :: pin ( async move {
346- Ok ( cache. transaction_lookup ( & key, & headers, true ) . await )
358+ Ok ( cache
359+ . transaction_lookup ( & key, & headers, true )
360+ . await
361+ . with_always_use_requested_range ( always_use_requested_range) )
347362 } ) )
348363 . await
349364 } ;
@@ -529,31 +544,45 @@ impl FastlyCache for Session {
529544 & mut self ,
530545 memory : & mut wiggle:: GuestMemory < ' _ > ,
531546 handle : types:: CacheHandle ,
532- options_mask : types:: CacheGetBodyOptionsMask ,
547+ mut options_mask : types:: CacheGetBodyOptionsMask ,
533548 options : & types:: CacheGetBodyOptions ,
534549 ) -> Result < types:: BodyHandle , Error > {
550+ let from = if options_mask. contains ( types:: CacheGetBodyOptionsMask :: FROM ) {
551+ Some ( options. from )
552+ } else {
553+ None
554+ } ;
555+ options_mask &= !types:: CacheGetBodyOptionsMask :: FROM ;
556+ let to = if options_mask. contains ( types:: CacheGetBodyOptionsMask :: TO ) {
557+ Some ( options. to )
558+ } else {
559+ None
560+ } ;
561+ options_mask &= !types:: CacheGetBodyOptionsMask :: TO ;
562+
535563 if !options_mask. is_empty ( ) {
536564 return Err ( Error :: NotAvailable ( "unknown cache get_body option" ) . into ( ) ) ;
537565 }
538566
539567 // We wind up re-borrowing `found` and `self.session` several times here, to avoid
540- // borrowing the both of them at once. Ultimately it is possible that inserting a body
541- // would change the address of Found, by re-shuffling the AsyncItems table; once again,
542- // borrowck wins the day.
568+ // borrowing the both of them at once.
569+ // (It possible that inserting a body would change the address of Found, by re-shuffling
570+ // the AsyncItems table; we have to live by borrowck's rules.)
543571 //
544572 // We have an exclusive borrow &mut self.session for the lifetime of this call,
545573 // so even though we're re-borrowing/repeating lookups, we know we won't run into TOCTOU.
546574
547- let found = self
548- . cache_entry ( handle. into ( ) )
549- . await ?
550- . found ( )
551- . ok_or ( Error :: CacheError ( crate :: cache:: Error :: Missing ) ) ?;
575+ let entry = self . cache_entry ( handle. into ( ) ) . await ?;
576+
552577 // Preemptively (optimistically) start a read. Don't worry, the Drop impl for Body will
553578 // clean up the copying task.
554579 // We have to do this to allow `found`'s lifetime to end before self.session.body, which
555580 // has to re-borrow self.self.session.
556- let body = found. body ( ) . await ?;
581+ let body = entry. body ( from, to) . await ?;
582+
583+ let found = entry
584+ . found ( )
585+ . ok_or ( Error :: CacheError ( crate :: cache:: Error :: Missing ) ) ?;
557586
558587 if let Some ( prev_handle) = found. last_body_handle {
559588 // Check if they're still reading the previous handle.
0 commit comments