Skip to content

Instantly share code, notes, and snippets.

@alextes
Last active November 30, 2023 20:00
Show Gist options
  • Save alextes/4095b1fca7d58bd3100825e10e882e57 to your computer and use it in GitHub Desktop.
Save alextes/4095b1fca7d58bd3100825e10e882e57 to your computer and use it in GitHub Desktop.
ETag middleware for use with Axum. It'd be nice to write a proper implementation as a Tower service.
async fn etag_middleware<B: std::fmt::Debug>(
req: Request<B>,
next: Next<B>,
) -> Result<Response, StatusCode> {
let if_none_match_header = req.headers().get(header::IF_NONE_MATCH).cloned();
let path = req.uri().path().to_owned();
let res = next.run(req).await;
let (mut parts, mut body) = res.into_parts();
let bytes = {
let mut body_bytes = vec![];
while let Some(inner) = body.data().await {
let bytes = inner.unwrap();
body_bytes.put(bytes);
}
body_bytes
};
match bytes.len() == 0 {
true => {
trace!(path, "response without body, skipping etag");
Ok(parts.into_response())
}
false => match if_none_match_header {
None => {
let etag = EntityTag::from_data(&bytes);
parts.headers.insert(
header::ETAG,
HeaderValue::from_str(&etag.to_string()).unwrap(),
);
trace!(path, %etag, "no if-none-match header");
Ok((parts, bytes).into_response())
}
Some(if_none_match) => {
let if_none_match_etag = if_none_match.to_str().unwrap().parse::<EntityTag>();
match if_none_match_etag {
Err(ref err) => {
error!("{} - {:?}", err, &if_none_match_etag);
let etag = EntityTag::from_data(&bytes);
parts.headers.insert(
header::ETAG,
HeaderValue::from_str(&etag.to_string()).unwrap(),
);
Ok((parts, bytes).into_response())
}
Ok(if_none_match_etag) => {
let etag = EntityTag::from_data(&bytes);
parts.headers.insert(
header::ETAG,
HeaderValue::from_str(&etag.to_string()).unwrap(),
);
let some_match = etag.strong_eq(&if_none_match_etag);
trace!(
path,
%etag,
some_match,
"if-none-match" = %if_none_match_etag
);
if some_match {
Ok((StatusCode::NOT_MODIFIED, parts).into_response())
} else {
Ok((parts, bytes).into_response())
}
}
}
}
},
}
}
@sdasda7777
Copy link

I made a few modifications for my own purposes: https://gist.github.com/sdasda7777/3acaa1a7bee2692a939526252b567119

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment