unirest-java-3
>
>
This skill covers the Unirest-Java 3.x HTTP client library for Java 8+. It uses Apache HttpClient 4 as the HTTP engine and includes GSON as the default JSON parser.
concurrency(total, perRoute))automaticRetries())Use this skill when the user needs to:
concurrency())Maven dependency (Unirest 3.14.5):
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.14.5</version>
</dependency>
✅ No JSON module declaration needed — GSON is included by default.
Minimal GET request:
String body = Unirest.get("https://api.example.com/users")
.asString()
.getBody();
Minimal POST with JSON:
HttpResponse<JsonNode> response = Unirest.post("https://api.example.com/users")
.header("Content-Type", "application/json")
.body(new User("Alice", "[email protected]"))
.asJson();
Unirest 3.x is a single dependency that includes GSON by default:
<dependency>
<groupId>com.konghq</groupId>
<artifactId>unirest-java</artifactId>
<version>3.14.5</version>
</dependency>
✅ No need to declare a separate JSON module —
JsonObjectMapper(GSON-based) is included.
All configuration goes through Unirest.config():
Unirest.config()
.connectTimeout(5000)
.socketTimeout(10000)
.concurrency(200, 20)
.setDefaultHeader("Accept", "application/json")
.setDefaultBasicAuth("user", "pass")
.followRedirects(true)
.verifySsl(true)
.enableCookieManagement(true)
.automaticRetries(true)
.proxy("proxy.com", 8080, "user", "pass");
Key config options:
| Method | Impact | Default |
|--------|--------|---------|
| connectTimeout(int) | Connection timeout (ms) | 10000 |
| socketTimeout(int) | Socket/read timeout (ms) | 60000 |
| concurrency(int, int) | Max total connections, max per route | 200/20 |
| followRedirects(boolean) | Follow HTTP redirects | true |
| verifySsl(boolean) | Enforce SSL verification | true |
| enableCookieManagement(boolean) | Accept/store cookies | true |
| automaticRetries(boolean) | Auto-retry on socket errors (up to 4 times) | true |
| retryAfter(boolean) | Auto-retry on 429/529 with Retry-After header | false |
| defaultBaseUrl(String) | Default base URL for all requests | none |
| addShutdownHook(boolean) | Register JVM shutdown hook | false |
| useSystemProperties(boolean) | Use system properties for proxies etc. | true |
Multiple configurations:
// Primary instance (same as static Unirest)
UnirestInstance unirest = Unirest.primaryInstance();
// Spawn a new independent instance
UnirestInstance custom = Unirest.spawnInstance();
custom.config().connectTimeout(3000);
⚠️ If you spawn a new instance, YOU are responsible for shutting it down.
See references/configuration.md for full config table, interceptors, object mappers, and metrics.
Basic request types:
Unirest.get("http://localhost/users").asString();
Unirest.post("http://localhost/users").body(json).asJson();
Unirest.put("http://localhost/users/1").body(user).asEmpty();
Unirest.delete("http://localhost/users/1").asEmpty();
Route parameters:
Unirest.get("http://localhost/users/{id}")
.routeParam("id", "42")
.asString();
// Results in http://localhost/users/42
Query parameters:
Unirest.get("http://localhost/search")
.queryString("q", "unirest")
.queryString("page", 1)
.asString();
Headers and auth:
Unirest.get("http://localhost/protected")
.header("X-Custom", "value")
.basicAuth("user", "pass")
.asString();
Form data:
Unirest.post("http://localhost/form")
.field("name", "Alice")
.field("age", 30)
.asEmpty();
File upload:
Unirest.post("http://localhost/upload")
.field("file", new File("/path/to/file.zip"))
.asEmpty();
Async request:
CompletableFuture<HttpResponse<JsonNode>> future = Unirest.get("http://localhost/data")
.asJsonAsync(response -> {
System.out.println(response.getBody());
});
Per-request proxy (3.x only):
Unirest.get("http://localhost/data")
.proxy("proxy.com", 8080)
.asString();
JSON Patch (RFC-6902):
Unirest.jsonPatch("http://localhost/resource")
.add("/fruits/-", "Apple")
.remove("/bugs")
.replace("/name", "Updated")
.asJson();
See references/requests.md for upload progress, paged requests, client certificates, and more.
Response types:
// String
String body = Unirest.get(url).asString().getBody();
// Object mapping (GSON included by default)
Book book = Unirest.get(url).asObject(Book.class).getBody();
// Generic types
List<Book> books = Unirest.get(url)
.asObject(new GenericType<List<Book>>(){}).getBody();
// JSON
JsonNode json = Unirest.get(url).asJson().getBody();
// File
File file = Unirest.get(url).asFile("/tmp/download.zip").getBody();
// Empty (status/headers only)
HttpResponse resp = Unirest.delete(url).asEmpty();
Error handling:
Unirest.get("http://localhost/data")
.asJson()
.ifSuccess(response -> handleSuccess(response))
.ifFailure(response -> {
log.error("Status: " + response.getStatus());
response.getParsingError().ifPresent(e -> {
log.error("Parse error: " + e.getMessage());
});
});
Parsing errors:
response.getParsingError().ifPresent(ex -> {
String originalBody = ex.getOriginalBody();
String message = ex.getMessage();
});
Map error objects:
HttpResponse<Book> book = Unirest.get(url).asObject(Book.class);
Error err = book.mapError(Error.class);
See references/responses.md for download progress, large responses, body mapping, and more.
Static mock:
MockClient mock = MockClient.register();
mock.expect(HttpMethod.GET, "http://api.example.com/users")
.thenReturn("{\"name\":\"Alice\"}")
.withStatus(200);
String body = Unirest.get("http://api.example.com/users")
.asString().getBody();
// body == "{\"name\":\"Alice\"}"
mock.verifyAll(); // Verify all expects were called
Instance mock (3.x requires both clients):
UnirestInstance unirest = Unirest.spawnInstance();
MockClient mock = MockClient.register(unirest);
// In 3.x, the mock implements both Client and AsyncClient
Body matching:
mock.expect(HttpMethod.POST, "http://api.example.com/users")
.body(FieldMatcher.of("name", "Alice", "role", "admin"))
.thenReturn()
.withStatus(201);
Verify with times:
var expect = mock.expect(HttpMethod.GET, "http://api.example.com/users").thenReturn();
expect.verify(); // At least once
expect.verify(Times.never()); // Never called
See references/mocking.md for POJO responses, multiple expects, and more.
Basic caching:
Unirest.config().cacheResponses(true);
Advanced caching with options:
Unirest.config().cacheResponses(Cache.builder()
.depth(100) // Max entries
.maxAge(5, TimeUnit.MINUTES)); // Entry TTL
Custom cache (e.g., Guava):
Unirest.config().cacheResponses(
Cache.builder().backingCache(new MyGuavaCache()));
See references/caching.md for custom cache implementation details.
Simple proxy:
Unirest.config().proxy("proxy.com", 8080, "user", "pass");
Per-request proxy (3.x only):
Unirest.get("http://localhost/data")
.proxy("proxy.com", 8080)
.asString();
System properties (default: true in 3.x):
System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "7777");
// useSystemProperties defaults to true in 3.x
See references/proxies.md for details.
| Error | Cause | Fix |
|-------|-------|-----|
| NoClassDefFoundError: kong/unirest/Unirest | Wrong package | Use import kong.unirest.* (not kong.unirest.core.*) |
| asObject() returns null body | Response parsing failed | Check response.getParsingError() for details |
| ConnectException: Connection timed out | Server unreachable or timeout too low | Increase connectTimeout or check network |
| SocketTimeoutException | Read timeout exceeded | Increase socketTimeout (default 60000ms) |
| SSLHandshakeException | SSL verification failure | Use verifySsl(false) for dev only, fix certs in prod |
| Proxy not working | System props may be disabled | Check useSystemProperties(true) (default true in 3.x) |
| Too many connections | Connection pool exhausted | Increase concurrency(total, perRoute) |
| Automatic retries not working | Disabled or not applicable | Check automaticRetries(true) (default true) |
kong.unirest — Not kong.unirest.core (that's 4.x)unirest-java:3.14.5 (unlike 4.x which uses BOM + core + module)socketTimeout() controls read timeout separately from connectTimeout()concurrency(total, perRoute) lets you tune Apache's connection poolautomaticRetries(true) retries socket errors up to 4 timesrequest.proxy(host, port) works (removed in 4.x)hostnameVerifier(verifier) for custom SSL hostname verificationaddShutdownHook(true) registers JVM shutdown hooksuseSystemProperties defaults to true (unlike 4.x)Unirest.sse() does not exist in 3.xClient and AsyncClient