#![deny(clippy::all)]
mod fixtures {
pub mod head_server;
}
use fixtures::head_server::spawn;
#[tokio::test]
async fn head_conditional_no_headers_existing_returns_200() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 200);
}
#[tokio::test]
async fn head_conditional_no_headers_nonexistent_returns_404() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/999"))
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 404);
}
#[tokio::test]
async fn head_conditional_200_has_no_body() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 200);
let body = resp.bytes().await.expect("failed to read body");
assert!(body.is_empty(), "HEAD response must not carry a body");
}
#[tokio::test]
async fn head_conditional_200_includes_etag_and_last_modified() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 200);
assert_eq!(resp.headers()["etag"], "\"known-etag-42\"");
assert_eq!(
resp.headers()["last-modified"],
"Wed, 01 Jan 2025 00:00:00 GMT"
);
assert_eq!(resp.headers()["content-type"], "application/json");
}
#[tokio::test]
async fn head_conditional_if_none_match_star_returns_304() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.header("If-None-Match", "*")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 304);
}
#[tokio::test]
async fn head_conditional_if_none_match_star_nonexistent_returns_404() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/999"))
.header("If-None-Match", "*")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 404);
}
#[tokio::test]
async fn head_conditional_if_none_match_matching_returns_304() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.header("If-None-Match", "\"known-etag-42\"")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 304);
}
#[tokio::test]
async fn head_conditional_if_none_match_nonmatching_returns_200() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.header("If-None-Match", "\"wrong-etag\"")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 200);
}
#[tokio::test]
async fn head_conditional_if_match_nonmatching_returns_412() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.header("If-Match", "\"wrong-etag\"")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 412);
}
#[tokio::test]
async fn head_conditional_if_match_nonmatching_nonexistent_returns_404() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/999"))
.header("If-Match", "\"wrong-etag\"")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 404);
}
#[tokio::test]
async fn head_conditional_if_modified_since_future_returns_304() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.header("If-Modified-Since", "Sun, 01 Jun 2025 00:00:00 GMT")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 304);
}
#[tokio::test]
async fn head_conditional_if_unmodified_since_past_returns_412() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/conditional/42"))
.header("If-Unmodified-Since", "Mon, 01 Jan 2024 00:00:00 GMT")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 412);
}
#[tokio::test]
async fn head_negotiated_json_accept_returns_200() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/negotiated/42"))
.header("Accept", "application/json")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 200);
}
#[tokio::test]
async fn head_negotiated_xml_only_returns_406() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/negotiated/42"))
.header("Accept", "application/xml")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 406);
}
#[tokio::test]
async fn head_negotiated_nonexistent_returns_404() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/negotiated/999"))
.header("Accept", "application/json")
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 404);
}
#[tokio::test]
async fn head_normalized_existing_returns_404() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/normalized/42"))
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 404);
}
#[tokio::test]
async fn head_normalized_nonexistent_returns_404() {
let addr = spawn().await;
let resp = reqwest::Client::new()
.head(format!("http://{addr}/cp/normalized/999"))
.send()
.await
.expect("request failed");
assert_eq!(resp.status(), 404);
}