@@ -42,6 +42,18 @@ pub const X_CACHE_LOOKUP: &str = "x-cache-lookup";
4242/// Value will be `HIT` if a response was served from the cache, `MISS` if not.
4343pub const X_CACHE : & str = "x-cache" ;
4444
45+ /// The name of the `x-cache-digest` custom header.
46+ ///
47+ /// This header is only present in the response when returning a body from the
48+ /// cache.
49+ ///
50+ /// This can be used to read a body directly from cache storage rather than
51+ /// reading the body through the response.
52+ ///
53+ /// This header is only present when a cached response body is being served from
54+ /// the cache.
55+ pub const X_CACHE_DIGEST : & str = "x-cache-digest" ;
56+
4557/// Gets the storage key for a request.
4658fn storage_key ( method : & Method , uri : & Uri , headers : & HeaderMap ) -> String {
4759 let mut hasher = Sha256 :: new ( ) ;
@@ -126,7 +138,12 @@ trait ResponseExt {
126138 fn extend_headers ( & mut self , headers : HeaderMap ) ;
127139
128140 /// Sets the cache status headers of the response.
129- fn set_cache_status ( & mut self , lookup : CacheLookupStatus , status : CacheStatus ) ;
141+ fn set_cache_status (
142+ & mut self ,
143+ lookup : CacheLookupStatus ,
144+ status : CacheStatus ,
145+ digest : Option < & str > ,
146+ ) ;
130147}
131148
132149impl < B > ResponseExt for Response < B > {
@@ -168,15 +185,24 @@ impl<B> ResponseExt for Response<B> {
168185 self . headers_mut ( ) . extend ( headers) ;
169186 }
170187
171- fn set_cache_status ( & mut self , lookup : CacheLookupStatus , status : CacheStatus ) {
172- self . headers_mut ( ) . insert (
188+ fn set_cache_status (
189+ & mut self ,
190+ lookup : CacheLookupStatus ,
191+ status : CacheStatus ,
192+ digest : Option < & str > ,
193+ ) {
194+ let headers = self . headers_mut ( ) ;
195+ headers. insert (
173196 X_CACHE_LOOKUP ,
174197 lookup. to_string ( ) . parse ( ) . expect ( "value should parse" ) ,
175198 ) ;
176- self . headers_mut ( ) . insert (
199+ headers . insert (
177200 X_CACHE ,
178201 status. to_string ( ) . parse ( ) . expect ( "value should parse" ) ,
179202 ) ;
203+ if let Some ( digest) = digest {
204+ headers. insert ( X_CACHE_DIGEST , digest. parse ( ) . expect ( "value should parse" ) ) ;
205+ }
180206 }
181207}
182208
@@ -374,7 +400,7 @@ where
374400 let policy =
375401 CachePolicy :: new_options ( & request_like, & response, SystemTime :: now ( ) , self . options ) ;
376402
377- response. set_cache_status ( lookup_status, CacheStatus :: Miss ) ;
403+ response. set_cache_status ( lookup_status, CacheStatus :: Miss , None ) ;
378404
379405 if matches ! ( request_like. method, Method :: GET | Method :: HEAD )
380406 && response. status ( ) . is_success ( )
@@ -460,9 +486,11 @@ where
460486 ) ;
461487
462488 stored. response . extend_headers ( parts. headers ) ;
463- stored
464- . response
465- . set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Hit ) ;
489+ stored. response . set_cache_status (
490+ CacheLookupStatus :: Hit ,
491+ CacheStatus :: Hit ,
492+ Some ( & stored. digest ) ,
493+ ) ;
466494 return Ok ( stored. response ) ;
467495 }
468496 BeforeRequest :: Stale {
@@ -506,8 +534,7 @@ where
506534 let ( parts, body) = response. into_parts ( ) ;
507535 match self . storage . store ( key. clone ( ) , parts, body, policy) . await {
508536 Ok ( mut response) => {
509- // Response was stored, return the response with the storage key
510- response. set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Miss ) ;
537+ response. set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Miss , None ) ;
511538 Ok ( response)
512539 }
513540 Err ( e) => {
@@ -559,7 +586,11 @@ where
559586 replying with not modified"
560587 ) ;
561588
562- Self :: prepare_stale_response ( & request_like. uri , & mut stored. response ) ;
589+ Self :: prepare_stale_response (
590+ & request_like. uri ,
591+ & mut stored. response ,
592+ & stored. digest ,
593+ ) ;
563594 Ok ( stored. response )
564595 }
565596 AfterResponse :: NotModified ( policy, parts) => {
@@ -582,10 +613,13 @@ where
582613 "response updated in cache successfully"
583614 ) ;
584615
585- // Response was stored and the body comes from storage
616+ // Response was updated and the body comes from storage
586617 let mut cached_response = Response :: from_parts ( parts, body) ;
587- cached_response
588- . set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Hit ) ;
618+ cached_response. set_cache_status (
619+ CacheLookupStatus :: Hit ,
620+ CacheStatus :: Hit ,
621+ Some ( & stored. digest ) ,
622+ ) ;
589623 Ok ( cached_response)
590624 }
591625 Err ( e) => {
@@ -618,7 +652,11 @@ where
618652 with a warning"
619653 ) ;
620654
621- Self :: prepare_stale_response ( & request_like. uri , & mut stored. response ) ;
655+ Self :: prepare_stale_response (
656+ & request_like. uri ,
657+ & mut stored. response ,
658+ & stored. digest ,
659+ ) ;
622660 Ok ( stored. response )
623661 }
624662 Ok ( mut response) => {
@@ -632,7 +670,7 @@ where
632670 ) ;
633671
634672 // Otherwise, don't serve the cached response at all
635- response. set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Miss ) ;
673+ response. set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Miss , None ) ;
636674 Ok ( response. map ( Body :: from_upstream) )
637675 }
638676 Err ( e) => {
@@ -650,15 +688,19 @@ where
650688 storage with a warning"
651689 ) ;
652690
653- Self :: prepare_stale_response ( & request_like. uri , & mut stored. response ) ;
691+ Self :: prepare_stale_response (
692+ & request_like. uri ,
693+ & mut stored. response ,
694+ & stored. digest ,
695+ ) ;
654696 Ok ( stored. response )
655697 }
656698 }
657699 }
658700 }
659701
660702 /// Prepares a stale response for sending back to the client.
661- fn prepare_stale_response < B > ( uri : & Uri , response : & mut Response < Body < B > > ) {
703+ fn prepare_stale_response < B > ( uri : & Uri , response : & mut Response < Body < B > > , digest : & str ) {
662704 // If the server failed to give us a response, add the required warning to the
663705 // cached response:
664706 // 111 Revalidation failed
@@ -667,6 +709,6 @@ where
667709 // due to an inability to reach the server.
668710 // (https://tools.ietf.org/html/rfc2616#section-14.46)
669711 response. add_warning ( uri, 111 , "Revalidation failed" ) ;
670- response. set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Hit ) ;
712+ response. set_cache_status ( CacheLookupStatus :: Hit , CacheStatus :: Hit , Some ( digest ) ) ;
671713 }
672714}
0 commit comments