All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.squareup.okhttp.Response Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2013 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.okhttp;

import com.squareup.okhttp.internal.http.OkHeaders;
import java.util.Collections;
import java.util.List;

import static com.squareup.okhttp.internal.http.StatusLine.HTTP_PERM_REDIRECT;
import static com.squareup.okhttp.internal.http.StatusLine.HTTP_TEMP_REDIRECT;
import static java.net.HttpURLConnection.HTTP_MOVED_PERM;
import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
import static java.net.HttpURLConnection.HTTP_MULT_CHOICE;
import static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
import static java.net.HttpURLConnection.HTTP_SEE_OTHER;
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;

/**
 * An HTTP response. Instances of this class are not immutable: the response
 * body is a one-shot value that may be consumed only once. All other properties
 * are immutable.
 */
public final class Response {
  private final Request request;
  private final Protocol protocol;
  private final int code;
  private final String message;
  private final Handshake handshake;
  private final Headers headers;
  private final ResponseBody body;
  private Response networkResponse;
  private Response cacheResponse;
  private final Response priorResponse;

  private volatile CacheControl cacheControl; // Lazily initialized.

  private Response(Builder builder) {
    this.request = builder.request;
    this.protocol = builder.protocol;
    this.code = builder.code;
    this.message = builder.message;
    this.handshake = builder.handshake;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.networkResponse = builder.networkResponse;
    this.cacheResponse = builder.cacheResponse;
    this.priorResponse = builder.priorResponse;
  }

  /**
   * The wire-level request that initiated this HTTP response. This is not
   * necessarily the same request issued by the application:
   * 
    *
  • It may be transformed by the HTTP client. For example, the client * may copy headers like {@code Content-Length} from the request body. *
  • It may be the request generated in response to an HTTP redirect or * authentication challenge. In this case the request URL may be * different than the initial request URL. *
*/ public Request request() { return request; } /** * Returns the HTTP protocol, such as {@link Protocol#HTTP_1_1} or {@link * Protocol#HTTP_1_0}. */ public Protocol protocol() { return protocol; } /** Returns the HTTP status code. */ public int code() { return code; } /** * Returns true if the code is in [200..300), which means the request was * successfully received, understood, and accepted. */ public boolean isSuccessful() { return code >= 200 && code < 300; } /** Returns the HTTP status message or null if it is unknown. */ public String message() { return message; } /** * Returns the TLS handshake of the connection that carried this response, or * null if the response was received without TLS. */ public Handshake handshake() { return handshake; } public List headers(String name) { return headers.values(name); } public String header(String name) { return header(name, null); } public String header(String name, String defaultValue) { String result = headers.get(name); return result != null ? result : defaultValue; } public Headers headers() { return headers; } public ResponseBody body() { return body; } public Builder newBuilder() { return new Builder(this); } /** Returns true if this response redirects to another resource. */ public boolean isRedirect() { switch (code) { case HTTP_PERM_REDIRECT: case HTTP_TEMP_REDIRECT: case HTTP_MULT_CHOICE: case HTTP_MOVED_PERM: case HTTP_MOVED_TEMP: case HTTP_SEE_OTHER: return true; default: return false; } } /** * 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. * The body of the returned response should not be read. */ public Response networkResponse() { return networkResponse; } /** * Returns the raw response received from the cache. Will be null if this * response didn't use the cache. For conditional get requests the cache * response and network response may both be non-null. The body of the * returned response should not be read. */ public Response cacheResponse() { return 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. The body of the returned response should not be read * because it has already been consumed by the redirecting client. */ public Response priorResponse() { return priorResponse; } /** * 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. Otherwise * this returns an empty list of challenges. */ public List challenges() { String responseField; if (code == HTTP_UNAUTHORIZED) { responseField = "WWW-Authenticate"; } else if (code == HTTP_PROXY_AUTH) { responseField = "Proxy-Authenticate"; } else { return Collections.emptyList(); } return OkHeaders.parseChallenges(headers(), responseField); } /** * Returns the cache control directives for this response. This is never null, * even if this response contains no {@code Cache-Control} header. */ public CacheControl cacheControl() { CacheControl result = cacheControl; return result != null ? result : (cacheControl = CacheControl.parse(headers)); } @Override public String toString() { return "Response{protocol=" + protocol + ", code=" + code + ", message=" + message + ", url=" + request.urlString() + '}'; } public static class Builder { private Request request; private Protocol protocol; private int code = -1; private String message; private Handshake handshake; private Headers.Builder headers; private ResponseBody body; private Response networkResponse; private Response cacheResponse; private Response priorResponse; public Builder() { headers = new Headers.Builder(); } private Builder(Response response) { this.request = response.request; this.protocol = response.protocol; this.code = response.code; this.message = response.message; this.handshake = response.handshake; this.headers = response.headers.newBuilder(); this.body = response.body; this.networkResponse = response.networkResponse; this.cacheResponse = response.cacheResponse; this.priorResponse = response.priorResponse; } public Builder request(Request request) { this.request = request; return this; } public Builder protocol(Protocol protocol) { this.protocol = protocol; return this; } public Builder code(int code) { this.code = code; return this; } public Builder message(String message) { this.message = message; return this; } public Builder handshake(Handshake handshake) { this.handshake = handshake; return this; } /** * Sets the header named {@code name} to {@code value}. If this request * already has any headers with that name, they are all replaced. */ public Builder header(String name, String value) { headers.set(name, value); return this; } /** * Adds a header with {@code name} and {@code value}. Prefer this method for * multiply-valued headers like "Set-Cookie". */ public Builder addHeader(String name, String value) { headers.add(name, value); return this; } public Builder removeHeader(String name) { headers.removeAll(name); return this; } /** Removes all headers on this builder and adds {@code headers}. */ public Builder headers(Headers headers) { this.headers = headers.newBuilder(); return this; } public Builder body(ResponseBody body) { this.body = body; return this; } public Builder networkResponse(Response networkResponse) { if (networkResponse != null) checkSupportResponse("networkResponse", networkResponse); this.networkResponse = networkResponse; return this; } public Builder cacheResponse(Response cacheResponse) { if (cacheResponse != null) checkSupportResponse("cacheResponse", cacheResponse); this.cacheResponse = cacheResponse; return this; } private void checkSupportResponse(String name, Response response) { if (response.body != null) { throw new IllegalArgumentException(name + ".body != null"); } else if (response.networkResponse != null) { throw new IllegalArgumentException(name + ".networkResponse != null"); } else if (response.cacheResponse != null) { throw new IllegalArgumentException(name + ".cacheResponse != null"); } else if (response.priorResponse != null) { throw new IllegalArgumentException(name + ".priorResponse != null"); } } public Builder priorResponse(Response priorResponse) { if (priorResponse != null) checkPriorResponse(priorResponse); this.priorResponse = priorResponse; return this; } private void checkPriorResponse(Response response) { if (response.body != null) { throw new IllegalArgumentException("priorResponse.body != null"); } } public Response build() { if (request == null) throw new IllegalStateException("request == null"); if (protocol == null) throw new IllegalStateException("protocol == null"); if (code < 0) throw new IllegalStateException("code < 0: " + code); return new Response(this); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy