Eclipse Jetty HTTP Client - A lightweight, asynchronous HTTP client library that supports HTTP/1.1, HTTP/2, WebSocket, and various authentication mechanisms, proxy configurations, and connection pooling strategies.
—
The content management capability provides flexible content handling for request bodies and response processing, supporting strings, byte arrays, streams, files, forms, and multipart data with both synchronous and asynchronous content delivery.
The base interface for all request content types.
public interface Request.Content {
String getContentType();
long getLength();
boolean isReproducible();
}Handle text-based request content including JSON, XML, and plain text.
public class StringRequestContent implements Request.Content {
public StringRequestContent(String content);
public StringRequestContent(String content, Charset charset);
public StringRequestContent(String contentType, String content);
public StringRequestContent(String contentType, String content, Charset charset);
public String getString();
public Charset getCharset();
}// Simple string content
StringRequestContent content = new StringRequestContent("Hello, World!");
// JSON content with explicit content type
String jsonData = "{\"name\":\"John\",\"age\":30}";
StringRequestContent jsonContent = new StringRequestContent("application/json", jsonData);
// XML content with custom charset
String xmlData = "<?xml version=\"1.0\"?><user><name>John</name></user>";
StringRequestContent xmlContent = new StringRequestContent(
"application/xml",
xmlData,
StandardCharsets.UTF_8
);
// Send with request
ContentResponse response = client.POST("https://api.example.com/users")
.content(jsonContent)
.send();Handle binary data including byte arrays and ByteBuffers.
public class BytesRequestContent implements Request.Content {
public BytesRequestContent(byte[] bytes);
public BytesRequestContent(String contentType, byte[] bytes);
public BytesRequestContent(byte[]... bytes);
public BytesRequestContent(String contentType, byte[]... bytes);
public byte[] getBytes();
}public class ByteBufferRequestContent implements Request.Content {
public ByteBufferRequestContent(ByteBuffer... buffers);
public ByteBufferRequestContent(String contentType, ByteBuffer... buffers);
public ByteBuffer[] getByteBuffers();
}// Binary data from byte array
byte[] imageData = Files.readAllBytes(Paths.get("image.png"));
BytesRequestContent imageContent = new BytesRequestContent("image/png", imageData);
// Multiple byte arrays
byte[] header = "HEADER".getBytes();
byte[] body = "BODY".getBytes();
BytesRequestContent multiContent = new BytesRequestContent("application/octet-stream", header, body);
// ByteBuffer content
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("Binary data".getBytes());
buffer.flip();
ByteBufferRequestContent bufferContent = new ByteBufferRequestContent("application/octet-stream", buffer);
// Send binary content
ContentResponse response = client.POST("https://api.example.com/upload")
.content(imageContent)
.send();Handle streaming data from InputStreams and OutputStreams.
public class InputStreamRequestContent implements Request.Content {
public InputStreamRequestContent(InputStream stream);
public InputStreamRequestContent(String contentType, InputStream stream);
public InputStreamRequestContent(InputStream stream, long contentLength);
public InputStreamRequestContent(String contentType, InputStream stream, long contentLength);
public InputStream getInputStream();
}public class OutputStreamRequestContent implements Request.Content {
public OutputStreamRequestContent();
public OutputStreamRequestContent(String contentType);
public OutputStream getOutputStream();
public void close();
}// Upload file via InputStream
try (FileInputStream fileStream = new FileInputStream("document.pdf")) {
InputStreamRequestContent streamContent = new InputStreamRequestContent(
"application/pdf",
fileStream,
new File("document.pdf").length()
);
ContentResponse response = client.POST("https://api.example.com/documents")
.content(streamContent)
.send();
}
// Generate content via OutputStream
OutputStreamRequestContent outputContent = new OutputStreamRequestContent("text/csv");
// Write data to the OutputStream in a background thread
CompletableFuture.runAsync(() -> {
try (OutputStream out = outputContent.getOutputStream();
PrintWriter writer = new PrintWriter(out)) {
writer.println("Name,Age,Email");
writer.println("John,30,john@example.com");
writer.println("Jane,25,jane@example.com");
} catch (IOException e) {
throw new RuntimeException(e);
}
});
ContentResponse response = client.POST("https://api.example.com/data")
.content(outputContent)
.send();Handle file uploads with automatic content type detection.
public class PathRequestContent implements Request.Content {
public PathRequestContent(Path file);
public PathRequestContent(String contentType, Path file);
public PathRequestContent(Path file, ByteBufferPool bufferPool);
public PathRequestContent(String contentType, Path file, ByteBufferPool bufferPool);
public Path getPath();
}// Simple file upload
Path documentPath = Paths.get("/path/to/document.pdf");
PathRequestContent fileContent = new PathRequestContent(documentPath);
// File upload with explicit content type
PathRequestContent imageContent = new PathRequestContent("image/jpeg", documentPath);
// Upload the file
ContentResponse response = client.POST("https://api.example.com/upload")
.content(fileContent)
.send();
// Alternative: Direct file method on Request
ContentResponse response2 = client.POST("https://api.example.com/upload")
.file(documentPath)
.send();Handle HTML form submissions including URL-encoded and multipart forms.
public class FormRequestContent implements Request.Content {
public FormRequestContent(Fields fields);
public FormRequestContent(Fields fields, Charset charset);
public Fields getFields();
public Charset getCharset();
}// Create form fields
Fields fields = new Fields();
fields.add("username", "john.doe");
fields.add("password", "secret123");
fields.add("remember", "true");
// Create form content
FormRequestContent formContent = new FormRequestContent(fields);
// Submit form
ContentResponse response = client.POST("https://example.com/login")
.content(formContent)
.send();
// Form with custom charset
FormRequestContent utf8Form = new FormRequestContent(fields, StandardCharsets.UTF_8);Handle multipart form submissions including file uploads and mixed content types.
public class MultiPartRequestContent implements Request.Content {
public MultiPartRequestContent();
public MultiPartRequestContent(String boundary);
public MultiPartRequestContent addPart(MultiPart.Part part);
public MultiPartRequestContent addFieldPart(String name, ContentSource content, HttpFields headers);
public MultiPartRequestContent addFilePart(String name, String fileName, ContentSource content, HttpFields headers);
public void close();
public String getBoundary();
}// Create multipart content
MultiPartRequestContent multipart = new MultiPartRequestContent();
// Add text field
multipart.addFieldPart("description",
new StringContentSource("Document upload"),
null);
// Add file upload
Path filePath = Paths.get("/path/to/document.pdf");
multipart.addFilePart("file",
"document.pdf",
new PathContentSource(filePath),
HttpFields.build().add("Content-Type", "application/pdf"));
// Add another text field
multipart.addFieldPart("category",
new StringContentSource("documents"),
null);
// Submit multipart form
ContentResponse response = client.POST("https://api.example.com/upload")
.content(multipart)
.send();
// Always close multipart content
multipart.close();MultiPartRequestContent multipart = new MultiPartRequestContent();
// Add JSON metadata
String jsonMetadata = "{\"title\":\"My Document\",\"tags\":[\"important\",\"draft\"]}";
multipart.addFieldPart("metadata",
new StringContentSource(jsonMetadata),
HttpFields.build().add("Content-Type", "application/json"));
// Add multiple files
Path[] files = {
Paths.get("/path/to/document.pdf"),
Paths.get("/path/to/image.png")
};
for (int i = 0; i < files.length; i++) {
Path file = files[i];
String fileName = file.getFileName().toString();
String contentType = Files.probeContentType(file);
multipart.addFilePart("files",
fileName,
new PathContentSource(file),
HttpFields.build().add("Content-Type", contentType));
}
try {
ContentResponse response = client.POST("https://api.example.com/bulk-upload")
.content(multipart)
.send();
System.out.println("Upload completed: " + response.getStatus());
} finally {
multipart.close();
}Handle content that is generated asynchronously or streamed over time.
public class AsyncRequestContent implements Request.Content {
public AsyncRequestContent();
public AsyncRequestContent(String contentType);
public void offer(ByteBuffer buffer);
public void offer(ByteBuffer buffer, Callback callback);
public void close();
public boolean isClosed();
public void fail(Throwable failure);
}// Create async content
AsyncRequestContent asyncContent = new AsyncRequestContent("text/plain");
// Start the request (non-blocking)
CompletableFuture<ContentResponse> future = client.POST("https://api.example.com/stream")
.content(asyncContent)
.send();
// Generate content asynchronously
CompletableFuture.runAsync(() -> {
try {
for (int i = 0; i < 10; i++) {
String data = "Chunk " + i + "\n";
ByteBuffer buffer = ByteBuffer.wrap(data.getBytes());
asyncContent.offer(buffer);
Thread.sleep(100); // Simulate processing time
}
} catch (InterruptedException e) {
asyncContent.fail(e);
Thread.currentThread().interrupt();
} finally {
asyncContent.close();
}
});
// Wait for response
ContentResponse response = future.get(30, TimeUnit.SECONDS);public class DataStreamer {
private final AsyncRequestContent content;
private final CompletableFuture<ContentResponse> responseFuture;
public DataStreamer(HttpClient client, String url) {
this.content = new AsyncRequestContent("application/json");
this.responseFuture = client.POST(url)
.content(content)
.send();
}
public void sendData(Object data) {
try {
String json = objectMapper.writeValueAsString(data);
ByteBuffer buffer = ByteBuffer.wrap(json.getBytes(StandardCharsets.UTF_8));
content.offer(buffer);
} catch (Exception e) {
content.fail(e);
}
}
public void finish() {
content.close();
}
public ContentResponse waitForResponse() throws Exception {
return responseFuture.get(60, TimeUnit.SECONDS);
}
}
// Usage
DataStreamer streamer = new DataStreamer(client, "https://api.example.com/realtime");
// Send data over time
for (SensorReading reading : sensorReadings) {
streamer.sendData(reading);
Thread.sleep(1000); // Send every second
}
streamer.finish();
ContentResponse response = streamer.waitForResponse();Integration with Jetty's Content.Source system for advanced content handling.
public class ContentSourceRequestContent implements Request.Content {
public ContentSourceRequestContent(Content.Source contentSource);
public ContentSourceRequestContent(String contentType, Content.Source contentSource);
public Content.Source getContentSource();
}// Custom content source that generates data
Content.Source customSource = new Content.Source() {
private int count = 0;
@Override
public Content.Chunk read() {
if (count >= 5) {
return Content.Chunk.EOF;
}
String data = "Generated data " + (++count) + "\n";
ByteBuffer buffer = ByteBuffer.wrap(data.getBytes());
return Content.Chunk.from(buffer);
}
@Override
public void demand(Runnable demandCallback) {
// Immediately signal data availability
demandCallback.run();
}
};
ContentSourceRequestContent sourceContent = new ContentSourceRequestContent(
"text/plain",
customSource
);
ContentResponse response = client.POST("https://api.example.com/custom")
.content(sourceContent)
.send();// For content with known length
byte[] data = "Known size content".getBytes();
BytesRequestContent content = new BytesRequestContent("text/plain", data);
// Length is automatically set to data.length
// For streaming content with unknown length
InputStream stream = new FileInputStream("largefile.dat");
InputStreamRequestContent streamContent = new InputStreamRequestContent("application/octet-stream", stream);
// Uses chunked transfer encoding
// For streaming content with known length
long fileSize = Files.size(Paths.get("largefile.dat"));
InputStreamRequestContent sizedStreamContent = new InputStreamRequestContent(
"application/octet-stream",
stream,
fileSize
);// Explicit content types for better server processing
StringRequestContent jsonContent = new StringRequestContent(
"application/json; charset=utf-8",
jsonData
);
// Use proper MIME types for files
Path imagePath = Paths.get("photo.jpg");
String mimeType = Files.probeContentType(imagePath);
PathRequestContent imageContent = new PathRequestContent(mimeType, imagePath);
// Custom content types for specific APIs
BytesRequestContent customContent = new BytesRequestContent(
"application/vnd.api+json",
jsonApiData.getBytes()
);// For large files, prefer streaming over loading into memory
Path largeFile = Paths.get("large-dataset.csv");
// Good: Streaming approach
PathRequestContent fileContent = new PathRequestContent("text/csv", largeFile);
// Avoid: Loading entire file into memory
byte[] fileBytes = Files.readAllBytes(largeFile); // Can cause OutOfMemoryError
BytesRequestContent memoryContent = new BytesRequestContent("text/csv", fileBytes);Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-client