Go REST

Java (HttpClient)

java.net.http.HttpClient sync and async usage, plus Jackson for JSON binding.

Java 11 addedjava.net.http.HttpClient, a built-in HTTP/2 client that finally makes Apache HttpClient and OkHttp optional. Combined with Jackson for JSON binding, it covers everything you need to call the Go REST API. This guide usesHttpClient for the core examples, then shows the SpringWebClient equivalent for reactive applications.

Setup

Define oneHttpClient per service; reuse it across calls. The connect timeout is the time to establish the TCP connection; the request timeout (set per-request below) is the total time including the response.

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class GoRest {
    private static final String API   = "https://gorest.co.in/public/v2";
    private static final String TOKEN = System.getenv("GOREST_TOKEN");

    private final HttpClient http = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(10))
        .build();
}

GET requests

The fluent builder API matches the shape of an HTTP request:uri,header one or more times, then a verb method (.GET(),.POST(...), etc.).

public HttpResponse<String> get(String path) throws Exception {
    HttpRequest req = HttpRequest.newBuilder()
        .uri(URI.create(API + path))
        .header("Authorization", "Bearer " + TOKEN)
        .header("Accept", "application/json")
        .timeout(Duration.ofSeconds(15))
        .GET()
        .build();
    return http.send(req, HttpResponse.BodyHandlers.ofString());
}

POST with Jackson

Add Jackson for JSON serialization (com.fasterxml.jackson.databind). Marshal your DTO, send the JSON string, then unmarshal the response.

import com.fasterxml.jackson.databind.ObjectMapper;

private final ObjectMapper json = new ObjectMapper();

public HttpResponse<String> post(String path, Object body) throws Exception {
    String payload = json.writeValueAsString(body);
    HttpRequest req = HttpRequest.newBuilder()
        .uri(URI.create(API + path))
        .header("Authorization", "Bearer " + TOKEN)
        .header("Content-Type", "application/json")
        .header("Accept", "application/json")
        .timeout(Duration.ofSeconds(15))
        .POST(HttpRequest.BodyPublishers.ofString(payload))
        .build();
    return http.send(req, HttpResponse.BodyHandlers.ofString());
}

Records and typed responses

Java 17+ records make response DTOs concise. UseTypeFactory to deserialize into a parameterized list.

public record User(int id, String name, String email,
                   String gender, String status) {}

public List<User> listUsers(String status) throws Exception {
    HttpResponse<String> res = get("/users?status=" + status);
    if (res.statusCode() != 200) {
        throw new RuntimeException("List -> " + res.statusCode());
    }
    return json.readValue(res.body(),
        json.getTypeFactory().constructCollectionType(List.class, User.class));
}

Async

sendAsync returns aCompletableFuture for non-blocking work. Useful in servers that want to fan-out reads without blocking a request thread.

public CompletableFuture<List<User>> listUsersAsync(String status) {
    HttpRequest req = HttpRequest.newBuilder()
        .uri(URI.create(API + "/users?status=" + status))
        .header("Authorization", "Bearer " + TOKEN)
        .header("Accept", "application/json")
        .GET()
        .build();
    return http.sendAsync(req, HttpResponse.BodyHandlers.ofString())
        .thenApply(res -> {
            if (res.statusCode() != 200) {
                throw new RuntimeException("List -> " + res.statusCode());
            }
            try {
                return json.readValue(res.body(),
                    json.getTypeFactory().constructCollectionType(List.class, User.class));
            } catch (Exception e) { throw new RuntimeException(e); }
        });
}

Retry on rate limits

Wrap your send call to readX-RateLimit-Reset on a 429 and sleep before retrying:

public HttpResponse<String> sendWithRetry(HttpRequest req) throws Exception {
    for (int attempt = 0; attempt < 3; attempt++) {
        HttpResponse<String> res = http.send(req, HttpResponse.BodyHandlers.ofString());
        if (res.statusCode() != 429) return res;
        int wait = res.headers().firstValue("X-RateLimit-Reset")
            .map(Integer::parseInt).orElse(1);
        Thread.sleep(Math.max(wait, 1) * 1000L);
    }
    throw new RuntimeException("Rate limited; gave up");
}

Spring WebClient (advanced)

If your application is already on Spring Boot, useWebClient instead ofHttpClient. It integrates with the rest of the framework (config, metrics, tracing) and supports reactive types. This section assumes Spring Boot, dependency injection, and reactiveMono /Flux types; skip it if you are new to Spring and stick withHttpClient above.

import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class GoRestConfig {
    @Bean
    public WebClient goRestClient(@Value("${gorest.token}") String token) {
        return WebClient.builder()
            .baseUrl("https://gorest.co.in/public/v2")
            .defaultHeader("Authorization", "Bearer " + token)
            .defaultHeader("Accept", "application/json")
            .build();
    }
}

@Service
public class UserService {
    private final WebClient client;
    public UserService(WebClient goRestClient) { this.client = goRestClient; }

    public Mono<List<User>> listActive() {
        return client.get()
            .uri("/users?status=active")
            .retrieve()
            .bodyToFlux(User.class)
            .collectList();
    }
}

Tips

Related guides

Keep going

Back to all guides Try it in the console