use aro_web::cache::{IfNoneMatch, conditional, with_etag};
use axum::Router;
use axum::body::Body;
use axum::http::{Request, StatusCode, header};
use axum::routing::get;
use tower::ServiceExt;
const ETAG: &str = "\"v1\"";
async fn etag_handler(inm: IfNoneMatch) -> axum::response::Response {
if let Some(not_modified) = conditional(ETAG, &inm) {
return not_modified;
}
with_etag("hello", ETAG)
}
fn app() -> Router {
Router::new().route("/resource", get(etag_handler))
}
#[tokio::test]
async fn matching_if_none_match_returns_304() {
let req = Request::builder()
.uri("/resource")
.header(header::IF_NONE_MATCH, ETAG)
.body(Body::empty())
.unwrap();
let resp = app().oneshot(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::NOT_MODIFIED);
assert_eq!(
resp.headers().get(header::ETAG).unwrap().to_str().unwrap(),
ETAG
);
let body = axum::body::to_bytes(resp.into_body(), usize::MAX)
.await
.unwrap();
assert!(body.is_empty(), "304 response should have no body");
}
#[tokio::test]
async fn non_matching_if_none_match_returns_200_with_etag() {
let req = Request::builder()
.uri("/resource")
.header(header::IF_NONE_MATCH, "\"stale\"")
.body(Body::empty())
.unwrap();
let resp = app().oneshot(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::ETAG).unwrap().to_str().unwrap(),
ETAG
);
}
#[tokio::test]
async fn no_if_none_match_returns_200_with_etag() {
let req = Request::builder()
.uri("/resource")
.body(Body::empty())
.unwrap();
let resp = app().oneshot(req).await.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get(header::ETAG).unwrap().to_str().unwrap(),
ETAG
);
}