web

httptest

httptest answers HTTP requests the way httpbin.org does. Point a client or a CI job at it when you need an endpoint that reflects your request back, forces a status code, stalls before responding, or hands you junk bytes.

It exists because httpbin.org has a habit of being down, and a test service you can't reach fails your build for reasons that have nothing to do with your code.

Migrating

The base URL is https://hypothesis.sh/api/httptest, and every endpoint hangs off that prefix. Switching over is a find-and-replace:

- curl https://httpbin.org/get
+ curl https://hypothesis.sh/api/httptest/get

CORS is open to any origin, so browser clients work without a proxy. Every response sets Cache-Control: no-store, since a cached answer would defeat the point.

What's there

EndpointBehavior
/get, /post, /put, /patch, /deleteReflects args, headers, origin, and the body's parsed views
/anything/*The same reflection on any path and any method, so it never 405s
/headers, /ip, /user-agentOne piece of the request each
/status/:codesReturns the code you name. A comma-separated list picks one at random
/delay/:nResponds after n seconds, up to 10
/bytes/:nn random bytes, up to 100 KB
/stream/:nn newline-delimited JSON objects, up to 100
/redirect/:nn hops of 302 before landing on /get, up to 10
/basic-auth/:user/:passwd, /bearer401 challenges you can satisfy
/response-headersEchoes query params back as real response headers
/cookies, /cookies/set, /cookies/deleteReads and writes cookies
/json, /html, /xml, /uuidSample documents, plus a fresh UUID per call

Sizes and durations clamp rather than error, matching httpbin. Status codes don't: /status/999 returns a 400, because answering with a code you never asked for is worse than refusing.

Two things to try

Prove your client's timeout fires:

curl --max-time 1 https://hypothesis.sh/api/httptest/delay/5
# curl: (28) Operation timed out after 1000 milliseconds

Point retry logic at an endpoint that fails about a third of the time:

curl -o /dev/null -w '%{http_code}\n' \
     https://hypothesis.sh/api/httptest/status/200,200,500

The explorer

The /httptest page lists every endpoint and fires real requests from your browser, reporting status, timing, response headers, and body. Binary responses are summarized by length instead of rendered as mojibake. The method and path live in the URL, so a specific request is shareable:

/httptest?path=/status/418

Where it differs from httpbin

This is a TypeScript port of httpbin's core surface rather than the Flask app, checked against psf/httpbin 0.10.4. Multipart bodies aren't decoded, and they land in data as raw text. Several endpoints are missing, including /gzip and /image/*.

/response-headers carries a Content-Security-Policy: sandbox header. That endpoint lets a caller put arbitrary bytes in the body and set the Content-Type, which is a live XSS on real httpbin. httpbin.org gets away with it as a sacrificial domain, and this one shares an origin with every other tool here. Scripts can't run, and programmatic clients read headers exactly as they would from httpbin.

The docs list every deviation, including the ones that come from the CDN rather than the code.