Service Provider Interface (SPI) for HTTP client implementations in the AWS SDK for Java v2
Immutable HTTP message representations including requests, responses, headers, and execution models. All message objects use builder patterns for construction and provide comprehensive configuration options while maintaining thread safety.
Base interface for HTTP requests containing all request metadata except the body content.
/**
* Base interface for HTTP requests containing all request metadata
*/
public interface SdkHttpRequest extends SdkHttpHeaders {
/**
* @return HTTP protocol (http or https)
*/
String protocol();
/**
* @return Request host
*/
String host();
/**
* @return Request port
*/
int port();
/**
* @return URL-encoded path component
*/
String encodedPath();
/**
* @return Optional URL-encoded query parameters as single string
*/
Optional<String> encodedQueryParameters();
/**
* @return Raw query parameters as map of parameter names to value lists
*/
Map<String, List<String>> rawQueryParameters();
/**
* @return HTTP method for this request
*/
SdkHttpMethod method();
/**
* @return Complete request URI constructed from components
*/
URI getUri();
/**
* @return Builder for creating modified copies of this request
*/
Builder toBuilder();
}HTTP request interface that extends SdkHttpRequest to include optional body content via ContentStreamProvider.
/**
* HTTP request with optional body content
*/
public interface SdkHttpFullRequest extends SdkHttpRequest {
/**
* @return Optional content stream provider for request body
*/
Optional<ContentStreamProvider> contentStreamProvider();
/**
* @return Builder for creating modified copies of this request
*/
SdkHttpFullRequest.Builder toBuilder();
/**
* @return New builder for constructing HTTP requests
*/
static Builder builder();
}Usage Example:
// Create a POST request with JSON body
SdkHttpFullRequest request = SdkHttpFullRequest.builder()
.method(SdkHttpMethod.POST)
.protocol("https")
.host("api.example.com")
.port(443)
.encodedPath("/v1/users")
.putHeader("Content-Type", "application/json")
.putHeader("Authorization", "Bearer " + token)
.contentStreamProvider(ContentStreamProvider.fromUtf8String(
"{\"name\":\"John\",\"email\":\"john@example.com\"}"
))
.build();
// Create a GET request with query parameters
SdkHttpFullRequest getRequest = SdkHttpFullRequest.builder()
.method(SdkHttpMethod.GET)
.protocol("https")
.host("api.example.com")
.port(443)
.encodedPath("/v1/users")
.putRawQueryParameter("page", "1")
.putRawQueryParameter("size", "10")
.putRawQueryParameter("sort", "name")
.putHeader("Accept", "application/json")
.build();Builder interface for constructing SdkHttpFullRequest instances with fluent API.
/**
* Builder for constructing SdkHttpFullRequest instances
*/
public interface Builder extends SdkHttpRequest.Builder {
/**
* Set the HTTP method for this request
*/
Builder method(SdkHttpMethod method);
/**
* Set the protocol (http or https)
*/
Builder protocol(String protocol);
/**
* Set the target host
*/
Builder host(String host);
/**
* Set the target port
*/
Builder port(int port);
/**
* Set the URL-encoded path
*/
Builder encodedPath(String encodedPath);
/**
* Add a raw query parameter (will be URL-encoded)
*/
Builder putRawQueryParameter(String parameterName, String parameterValue);
/**
* Add multiple values for a raw query parameter
*/
Builder putRawQueryParameter(String parameterName, List<String> parameterValues);
/**
* Set all raw query parameters, replacing existing ones
*/
Builder rawQueryParameters(Map<String, List<String>> rawQueryParameters);
/**
* Remove a query parameter
*/
Builder removeQueryParameter(String parameterName);
/**
* Clear all query parameters
*/
Builder clearQueryParameters();
/**
* Add an HTTP header
*/
Builder putHeader(String headerName, String headerValue);
/**
* Add multiple values for an HTTP header
*/
Builder putHeader(String headerName, List<String> headerValues);
/**
* Add all headers from a map
*/
Builder headers(Map<String, List<String>> headers);
/**
* Remove an HTTP header
*/
Builder removeHeader(String headerName);
/**
* Clear all HTTP headers
*/
Builder clearHeaders();
/**
* Set the content stream provider for request body
*/
Builder contentStreamProvider(ContentStreamProvider contentStreamProvider);
/**
* Build the SdkHttpFullRequest
*/
SdkHttpFullRequest build();
}Base interface for HTTP responses containing status information and headers, but without access to the response body.
/**
* HTTP response without body access
*/
public interface SdkHttpResponse extends SdkHttpHeaders {
/**
* @return HTTP status code (always positive)
*/
int statusCode();
/**
* @return Optional HTTP status text if provided by service
*/
Optional<String> statusText();
/**
* @return true for 2xx status codes, false otherwise
*/
boolean isSuccessful();
/**
* @return Builder for creating modified copies of this response
*/
Builder toBuilder();
/**
* @return New builder for constructing HTTP responses
*/
static Builder builder();
}HTTP response interface that extends SdkHttpResponse to include access to the response body stream.
/**
* HTTP response with body access
*/
public interface SdkHttpFullResponse extends SdkHttpResponse {
/**
* @return Optional response body stream (must be closed by caller)
*/
Optional<AbortableInputStream> content();
/**
* @return Builder for creating modified copies of this response
*/
SdkHttpFullResponse.Builder toBuilder();
/**
* @return New builder for constructing HTTP responses with body
*/
static Builder builder();
}Interface providing access to HTTP headers with utility methods for case-insensitive header operations.
/**
* Immutable set of HTTP headers with utility methods
*/
public interface SdkHttpHeaders {
/**
* @return All HTTP headers as case-insensitive sorted map
*/
Map<String, List<String>> headers();
/**
* Find first matching header (case-insensitive)
* @param header Header name to search for
* @return First matching header value, or empty if not found
*/
Optional<String> firstMatchingHeader(String header);
/**
* Get all matching headers (case-insensitive)
* @param header Header name to search for
* @return List of all matching header values
*/
List<String> matchingHeaders(String header);
/**
* Check if any header matches the given predicate
* @param predicate Predicate to test header names against
* @return true if any header matches, false otherwise
*/
boolean anyMatchingHeader(Predicate<String> predicate);
/**
* Iterate over all headers with a consumer function
* @param consumer Function to accept header name and values
*/
void forEachHeader(BiConsumer<String, List<String>> consumer);
/**
* @return Number of headers
*/
int numHeaders();
}Usage Example:
// Working with response headers
SdkHttpResponse response = // ... received from HTTP call
// Check content type
Optional<String> contentType = response.firstMatchingHeader("Content-Type");
if (contentType.isPresent() && contentType.get().startsWith("application/json")) {
// Handle JSON response
}
// Get all cache control directives
List<String> cacheControl = response.matchingHeaders("Cache-Control");
// Check for specific headers
boolean hasETag = response.anyMatchingHeader(header ->
header.equalsIgnoreCase("ETag"));
// Iterate all headers
response.forEachHeader((name, values) -> {
System.out.println(name + ": " + String.join(", ", values));
});/**
* Enumeration of supported HTTP methods
*/
public enum SdkHttpMethod {
GET, POST, PUT, DELETE, HEAD, PATCH, OPTIONS
}/**
* HTTP status code families for response categorization
*/
public enum HttpStatusFamily {
INFORMATIONAL(100, 199),
SUCCESSFUL(200, 299),
REDIRECTION(300, 399),
CLIENT_ERROR(400, 499),
SERVER_ERROR(500, 599),
OTHER(0, 99);
/**
* Get the status family for a given status code
* @param statusCode HTTP status code
* @return Corresponding HttpStatusFamily
*/
public static HttpStatusFamily of(int statusCode);
}
/**
* Common HTTP status code constants
*/
public final class HttpStatusCode {
public static final int OK = 200;
public static final int CREATED = 201;
public static final int ACCEPTED = 202;
public static final int NO_CONTENT = 204;
public static final int MOVED_PERMANENTLY = 301;
public static final int FOUND = 302;
public static final int NOT_MODIFIED = 304;
public static final int BAD_REQUEST = 400;
public static final int UNAUTHORIZED = 401;
public static final int FORBIDDEN = 403;
public static final int NOT_FOUND = 404;
public static final int METHOD_NOT_ALLOWED = 405;
public static final int CONFLICT = 409;
public static final int INTERNAL_SERVER_ERROR = 500;
public static final int BAD_GATEWAY = 502;
public static final int SERVICE_UNAVAILABLE = 503;
public static final int GATEWAY_TIMEOUT = 504;
}HTTP execution model for synchronous client operations.
/**
* Request object for synchronous HTTP execution
*/
public final class HttpExecuteRequest {
/**
* @return The HTTP request to execute
*/
public SdkHttpRequest httpRequest();
/**
* @return Optional content stream provider for request body
*/
public Optional<ContentStreamProvider> contentStreamProvider();
/**
* @return Optional metrics collector for this request
*/
public Optional<MetricCollector> metricCollector();
/**
* @return New builder for HTTP execution requests
*/
public static Builder builder();
public interface Builder {
Builder request(SdkHttpRequest request);
Builder contentStreamProvider(ContentStreamProvider contentStreamProvider);
Builder metricCollector(MetricCollector metricCollector);
HttpExecuteRequest build();
}
}
/**
* Response object for synchronous HTTP execution
*/
public final class HttpExecuteResponse {
/**
* @return The HTTP response
*/
public SdkHttpResponse httpResponse();
/**
* @return Optional response body stream (must be closed by caller)
*/
public Optional<AbortableInputStream> responseBody();
/**
* @return New builder for HTTP execution responses
*/
public static Builder builder();
public interface Builder {
Builder response(SdkHttpResponse response);
Builder responseBody(AbortableInputStream responseBody);
HttpExecuteResponse build();
}
}Request object for asynchronous HTTP execution containing all parameters needed for async operations.
/**
* Request object containing the parameters necessary to make an asynchronous HTTP request
*/
@SdkPublicApi
public final class AsyncExecuteRequest {
/**
* @return The HTTP request to execute
*/
public SdkHttpRequest request();
/**
* @return The publisher of request body content
*/
public SdkHttpContentPublisher requestContentPublisher();
/**
* @return The response handler for processing the async response
*/
public SdkAsyncHttpResponseHandler responseHandler();
/**
* @return Optional metrics collector for this request
*/
public Optional<MetricCollector> metricCollector();
/**
* @return True if the operation is full duplex (request and response sent/received simultaneously)
*/
public boolean fullDuplex();
/**
* @return The SDK HTTP execution attributes associated with this request
*/
public SdkHttpExecutionAttributes httpExecutionAttributes();
/**
* @return New builder for async execution requests
*/
public static Builder builder();
public interface Builder {
/**
* Set the HTTP request to be executed by the client
*/
Builder request(SdkHttpRequest request);
/**
* Set the publisher of the request content
*/
Builder requestContentPublisher(SdkHttpContentPublisher requestContentPublisher);
/**
* Set the response handler for the response
*/
Builder responseHandler(SdkAsyncHttpResponseHandler responseHandler);
/**
* Set the MetricCollector to be used by the HTTP client to report metrics
*/
Builder metricCollector(MetricCollector metricCollector);
/**
* Indicate if the request is for a full duplex operation (request and response sent/received simultaneously)
*/
Builder fullDuplex(boolean fullDuplex);
/**
* Put an HTTP execution attribute into the collection of HTTP execution attributes for this request
*/
<T> Builder putHttpExecutionAttribute(SdkHttpExecutionAttribute<T> attribute, T value);
/**
* Sets the additional HTTP execution attributes collection for this request.
* This will override attributes configured through putHttpExecutionAttribute()
*/
Builder httpExecutionAttributes(SdkHttpExecutionAttributes executionAttributes);
AsyncExecuteRequest build();
}
}/**
* Common HTTP header name constants
*/
public final class Header {
public static final String ACCEPT = "Accept";
public static final String ACCEPT_CHARSET = "Accept-Charset";
public static final String ACCEPT_ENCODING = "Accept-Encoding";
public static final String ACCEPT_LANGUAGE = "Accept-Language";
public static final String AUTHORIZATION = "Authorization";
public static final String CACHE_CONTROL = "Cache-Control";
public static final String CONNECTION = "Connection";
public static final String CONTENT_ENCODING = "Content-Encoding";
public static final String CONTENT_LENGTH = "Content-Length";
public static final String CONTENT_TYPE = "Content-Type";
public static final String DATE = "Date";
public static final String ETAG = "ETag";
public static final String EXPIRES = "Expires";
public static final String HOST = "Host";
public static final String IF_MATCH = "If-Match";
public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
public static final String IF_NONE_MATCH = "If-None-Match";
public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
public static final String LAST_MODIFIED = "Last-Modified";
public static final String LOCATION = "Location";
public static final String RANGE = "Range";
public static final String SERVER = "Server";
public static final String USER_AGENT = "User-Agent";
public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
}Install with Tessl CLI
npx tessl i tessl/maven-software-amazon-awssdk--http-client-spi