use std::fs;
use std::path::Path;
use criterion::{criterion_group, criterion_main, Criterion};
use mini_static::resolve_with_canonical_root;
use tempfile::TempDir;
const DEEP_NESTING: usize = 10;
fn build_fixture_root() -> TempDir {
let dir = tempfile::tempdir().expect("create fixture tempdir");
let root = dir.path();
fs::write(root.join("shallow.txt"), b"shallow").expect("write shallow fixture");
let mut deep = root.to_path_buf();
for i in 0..DEEP_NESTING {
deep.push(format!("segment-{i}"));
}
fs::create_dir_all(&deep).expect("create deep fixture dirs");
fs::write(deep.join("deep.txt"), b"deep").expect("write deep fixture");
fs::write(root.join("caf\u{e9}.txt"), b"percent-decoded").expect("write encoded fixture");
let index_dir = root.join("indexed");
fs::create_dir_all(&index_dir).expect("create indexed dir");
fs::write(index_dir.join("index.html"), b"<html></html>").expect("write index fixture");
dir
}
fn deep_request_path() -> String {
let mut path = String::new();
for i in 0..DEEP_NESTING {
path.push_str(&format!("/segment-{i}"));
}
path.push_str("/deep.txt");
path
}
fn bench_path_resolution(c: &mut Criterion) {
let fixture = build_fixture_root();
let root_canon = fixture
.path()
.canonicalize()
.expect("canonicalize fixture root");
let deep_path = deep_request_path();
let mut group = c.benchmark_group("resolve_with_canonical_root");
group.bench_function("shallow", |b| {
b.iter(|| resolve_with_canonical_root(&root_canon, "/shallow.txt"))
});
group.bench_function("deep_nested", |b| {
b.iter(|| resolve_with_canonical_root(&root_canon, &deep_path))
});
group.bench_function("percent_decoded", |b| {
b.iter(|| resolve_with_canonical_root(&root_canon, "/caf%C3%A9.txt"))
});
group.bench_function("traversal_rejected", |b| {
b.iter(|| resolve_with_canonical_root(&root_canon, "/../../etc/passwd"))
});
group.bench_function("directory_index", |b| {
b.iter(|| resolve_with_canonical_root(&root_canon, "/indexed"))
});
group.finish();
c.bench_function("resolve_per_call_root_canonicalize", |b| {
b.iter(|| mini_static::resolve(Path::new(fixture.path()), "/shallow.txt"))
});
}
criterion_group!(benches, bench_path_resolution);
criterion_main!(benches);