tower_etag_cache/
passthrough_predicate.rs1use http::{
2 header::{CONTENT_LENGTH, ETAG},
3 Method,
4};
5
6pub trait PassthroughPredicate: Clone {
8 fn should_passthrough_req<T>(&mut self, req: &http::Request<T>) -> bool;
11
12 fn should_passthrough_resp<T>(&mut self, resp: &http::Response<T>) -> bool;
15}
16
17#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Hash)]
19pub struct DefaultPredicate;
20
21impl PassthroughPredicate for DefaultPredicate {
22 fn should_passthrough_req<T>(&mut self, req: &http::Request<T>) -> bool {
24 !matches!(*req.method(), Method::GET | Method::HEAD)
25 }
26
27 fn should_passthrough_resp<T>(&mut self, resp: &http::Response<T>) -> bool {
32 match resp.status().as_u16() {
33 200..=203 | 205..=299 => (),
34 _ => return true,
35 }
36 if resp.headers().contains_key(ETAG) {
37 return true;
38 }
39 let content_length_hv = match resp.headers().get(CONTENT_LENGTH) {
40 Some(s) => s,
41 None => return false,
42 };
43 let content_length_str = match content_length_hv.to_str() {
44 Ok(s) => s,
45 Err(_) => return false,
46 };
47 let content_length: usize = match content_length_str.parse() {
48 Ok(u) => u,
49 Err(_) => return false,
50 };
51 content_length == 0
52 }
53}