foreach-ui logo
codeLanguages
account_treeDSA

Quick Actions

quizlock Random Quiz
trending_uplock Progress
  • 1
  • 2
  • 3
  • 4
  • 5
  • quiz
Java
  • Use the modern HttpClient API (Java 11+)
  • Make synchronous and asynchronous HTTP requests
  • Send different HTTP methods with body data
  • Handle responses and headers properly

HTTP Client API

Java 11 introduced a modern HTTP Client API (java.net.http) replacing HttpURLConnection. Supports HTTP/1.1 and HTTP/2, sync and async, cleaner API. Recommended for new HTTP client code.

Key Classes

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

// HttpClient - sends requests, receives responses
// HttpRequest - represents an HTTP request
// HttpResponse - represents an HTTP response

Creating an HttpClient

// Simple client with defaults
HttpClient client = HttpClient.newHttpClient();

// Customized client
HttpClient client = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2)         // Prefer HTTP/2
    .followRedirects(HttpClient.Redirect.NORMAL) // Follow redirects
    .connectTimeout(Duration.ofSeconds(10))      // Connection timeout
    .build();

Making GET Requests

Synchronous GET

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .header("Accept", "application/json")
    .GET()  // Default, can be omitted
    .build();

HttpResponse<String> response = client.send(
    request, 
    HttpResponse.BodyHandlers.ofString()
);

System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());

Asynchronous GET

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .build();

client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println)
    .join();  // Wait for completion

With CompletableFuture

CompletableFuture<HttpResponse<String>> future = 
    client.sendAsync(request, HttpResponse.BodyHandlers.ofString());

future.thenAccept(response -> {
    System.out.println("Status: " + response.statusCode());
    System.out.println("Body: " + response.body());
}).exceptionally(e -> {
    System.err.println("Error: " + e.getMessage());
    return null;
});

Making POST Requests

POST with JSON Body

String json = "{\"name\": \"John\", \"email\": \"john@example.com\"}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(json))
    .build();

HttpResponse<String> response = client.send(
    request, 
    HttpResponse.BodyHandlers.ofString()
);

if (response.statusCode() == 201) {
    System.out.println("Created: " + response.body());
}

POST with Form Data

String formData = "username=john&password=secret";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://example.com/login"))
    .header("Content-Type", "application/x-www-form-urlencoded")
    .POST(HttpRequest.BodyPublishers.ofString(formData))
    .build();

HttpResponse<String> response = client.send(
    request, 
    HttpResponse.BodyHandlers.ofString()
);

POST with File

Path filePath = Path.of("data.txt");

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/upload"))
    .header("Content-Type", "text/plain")
    .POST(HttpRequest.BodyPublishers.ofFile(filePath))
    .build();

HttpResponse<String> response = client.send(
    request, 
    HttpResponse.BodyHandlers.ofString()
);

Other HTTP Methods

// PUT
HttpRequest putRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .header("Content-Type", "application/json")
    .PUT(HttpRequest.BodyPublishers.ofString(json))
    .build();

// DELETE
HttpRequest deleteRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .DELETE()
    .build();

// Custom method
HttpRequest patchRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .method("PATCH", HttpRequest.BodyPublishers.ofString(json))
    .build();

Response Body Handlers

// As String
HttpResponse<String> stringResponse = client.send(
    request, HttpResponse.BodyHandlers.ofString());

// As byte array
HttpResponse<byte[]> bytesResponse = client.send(
    request, HttpResponse.BodyHandlers.ofByteArray());

// Save to file
HttpResponse<Path> fileResponse = client.send(
    request, HttpResponse.BodyHandlers.ofFile(Path.of("output.txt")));

// As stream of lines
HttpResponse<Stream<String>> streamResponse = client.send(
    request, HttpResponse.BodyHandlers.ofLines());

streamResponse.body().forEach(System.out::println);

// Discard body
HttpResponse<Void> discardResponse = client.send(
    request, HttpResponse.BodyHandlers.discarding());

