A minimal HTTP server that responds to every request with a randomly chosen — and often obscure — HTTP status code. A fun little tool for testing HTTP client resilience, benchmarking, or just exploring the weird corners of the HTTP spec.
- Returns a random status code from a curated selection of rare, odd, and non-standard codes.
- HTTP/1.0 and HTTP/1.1 only (HTTP/2 stripped out at compile time via build tags).
- No keep-alives — each request gets a fresh TCP connection.
- Optional liveness and readiness probe endpoints.
- Single-binary deployment, statically linked, distroless Docker image.
| Flag | Environment variable | Default value | Description |
|---|---|---|---|
--listen |
LISTEN |
0.0.0.0:8888 |
Listen endpoint (addr:port). |
--readiness-path |
READINESS_PATH |
"" |
Readiness probe path. |
--liveness-path |
LIVENESS_PATH |
"" |
Liveness probe path. |
# 1st shell
make
./rngpotd# 2nd shell
curl -v http://localhost:8888/| Code | Message | Notes |
|---|---|---|
| 203 | Non-Authoritative Information | |
| 204 | No Content | |
| 205 | Reset Content | |
| 207 | Multi-Status | |
| 208 | Already Reported | |
| 226 | IM Used | |
| 267 | Doubtful But Okay | Proposal (internet meme/joke) |
| 306 | Switch Proxy | gone; reserved in RFC 2616 |
| 402 | Payment Required | |
| 406 | Not Acceptable | |
| 407 | Proxy Authentication Required | |
| 409 | Conflict | |
| 410 | Gone | |
| 412 | Precondition Failed | |
| 413 | Request Entity Too Large | |
| 414 | Request-URI Too Long | |
| 415 | Unsupported Media Type | |
| 416 | Requested Range Not Satisfiable | |
| 417 | Expectation Failed | |
| 418 | I'm a teapot | RFC 2324 (April 1st joke from IETF) |
| 421 | Misdirected Request | |
| 422 | Unprocessable Entity | |
| 423 | Locked | |
| 424 | Failed Dependency | |
| 425 | Too Early | |
| 426 | Upgrade Required | |
| 428 | Precondition Required | |
| 429 | Too Many Requests | |
| 431 | Request Header Fields Too Large | |
| 444 | Connection Closed Without Response | nginx-specific internal code |
| 451 | Unavailable For Legal Reasons | |
| 499 | Client Closed Request | nginx-specific internal code |
makeThe binary is statically linked with CGO disabled. HTTP/2 support is stripped
from the build (nethttpomithttp2 build tag) to reduce binary size.
docker build -t rngpotd .The Docker image is based on gcr.io/distroless/static-debian13:nonroot and runs
as a non-root user.
| Tag | Effect |
|---|---|
nethttpomithttp2 |
Excludes HTTP/2 from net/http. |
Enables the race detector and CGO:
make dev-buildSince the server is HTTP/1.x only, good old ab (ApacheBench) works perfectly:
# 50k requests, 100 concurrent
ab -n 50000 -c 100 http://localhost:8888/Or try hey for a modern alternative:
hey -n 50000 -c 100 http://localhost:8888/Each request opens and closes a new connection. Disabling keep-alives like this makes the benchmark a good test of TCP connection handling under load.
httpAnyRequest()picks a random status code from therngRetCodesarray.- Looks up the corresponding status text via
httpStatusText()(supports non-standard codes). - Responds with
text/plain, the status text as the body, and a playfulServer: nginx/X.Y.Zheader.
That's it. One endpoint, random responses.
If configured via --liveness-path or --readiness-path, the server registers
dedicated endpoints that respond with HTTP 200 OK and a plain-text OK body.
Probes use the real server identity (rngpotd/X.Y.Z) in the Server header,
distinct from the fake nginx/X.Y.Z served on the main endpoint.
Apache 2.0 | spdx.org | opensource.org