1a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath/*
2a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Copyright (C) 2013 Square, Inc.
3a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *
4a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License");
5a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * you may not use this file except in compliance with the License.
6a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * You may obtain a copy of the License at
7a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *
8a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *      http://www.apache.org/licenses/LICENSE-2.0
9a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath *
10a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * Unless required by applicable law or agreed to in writing, software
11a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS,
12a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * See the License for the specific language governing permissions and
14a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * limitations under the License.
15a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath */
16a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathpackage com.squareup.okhttp;
17a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport com.squareup.okhttp.internal.http.OkHeaders;
193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.util.Collections;
20a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamathimport java.util.List;
213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
22e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static com.squareup.okhttp.internal.http.StatusLine.HTTP_PERM_REDIRECT;
23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static com.squareup.okhttp.internal.http.StatusLine.HTTP_TEMP_REDIRECT;
24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.net.HttpURLConnection.HTTP_MOVED_PERM;
25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.net.HttpURLConnection.HTTP_MULT_CHOICE;
27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.net.HttpURLConnection.HTTP_PROXY_AUTH;
28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.net.HttpURLConnection.HTTP_SEE_OTHER;
29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
30a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
31a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath/**
32a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * An HTTP response. Instances of this class are not immutable: the response
33a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * body is a one-shot value that may be consumed only once. All other properties
34a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath * are immutable.
35a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath */
363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpublic final class Response {
37a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  private final Request request;
38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final Protocol protocol;
39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final int code;
40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final String message;
413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private final Handshake handshake;
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private final Headers headers;
43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final ResponseBody body;
44f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  private Response networkResponse;
45f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  private Response cacheResponse;
46f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  private final Response priorResponse;
47a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private volatile CacheControl cacheControl; // Lazily initialized.
493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
50a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  private Response(Builder builder) {
51a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    this.request = builder.request;
52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    this.protocol = builder.protocol;
53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    this.code = builder.code;
54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    this.message = builder.message;
553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    this.handshake = builder.handshake;
563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    this.headers = builder.headers.build();
57a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    this.body = builder.body;
58f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    this.networkResponse = builder.networkResponse;
59f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    this.cacheResponse = builder.cacheResponse;
60f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    this.priorResponse = builder.priorResponse;
61a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
62a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
63a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  /**
64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * The wire-level request that initiated this HTTP response. This is not
65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * necessarily the same request issued by the application:
66a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath   * <ul>
67a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath   *     <li>It may be transformed by the HTTP client. For example, the client
68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *         may copy headers like {@code Content-Length} from the request body.
69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *     <li>It may be the request generated in response to an HTTP redirect or
70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *         authentication challenge. In this case the request URL may be
71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *         different than the initial request URL.
72a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath   * </ul>
73a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath   */
74a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  public Request request() {
75a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    return request;
76a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
77a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
78e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the HTTP protocol, such as {@link Protocol#HTTP_1_1} or {@link
80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Protocol#HTTP_1_0}.
81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public Protocol protocol() {
83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return protocol;
843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /** Returns the HTTP status code. */
87a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  public int code() {
88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return code;
89a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
90a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns true if the code is in [200..300), which means the request was
93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * successfully received, understood, and accepted.
94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
95e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public boolean isSuccessful() {
96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return code >= 200 && code < 300;
97a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
98a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /** Returns the HTTP status message or null if it is unknown. */
100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public String message() {
101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return message;
102a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
103a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
1043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
1053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Returns the TLS handshake of the connection that carried this response, or
1063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * null if the response was received without TLS.
1073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
1083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public Handshake handshake() {
1093c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return handshake;
110a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
111a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
1123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public List<String> headers(String name) {
1133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return headers.values(name);
114a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
115a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
1163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public String header(String name) {
1173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return header(name, null);
118a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
119a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
1203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public String header(String name, String defaultValue) {
1213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    String result = headers.get(name);
1223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result != null ? result : defaultValue;
123a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
124a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
1253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public Headers headers() {
1263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return headers;
127a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
128a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public ResponseBody body() {
130a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    return body;
131a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
132a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
1333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public Builder newBuilder() {
1343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return new Builder(this);
1353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /** Returns true if this response redirects to another resource. */
138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public boolean isRedirect() {
139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    switch (code) {
140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      case HTTP_PERM_REDIRECT:
141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      case HTTP_TEMP_REDIRECT:
142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      case HTTP_MULT_CHOICE:
143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      case HTTP_MOVED_PERM:
144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      case HTTP_MOVED_TEMP:
145e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      case HTTP_SEE_OTHER:
146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        return true;
147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      default:
148e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        return false;
149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
150f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  }
151f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller
152f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  /**
153f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   * Returns the raw response received from the network. Will be null if this
154f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   * response didn't use the network, such as when the response is fully cached.
155f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   * The body of the returned response should not be read.
156f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   */
157f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  public Response networkResponse() {
158f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    return networkResponse;
159f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  }
160f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller
161f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  /**
162f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   * Returns the raw response received from the cache. Will be null if this
163f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   * response didn't use the cache. For conditional get requests the cache
164f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   * response and network response may both be non-null. The body of the
165f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   * returned response should not be read.
166f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller   */
167f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller  public Response cacheResponse() {
168f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    return cacheResponse;
169a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
170a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
1713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the response for the HTTP redirect or authorization challenge that
173e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * triggered this response, or null if this response wasn't triggered by an
174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * automatic retry. The body of the returned response should not be read
175e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * because it has already been consumed by the redirecting client.
1763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
177e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public Response priorResponse() {
178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return priorResponse;
1793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
1813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * Returns the authorization challenges appropriate for this response's code.
183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * If the response code is 401 unauthorized, this returns the
184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * "WWW-Authenticate" challenges. If the response code is 407 proxy
185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * unauthorized, this returns the "Proxy-Authenticate" challenges. Otherwise
186e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * this returns an empty list of challenges.
1873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
188e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public List<Challenge> challenges() {
189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    String responseField;
190e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    if (code == HTTP_UNAUTHORIZED) {
191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      responseField = "WWW-Authenticate";
192e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } else if (code == HTTP_PROXY_AUTH) {
193e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      responseField = "Proxy-Authenticate";
194e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } else {
195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return Collections.emptyList();
196a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
197e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return OkHeaders.parseChallenges(headers(), responseField);
1983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
1993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /**
2013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * Returns the cache control directives for this response. This is never null,
2023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   * even if this response contains no {@code Cache-Control} header.
2033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller   */
2043c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  public CacheControl cacheControl() {
2053c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    CacheControl result = cacheControl;
2063c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return result != null ? result : (cacheControl = CacheControl.parse(headers));
2073c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
2083c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Override public String toString() {
210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return "Response{protocol="
211e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + protocol
212e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + ", code="
213e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + code
214e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + ", message="
215e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + message
216e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + ", url="
217e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + request.urlString()
218e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + '}';
219a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
220a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
221a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  public static class Builder {
2223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    private Request request;
223e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    private Protocol protocol;
224e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    private int code = -1;
225e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    private String message;
2263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    private Handshake handshake;
2273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    private Headers.Builder headers;
228e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    private ResponseBody body;
229f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    private Response networkResponse;
230f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    private Response cacheResponse;
231f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    private Response priorResponse;
232a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
2333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    public Builder() {
2343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      headers = new Headers.Builder();
2353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    private Builder(Response response) {
2383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.request = response.request;
239e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      this.protocol = response.protocol;
240e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      this.code = response.code;
241e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      this.message = response.message;
2423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.handshake = response.handshake;
2433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.headers = response.headers.newBuilder();
2443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.body = response.body;
245f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      this.networkResponse = response.networkResponse;
246f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      this.cacheResponse = response.cacheResponse;
247f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      this.priorResponse = response.priorResponse;
2483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    public Builder request(Request request) {
251a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      this.request = request;
2523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return this;
2533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
255e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    public Builder protocol(Protocol protocol) {
256e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      this.protocol = protocol;
2573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return this;
2583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
260e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    public Builder code(int code) {
261e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      this.code = code;
262e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return this;
263e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
264e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
265e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    public Builder message(String message) {
266e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      this.message = message;
267e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return this;
2683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    public Builder handshake(Handshake handshake) {
2713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.handshake = handshake;
2723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return this;
273a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
274a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
275a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    /**
276a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath     * Sets the header named {@code name} to {@code value}. If this request
277a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath     * already has any headers with that name, they are all replaced.
278a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath     */
279a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    public Builder header(String name, String value) {
280a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      headers.set(name, value);
281a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      return this;
282a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
283a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
284a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    /**
285a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath     * Adds a header with {@code name} and {@code value}. Prefer this method for
286a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath     * multiply-valued headers like "Set-Cookie".
287a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath     */
288a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    public Builder addHeader(String name, String value) {
289a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      headers.add(name, value);
290a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      return this;
291a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
292a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
2933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    public Builder removeHeader(String name) {
2943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      headers.removeAll(name);
2953c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return this;
2963c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
2973c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
2983c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    /** Removes all headers on this builder and adds {@code headers}. */
2993c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    public Builder headers(Headers headers) {
3003c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      this.headers = headers.newBuilder();
3013c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      return this;
3023c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
3033c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
304e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    public Builder body(ResponseBody body) {
305a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      this.body = body;
306a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      return this;
307a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
308a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
309f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    public Builder networkResponse(Response networkResponse) {
310f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      if (networkResponse != null) checkSupportResponse("networkResponse", networkResponse);
311f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      this.networkResponse = networkResponse;
312f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      return this;
313f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    }
314f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller
315f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    public Builder cacheResponse(Response cacheResponse) {
316f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      if (cacheResponse != null) checkSupportResponse("cacheResponse", cacheResponse);
317f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      this.cacheResponse = cacheResponse;
318f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      return this;
319f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    }
320f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller
321f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    private void checkSupportResponse(String name, Response response) {
322f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      if (response.body != null) {
323f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller        throw new IllegalArgumentException(name + ".body != null");
324f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      } else if (response.networkResponse != null) {
325f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller        throw new IllegalArgumentException(name + ".networkResponse != null");
326f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      } else if (response.cacheResponse != null) {
327f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller        throw new IllegalArgumentException(name + ".cacheResponse != null");
328f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      } else if (response.priorResponse != null) {
329f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller        throw new IllegalArgumentException(name + ".priorResponse != null");
330f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      }
331f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    }
332f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller
333f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller    public Builder priorResponse(Response priorResponse) {
334e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      if (priorResponse != null) checkPriorResponse(priorResponse);
335f6af62d5c9bb5e15649a80ebae973463e8e2dc46Neil Fuller      this.priorResponse = priorResponse;
336a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      return this;
337a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
338a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath
339e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    private void checkPriorResponse(Response response) {
340e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      if (response.body != null) {
341e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        throw new IllegalArgumentException("priorResponse.body != null");
342e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
343e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
344e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
345a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    public Response build() {
3463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (request == null) throw new IllegalStateException("request == null");
347e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      if (protocol == null) throw new IllegalStateException("protocol == null");
348e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      if (code < 0) throw new IllegalStateException("code < 0: " + code);
349a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath      return new Response(this);
350a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath    }
351a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath  }
352a82f42bbeedd0b07f3892f3b0efaa8122dc8f264Narayan Kamath}
353