Whyhttp - HTTP mocks that fail where the bug actually is
โ Rust ๐ 2026-04-22 ๐ค surdeus ๐๏ธ 1I just put a small crate whyhttp
Yeah, another one. I wrote it for an internal project. My checklist:
- real HTTP server, no in-process mocking
- works from sync and async tests
- an API that reads like the test itself
- guaranteed assert on drop (can't forget)
- separate "which mock handles this" from "what should the request look like"
Out of what I tried, httptest came closest - most of what I wanted was
already there. What started to hurt at scale was readability: matchers do
double duty (routing and asserting), all crammed into one all_of![...].
Hard to tell "this picks the mock" from "this validates the field".
whyhttp splits those two:
let server = whyhttp::Whyhttp::run();
server
.when().path("/orders").method("POST") // routing
.should().body(r#"{"qty":1}"#) // validation, doesn't affect routing
.response().status(201);
If the body is wrong, the request still routes here, still gets 201, and
the test panics on drop with "expected body X, got Y". You see what was
wrong with the request, not "response parser failed" five frames later.
What it doesn't have: regex, partial JSON, custom predicates, dynamic
responses. Not because they're hard. I just don't want to pick an API
shape without a real use case. Plenty of time to break the API later;
no reason to rush the first cut.
If httptest or wiremock already cover your case, stick with them. If
you hit one where a matcher I don't have would help, open an issue --
that's what I need before picking a shape.
- crates.io: crates.io: Rust Package Registry
- docs: whyhttp - Rust
- repo: GitHub - nerjs/whyhttp: Yet another tool for testing HTTP requests. ยท GitHub
The API is stable; feedback welcome.
1 post - 1 participant
๐ท๏ธ Rust_feed