A Java-based HTTP server that lets you locally test your HTTP client, retry logic, streaming behavior, timeouts, etc. with the endpoints of httpbin.org.
This way, you can write tests without relying on an external dependency like httpbin.org.
Java httpbin supports a subset of httpbin endpoints:
/ipReturns Origin IP./user-agentReturns user-agent./headersReturns headers./deleteReturns DELETE data./getReturns GET data./patchReturns PATCH data./postReturns POST data./putReturns PUT data./anythingReturns anything passed in request data./status/:codeReturns given HTTP Status code./redirect/:n302 Redirects n times./relative-redirect/:n302 Redirects n times./absolute-redirect/:n302 Absolute redirects n times./redirect-to?url=foo302 Redirects to the foo URL./stream/:nStreams n lines of JSON objects./stream-bytes/:n?chunkSize=c&seed=sStreams n bytes./delay/:nDelays responding for min(n, 10) seconds./bytes/:nGenerates n random bytes of binary data, accepts optional seed integer parameter./base64/:sReturns a base64 decoded :s input/range/:sReturn a subset of data based on Content-range header./cookiesReturns the cookies./cookies/set?name=valueSets one or more simple cookies./cookies/set/:name/:valueSets one simple cookie./cookies/delete?nameDeletes one or more simple cookies./drip?numbytes=n&duration=s&delay=s&code=codeDrips data over a duration after an optional initial delay, then optionally returns with the given status code./cacheReturns 200 unless an If-Modified-Since or If-None-Match header is provided, when it returns a 304./cache/:nSets a Cache-Control header for n seconds./etagReturn 200 when If-Match or If-None-Match succeed./response-headers?key=valueSets the given response headers and returns them as JSON./gzipReturns gzip-encoded data./deflateReturns deflate-encoded data./brotliReturns Brotli-encoded data./robots.txtReturns some robots.txt rules./denyDenied by robots.txt file./basic-auth/:user/:passwdChallenges HTTP Basic Auth./hidden-basic-auth/:user/:passwdChallenges HTTP Basic Auth and returns 404 on failure./bearerChallenges HTTP Bearer Auth and returns the token./digest-auth/:qop/:user/:passwd[/:algorithm[/:stale_after]]Challenges HTTP Digest Auth./htmlReturns some HTML./forms/postReturns an HTML form that posts to/post./links/:n[/:offset]Returns a page of n links./encoding/utf8Returns a page of UTF-8 encoded text./xmlReturns some XML./jsonReturns a sample JSON document./uuidReturns a UUID4./image/pngReturns page containing a PNG image./image/jpegReturns page containing a JPEG image./image/svgReturns page containing an SVG image./image/webpReturns page containing a WebP image./imageReturns an image the Accept header names, or 406.
/brotli answers with a valid Brotli stream that stores its bytes rather
than compressing them: the JDK ships no Brotli encoder, and the ones on offer
bind to a native library that everything depending on this library would then
have to carry.
Every response carries the CORS headers httpbin sends. OPTIONS answers a
preflight with the 200 a browser requires before it will send the request
itself; a preflight names a path the browser has not fetched yet, so any path
answers one, not only the endpoints above.
First add dependency to pom.xml:
<dependency>
<groupId>org.gaul</groupId>
<artifactId>httpbin</artifactId>
<version>1.4.0</version>
</dependency>Then add to your test code:
private URI httpBinEndpoint = URI.create("http://127.0.0.1:0");
private final HttpBin httpBin = new HttpBin(httpBinEndpoint);
@Before
public void setUp() throws Exception {
httpBin.start();
// reset endpoint to handle zero port
httpBinEndpoint = new URI(httpBinEndpoint.getScheme(),
httpBinEndpoint.getUserInfo(), httpBinEndpoint.getHost(),
httpBin.getPort(), httpBinEndpoint.getPath(),
httpBinEndpoint.getQuery(), httpBinEndpoint.getFragment());
}
@After
public void tearDown() throws Exception {
httpBin.stop();
}
@Test
public void test() throws Exception {
URI uri = URI.create(httpBinEndpoint + "/status/200");
HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();
assert conn.getResponseCode() == 200;
}By default the endpoints live at the server root. Give the endpoint URI a path to serve them beneath it instead, so that a test can share an origin with another service:
URI httpBinEndpoint = URI.create("http://127.0.0.1:0/some/other/path");
HttpBin httpBin = new HttpBin(httpBinEndpoint);
httpBin.start();
// GET /some/other/path/headers returns the headers
// GET /headers returns 501The executable jar accepts the same URI:
httpbin http://127.0.0.1:8080/some/other/path
Notes:
- Requests outside the prefix return 501, as unknown paths already do.
- The prefix must be a plain path: no percent-encoding,
;,?,#, or empty or dot segments. Requests are matched against the raw path, so a prefix needing decoding could never match, and an invalid one is rejected outright rather than silently serving nothing. - For the same reason, a prefixed request carrying path parameters
(
/some/other/path/get;jsessionid=1) or dot segments does not match and returns 501. Locationheaders this server generates, and thePathof cookies it sets, carry the prefix./redirect-to?url=and/response-headersecho values the caller supplied and are left verbatim, so a caller wanting those prefixed must say so.- When passing your own handler to
new HttpBin(endpoint, handler), the handler's prefix must match the endpoint's, otherwise the constructor throws.
psf/httpbin's own test suite runs against this server in CI, which measures the subset above rather than merely describing it. Each test that does not pass names the endpoint that is missing or the behavior that differs. See src/test/python to run the suite, or to work through one of those differences.
- httpbin - original Python implementation
- go-httpbin - Go reimplementation
Copyright (C) 2018-2023 Andrew Gaul
Copyright (C) 2015-2016 Bounce Storage
Licensed under the Apache License, Version 2.0