axum_cache_fred/
strategy.rs1use fred::types::Key;
6use http::Request;
7use tracing::log::*;
8
9use std::time::Duration;
10
11pub trait CacheStrategy<B> {
13 fn ttl(&self) -> Duration {
17 Duration::from_secs(86_400)
18 }
19
20 fn computed_key(&self, req: &Request<B>) -> (Duration, Key);
25}
26
27#[derive(Debug, Default, Clone)]
34pub struct RouteKey {}
35
36impl<B> CacheStrategy<B> for RouteKey {
37 fn computed_key(&self, req: &Request<B>) -> (Duration, Key) {
38 let key = format!("{}-{}", req.method(), req.uri().path().to_lowercase());
39 trace!("computed a cache key of `{key}`");
40 (<RouteKey as CacheStrategy<B>>::ttl(self), key.into())
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use pretty_assertions::assert_eq;
48
49 #[test]
50 fn test_route_key() -> anyhow::Result<()> {
51 let strategy = RouteKey::default();
52 let req: Request<()> = Request::builder()
53 .method(http::method::Method::GET)
54 .uri("https://example.com/healthz")
55 .body(())?;
56 let (_, key) = strategy.computed_key(&req);
57 assert_eq!(key, "GET-/healthz".into());
58 Ok(())
59 }
60
61 #[test]
62 fn test_case_insensitive_key() -> anyhow::Result<()> {
63 let strategy = RouteKey::default();
64 let req: Request<()> = Request::builder()
65 .method(http::method::Method::GET)
66 .uri("https://example.com/HealthZ")
67 .body(())?;
68 let (_, key) = strategy.computed_key(&req);
69 assert_eq!(key, "GET-/healthz".into());
70 Ok(())
71 }
72
73 #[test]
74 fn test_key_at_root() -> anyhow::Result<()> {
75 let strategy = RouteKey::default();
76 let req: Request<()> = Request::builder()
77 .method(http::method::Method::GET)
78 .uri("https://example.com/")
79 .body(())?;
80 let (_, key) = strategy.computed_key(&req);
81 assert_eq!(key, "GET-/".into());
82 Ok(())
83 }
84}