mod common;
use mini_static::Server;
use std::fs;
use tempfile::TempDir;
#[test]
fn traversal_and_missing_file_both_return_404() {
let root = TempDir::new().unwrap();
fs::write(root.path().join("exists.txt"), b"content").unwrap();
let server = Server::new(root.path()).unwrap();
let traversal_response = server.handle_request("/../../../etc/passwd");
let missing_response = server.handle_request("/nonexistent.txt");
assert_eq!(traversal_response.status().as_u16(), 404);
assert_eq!(missing_response.status().as_u16(), 404);
}
#[test]
fn traversal_and_missing_file_have_identical_bodies() {
let root = TempDir::new().unwrap();
let server = Server::new(root.path()).unwrap();
let traversal_response = server.handle_request("/../../../etc/passwd");
let missing_response = server.handle_request("/nonexistent.txt");
let traversal_status = traversal_response.status().as_u16();
let missing_status = missing_response.status().as_u16();
assert_eq!(traversal_status, missing_status, "status codes should match");
assert_eq!(traversal_status, 404, "both should be 404");
}
#[tokio::test]
async fn all_responses_have_nosniff_header_and_success_returns_real_file_content() {
let root = TempDir::new().unwrap();
fs::write(root.path().join("test.txt"), b"content").unwrap();
let server = Server::new(root.path()).unwrap();
let traversal_response = server.handle_request("/../etc/passwd");
let missing_response = server.handle_request("/nonexistent.txt");
let success_response = server.handle_request("/test.txt");
let traversal_nosniff = traversal_response.headers().get("X-Content-Type-Options").cloned();
let missing_nosniff = missing_response.headers().get("X-Content-Type-Options").cloned();
let success_nosniff = success_response.headers().get("X-Content-Type-Options").cloned();
assert_eq!(
traversal_nosniff.as_ref().map(|v| v.to_str().unwrap()),
Some("nosniff"),
"traversal response should have nosniff"
);
assert_eq!(
missing_nosniff.as_ref().map(|v| v.to_str().unwrap()),
Some("nosniff"),
"missing file response should have nosniff"
);
assert_eq!(
success_nosniff.as_ref().map(|v| v.to_str().unwrap()),
Some("nosniff"),
"successful response should have nosniff"
);
assert_eq!(success_response.status().as_u16(), 200);
let body = common::body_bytes(success_response).await;
assert_eq!(&body[..], b"content", "success response body should be the file's real content");
}
#[test]
fn no_information_leak_between_traversal_and_missing() {
let root = TempDir::new().unwrap();
let server = Server::new(root.path()).unwrap();
let traversal_response = server.handle_request("/../../../etc/passwd");
let missing_response = server.handle_request("/definitely-not-a-real-file-xyz.txt");
assert_eq!(traversal_response.status(), missing_response.status());
let traversal_msg = traversal_response.headers().get("X-Content-Type-Options");
let missing_msg = missing_response.headers().get("X-Content-Type-Options");
assert_eq!(traversal_msg, missing_msg);
}