An HTTP & SPDY client for Android and Java applications with efficient connection pooling, interceptors, and modern protocol support
—
Comprehensive response handling with status codes, headers, body access, and response chaining for redirects and caching.
Immutable HTTP response with status, headers, and body. Body is one-shot value that may be consumed only once.
/**
* An HTTP response. Instances of this class are not immutable: the response
* body is a one-shot value that may be consumed only once.
*/
public final class Response {
public Request request();
public Protocol protocol();
public int code();
public boolean isSuccessful();
public String message();
public Handshake handshake();
public List<String> headers(String name);
public String header(String name);
public String header(String name, String defaultValue);
public Headers headers();
public ResponseBody body();
public Builder newBuilder();
public boolean isRedirect();
public Response networkResponse();
public Response cacheResponse();
public Response priorResponse();
public List<Challenge> challenges();
public CacheControl cacheControl();
}Basic Usage:
Response response = client.newCall(request).execute();
try {
if (response.isSuccessful()) {
String responseBody = response.body().string();
System.out.println("Response: " + responseBody);
} else {
System.err.println("Request failed: " + response.code() + " " + response.message());
}
} finally {
response.body().close();
}Check response status and handle different HTTP status codes.
/**
* Returns the HTTP status code.
* @return the status code (200, 404, 500, etc.)
*/
public int code();
/**
* Returns true if the code is in [200..300), which means the request was
* successfully received, understood, and accepted.
* @return true if successful
*/
public boolean isSuccessful();
/**
* Returns the HTTP status message or null if it is unknown.
* @return the status message
*/
public String message();
/**
* Returns true if this response redirects to another resource.
* @return true if this is a redirect response
*/
public boolean isRedirect();Usage Examples:
Response response = client.newCall(request).execute();
switch (response.code()) {
case 200:
// Success
String data = response.body().string();
break;
case 401:
// Unauthorized
System.err.println("Authentication required");
break;
case 404:
// Not found
System.err.println("Resource not found");
break;
case 500:
// Server error
System.err.println("Server error: " + response.message());
break;
default:
if (response.isSuccessful()) {
// Other 2xx codes
String data = response.body().string();
} else {
// Other error codes
System.err.println("Request failed: " + response.code());
}
}
// Check for redirects
if (response.isRedirect()) {
String location = response.header("Location");
System.out.println("Redirected to: " + location);
}Access response headers with various helper methods.
/**
* Returns all values for the specified header name.
* @param name the header name (case-insensitive)
* @return list of header values
*/
public List<String> headers(String name);
/**
* Returns the value of the specified header, or null if not present.
* @param name the header name (case-insensitive)
* @return the header value or null
*/
public String header(String name);
/**
* Returns the value of the specified header, or defaultValue if not present.
* @param name the header name (case-insensitive)
* @param defaultValue the default value to return
* @return the header value or defaultValue
*/
public String header(String name, String defaultValue);
/**
* Returns all response headers.
* @return the Headers object
*/
public Headers headers();Usage Examples:
Response response = client.newCall(request).execute();
// Get single header
String contentType = response.header("Content-Type");
String contentLength = response.header("Content-Length", "0");
// Get multiple header values
List<String> setCookies = response.headers("Set-Cookie");
// Access all headers
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
System.out.println(headers.name(i) + ": " + headers.value(i));
}
// Check specific headers
String server = response.header("Server");
String lastModified = response.header("Last-Modified");
String etag = response.header("ETag");Access response body using various methods with proper resource management.
/**
* Returns the response body.
* @return the ResponseBody (must be closed after use)
*/
public ResponseBody body();Usage Examples:
Response response = client.newCall(request).execute();
try {
ResponseBody body = response.body();
// Get as string (consumes the body)
String content = body.string();
// Alternative: Get as bytes
// byte[] bytes = body.bytes();
// Alternative: Get as InputStream
// InputStream inputStream = body.byteStream();
// Alternative: Get as Reader
// Reader reader = body.charStream();
// Get content type and length
MediaType contentType = body.contentType();
long contentLength = body.contentLength();
} finally {
response.body().close(); // Important: always close
}Get information about the HTTP protocol used for the response.
/**
* Returns the HTTP protocol, such as Protocol.HTTP_1_1 or Protocol.HTTP_2.
* @return the Protocol used
*/
public Protocol protocol();Usage Examples:
Response response = client.newCall(request).execute();
Protocol protocol = response.protocol();
switch (protocol) {
case HTTP_1_0:
System.out.println("Using HTTP/1.0");
break;
case HTTP_1_1:
System.out.println("Using HTTP/1.1");
break;
case SPDY_3:
System.out.println("Using SPDY/3.1");
break;
case HTTP_2:
System.out.println("Using HTTP/2");
break;
}Access TLS handshake information for HTTPS responses.
/**
* Returns the TLS handshake of the connection that carried this response,
* or null if the response was received without TLS.
* @return the Handshake or null
*/
public Handshake handshake();Usage Examples:
Response response = client.newCall(request).execute();
Handshake handshake = response.handshake();
if (handshake != null) {
// HTTPS connection
String cipherSuite = handshake.cipherSuite();
List<Certificate> peerCerts = handshake.peerCertificates();
List<Certificate> localCerts = handshake.localCertificates();
System.out.println("Cipher Suite: " + cipherSuite);
System.out.println("Peer Certificates: " + peerCerts.size());
} else {
// HTTP connection
System.out.println("No TLS handshake (HTTP connection)");
}Access the original request that generated this response.
/**
* The wire-level request that initiated this HTTP response. This is not
* necessarily the same request issued by the application.
* @return the Request
*/
public Request request();Usage Examples:
Response response = client.newCall(request).execute();
Request originalRequest = response.request();
// Compare original vs final request (after redirects/auth)
System.out.println("Original URL: " + request.urlString());
System.out.println("Final URL: " + originalRequest.urlString());
// Check if request was modified
if (!request.urlString().equals(originalRequest.urlString())) {
System.out.println("Request was redirected");
}Access information about response chains from redirects and caching.
/**
* Returns the raw response received from the network. Will be null if this
* response didn't use the network, such as when the response is fully cached.
* @return the network Response or null
*/
public Response networkResponse();
/**
* Returns the raw response received from the cache. Will be null if this
* response didn't use the cache.
* @return the cache Response or null
*/
public Response cacheResponse();
/**
* Returns the response for the HTTP redirect or authorization challenge that
* triggered this response, or null if this response wasn't triggered by an
* automatic retry.
* @return the prior Response or null
*/
public Response priorResponse();Usage Examples:
Response response = client.newCall(request).execute();
// Check if response came from cache
Response cacheResponse = response.cacheResponse();
Response networkResponse = response.networkResponse();
if (cacheResponse != null && networkResponse == null) {
System.out.println("Response served from cache");
} else if (cacheResponse == null && networkResponse != null) {
System.out.println("Response served from network");
} else if (cacheResponse != null && networkResponse != null) {
System.out.println("Conditional request: cache validated with network");
}
// Check redirect chain
Response prior = response.priorResponse();
int redirectCount = 0;
while (prior != null) {
redirectCount++;
System.out.println("Redirect " + redirectCount + ": " + prior.request().urlString());
prior = prior.priorResponse();
}Handle authentication challenges from 401/407 responses.
/**
* Returns the authorization challenges appropriate for this response's code.
* If the response code is 401 unauthorized, this returns the
* "WWW-Authenticate" challenges. If the response code is 407 proxy
* unauthorized, this returns the "Proxy-Authenticate" challenges.
* @return list of Challenge objects
*/
public List<Challenge> challenges();Usage Examples:
Response response = client.newCall(request).execute();
if (response.code() == 401 || response.code() == 407) {
List<Challenge> challenges = response.challenges();
for (Challenge challenge : challenges) {
String scheme = challenge.getScheme();
String realm = challenge.getRealm();
System.out.println("Auth challenge: " + scheme + " realm=" + realm);
if ("Basic".equalsIgnoreCase(scheme)) {
// Handle Basic authentication
String credentials = Credentials.basic("username", "password");
// Retry request with credentials...
}
}
}Access cache control directives from the response.
/**
* Returns the cache control directives for this response. This is never null,
* even if this response contains no Cache-Control header.
* @return the CacheControl object
*/
public CacheControl cacheControl();Usage Examples:
Response response = client.newCall(request).execute();
CacheControl cacheControl = response.cacheControl();
// Check cache directives
if (cacheControl.noCache()) {
System.out.println("Response should not be cached");
}
if (cacheControl.noStore()) {
System.out.println("Response should not be stored");
}
int maxAge = cacheControl.maxAgeSeconds();
if (maxAge != -1) {
System.out.println("Response valid for " + maxAge + " seconds");
}Create modified responses using the builder pattern.
/**
* Returns a new Builder based on this response.
* @return a new Builder with this response's configuration
*/
public Builder newBuilder();Usage Examples:
Response originalResponse = client.newCall(request).execute();
// Create modified response (e.g., in an interceptor)
Response modifiedResponse = originalResponse.newBuilder()
.header("Custom-Header", "Custom-Value")
.build();
// Note: This is typically used in interceptors to modify responsesInstall with Tessl CLI
npx tessl i tessl/maven-com-squareup-okhttp--okhttp