Working with Headers

Request Headers

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/data"))
    .header("Accept", "application/json")
    .header("Authorization", "Bearer token123")
    .header("User-Agent", "Java HttpClient")
    .headers("X-Custom-1", "value1", "X-Custom-2", "value2")
    .build();

Response Headers

HttpResponse<String> response = client.send(
    request, HttpResponse.BodyHandlers.ofString());

// Get all headers
HttpHeaders headers = response.headers();

// Get specific header
Optional<String> contentType = headers.firstValue("Content-Type");
List<String> cookies = headers.allValues("Set-Cookie");

// Print all headers
headers.map().forEach((name, values) -> {
    System.out.println(name + ": " + values);
});

Timeouts

// Client-level timeout
HttpClient client = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(10))
    .build();

// Request-level timeout
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/slow"))
    .timeout(Duration.ofSeconds(30))
    .build();

try {
    HttpResponse<String> response = client.send(
        request, HttpResponse.BodyHandlers.ofString());
} catch (HttpTimeoutException e) {
    System.err.println("Request timed out!");
}

Handling Redirects

HttpClient client = HttpClient.newBuilder()
    .followRedirects(HttpClient.Redirect.ALWAYS)  // Follow all redirects
    .build();

// Redirect policies:
// NEVER - never follow redirects
// ALWAYS - always follow redirects
// NORMAL - follow redirects except HTTPS to HTTP

Concurrent Requests

HttpClient client = HttpClient.newHttpClient();

List<URI> uris = List.of(
    URI.create("https://api.example.com/users/1"),
    URI.create("https://api.example.com/users/2"),
    URI.create("https://api.example.com/users/3")
);

List<CompletableFuture<String>> futures = uris.stream()
    .map(uri -> HttpRequest.newBuilder(uri).build())
    .map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
    .map(future -> future.thenApply(HttpResponse::body))
    .collect(Collectors.toList());

// Wait for all and collect results
List<String> results = futures.stream()
    .map(CompletableFuture::join)
    .collect(Collectors.toList());

Authentication

Basic Authentication

HttpClient client = HttpClient.newBuilder()
    .authenticator(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(
                "username",
                "password".toCharArray()
            );
        }
    })
    .build();

Bearer Token

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/protected"))
    .header("Authorization", "Bearer " + token)
    .build();

Complete Example

public class HttpClientExample {
    private final HttpClient client;
    
    public HttpClientExample() {
        this.client = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .connectTimeout(Duration.ofSeconds(10))
            .followRedirects(HttpClient.Redirect.NORMAL)
            .build();
    }
    
    public String get(String url) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .header("Accept", "application/json")
            .timeout(Duration.ofSeconds(30))
            .GET()
            .build();
        
        HttpResponse<String> response = client.send(
            request, HttpResponse.BodyHandlers.ofString());
        
        if (response.statusCode() >= 400) {
            throw new RuntimeException("HTTP error: " + response.statusCode());
        }
        
        return response.body();
    }
    
    public String post(String url, String json) throws Exception {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .header("Content-Type", "application/json")
            .header("Accept", "application/json")
            .timeout(Duration.ofSeconds(30))
            .POST(HttpRequest.BodyPublishers.ofString(json))
            .build();
        
        HttpResponse<String> response = client.send(
            request, HttpResponse.BodyHandlers.ofString());
        
        return response.body();
    }
    
    public CompletableFuture<String> getAsync(String url) {
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .build();
        
        return client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
            .thenApply(HttpResponse::body);
    }
}

HttpClient sends requests, HttpRequest builds them, HttpResponse accesses data. BodyPublishers create request bodies, BodyHandlers process responses. Use HttpClient.newBuilder() for configured clients. send() for sync, sendAsync() for async. Set timeouts at client or request level. Reuse HttpClient instances—they're thread-safe.

© 2026 forEach. All rights reserved.

Privacy Policy•Terms of Service