pub struct Conditional { /* private fields */ }Expand description
Extractor for the request’s If-None-Match, to answer 304 Not Modified without rendering.
Like Rails’ fresh_when. Only GET and HEAD requests are considered; for
other methods (and when the header is absent or not ASCII) the client is
never fresh. Extraction never fails. Comparison is weak (RFC 9110):
W/"x" matches "x", and * matches any tag. Default is a request
without the header.
The handler still runs its database queries to build the ETag; a 304
skips only rendering and the body, saving CPU and bandwidth.
§Examples
use axum::response::Response;
use ocre::{Result, cache::{CacheControl, Conditional, ETag}};
async fn show(conditional: Conditional) -> Result<Response> {
let post = ("Hello", 1767225600); // e.g. post::find(&ctx, id).await?.or_404()?
let etag = ETag::of(&post)?; // everything the page shows
conditional.fresh_when(etag, CacheControl::no_cache(), || Ok(format!("<h1>{}</h1>", post.0)))
}
let response = pollster::block_on(show(Conditional::default()))?;
assert_eq!(response.status(), 200);Implementations§
Source§impl Conditional
impl Conditional
Sourcepub fn is_fresh(&self, etag: &ETag) -> bool
pub fn is_fresh(&self, etag: &ETag) -> bool
Whether the client already has the version etag.
Always false for requests other than GET and HEAD, and when the
request had no If-None-Match.
§Examples
use axum::{extract::FromRequestParts, http::Request};
use ocre::cache::{Conditional, ETag};
let etag = ETag::new("v1");
let (mut parts, ()) = Request::get("/").header("If-None-Match", etag.as_str()).body(()).unwrap().into_parts();
let conditional = pollster::block_on(Conditional::from_request_parts(&mut parts, &())).unwrap();
assert!(conditional.is_fresh(&etag));
assert!(!conditional.is_fresh(&ETag::new("v2")));Sourcepub fn fresh_when<R: IntoResponse>(
&self,
etag: ETag,
cache_control: CacheControl,
render: impl FnOnce() -> Result<R>,
) -> Result<Response>
pub fn fresh_when<R: IntoResponse>( &self, etag: ETag, cache_control: CacheControl, render: impl FnOnce() -> Result<R>, ) -> Result<Response>
Answers 304 Not Modified when the client’s copy is current, or else renders the page.
When is_fresh, the response is a 304 with the
ETag and Cache-Control headers and no body, and render is not
called. Otherwise render runs and its response gets both headers.
§Errors
Whatever render returns; a 304 never fails.
§Examples
use axum::{extract::FromRequestParts, http::Request};
use ocre::cache::{CacheControl, Conditional, ETag};
let response = Conditional::default().fresh_when(ETag::new("v1"), CacheControl::no_cache(), || Ok("page"))?;
assert_eq!(response.status(), 200);
assert_eq!(response.headers()["cache-control"], "private, no-cache");
let etag = ETag::new("v1");
let (mut parts, ()) = Request::get("/").header("If-None-Match", etag.as_str()).body(()).unwrap().into_parts();
let conditional = pollster::block_on(Conditional::from_request_parts(&mut parts, &())).unwrap();
let response = conditional.fresh_when(etag, CacheControl::no_cache(), || -> ocre::Result<&str> {
unreachable!("not rendered")
})?;
assert_eq!(response.status(), 304);Trait Implementations§
Source§impl Clone for Conditional
impl Clone for Conditional
Source§fn clone(&self) -> Conditional
fn clone(&self) -> Conditional
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more