Skip to content

Commit 210b734

Browse files
authored
fix: add back x-cache-digest header. (#13)
The previous PR removed the `x-cache-digest` header in all responses. It _should_ have limited the removal to just the times when the cached body isn't being served from the cache. The other instances where we are serving the body from the cache can set the header. Additionally, this updates the `http-cache-semantics` dependency to go back to the upstream crate that doesn't support 206 responses. Given the complexity and narrow scope of supporting very specific ranged requests, it wasn't worth the trouble of implementing it.
1 parent e5e7306 commit 210b734

File tree

3 files changed

+63
-20
lines changed

3 files changed

+63
-20
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ futures = "0.3.31"
3030
hex = "0.4.3"
3131
http = "1.3.1"
3232
http-body = "1.0.1"
33-
http-cache-semantics = { version = "2.1.0", git = "https://github.com/peterhuene/rusty-http-cache-semantics", branch = "allow-partial-content" }
33+
http-cache-semantics = "2.1.0"
3434
http-serde = "2.1.1"
3535
httpdate = "1.0.3"
3636
libc = "0.2.175"

crates/reqwest/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use bytes::Bytes;
3838
use futures::FutureExt;
3939
use futures::future::BoxFuture;
4040
pub use http_cache_stream::X_CACHE;
41+
pub use http_cache_stream::X_CACHE_DIGEST;
4142
pub use http_cache_stream::X_CACHE_LOOKUP;
4243
use http_cache_stream::http::Extensions;
4344
use http_cache_stream::http::Uri;

src/cache.rs

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
4343
pub 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.
4658
fn 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

132149
impl<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

Comments
 (0)