Пример #1
0
  /**
   * Initialize the source for this response. It may be corrected later if the request headers
   * forbids network use.
   */
  private void initResponseSource() throws IOException {
    responseSource = ResponseSource.NETWORK;
    if (!policy.getUseCaches()) return;

    OkResponseCache responseCache = client.getOkResponseCache();
    if (responseCache == null) return;

    CacheResponse candidate =
        responseCache.get(uri, method, requestHeaders.getHeaders().toMultimap(false));
    if (candidate == null) return;

    Map<String, List<String>> responseHeadersMap = candidate.getHeaders();
    cachedResponseBody = candidate.getBody();
    if (!acceptCacheResponseType(candidate)
        || responseHeadersMap == null
        || cachedResponseBody == null) {
      Util.closeQuietly(cachedResponseBody);
      return;
    }

    RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap, true);
    cachedResponseHeaders = new ResponseHeaders(uri, rawResponseHeaders);
    long now = System.currentTimeMillis();
    this.responseSource = cachedResponseHeaders.chooseResponseSource(now, requestHeaders);
    if (responseSource == ResponseSource.CACHE) {
      this.cacheResponse = candidate;
      setResponse(cachedResponseHeaders, cachedResponseBody);
    } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
      this.cacheResponse = candidate;
    } else if (responseSource == ResponseSource.NETWORK) {
      Util.closeQuietly(cachedResponseBody);
    } else {
      throw new AssertionError();
    }
  }
Пример #2
0
  /**
   * Figures out what the response source will be, and opens a socket to that source if necessary.
   * Prepares the request headers and gets ready to start writing the request body if it exists.
   */
  public final void sendRequest() throws IOException {
    if (responseSource != null) {
      return;
    }

    prepareRawRequestHeaders();
    initResponseSource();
    OkResponseCache responseCache = client.getOkResponseCache();
    if (responseCache != null) {
      responseCache.trackResponse(responseSource);
    }

    // The raw response source may require the network, but the request
    // headers may forbid network use. In that case, dispose of the network
    // response and use a GATEWAY_TIMEOUT response instead, as specified
    // by http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4.
    if (requestHeaders.isOnlyIfCached() && responseSource.requiresConnection()) {
      if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
        Util.closeQuietly(cachedResponseBody);
      }
      this.responseSource = ResponseSource.CACHE;
      this.cacheResponse = GATEWAY_TIMEOUT_RESPONSE;
      RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(cacheResponse.getHeaders(), true);
      setResponse(new ResponseHeaders(uri, rawResponseHeaders), cacheResponse.getBody());
    }

    if (responseSource.requiresConnection()) {
      sendSocketRequest();
    } else if (connection != null) {
      client.getConnectionPool().recycle(connection);
      connection = null;
    }
  }
Пример #3
0
 /** Connect to the origin server either directly or via a proxy. */
 protected final void connect() throws IOException {
   if (connection != null) {
     return;
   }
   if (routeSelector == null) {
     String uriHost = uri.getHost();
     if (uriHost == null) {
       throw new UnknownHostException(uri.toString());
     }
     SSLSocketFactory sslSocketFactory = null;
     HostnameVerifier hostnameVerifier = null;
     if (uri.getScheme().equalsIgnoreCase("https")) {
       sslSocketFactory = client.getSslSocketFactory();
       hostnameVerifier = client.getHostnameVerifier();
     }
     Address address =
         new Address(
             uriHost,
             getEffectivePort(uri),
             sslSocketFactory,
             hostnameVerifier,
             client.getAuthenticator(),
             client.getProxy(),
             client.getTransports());
     routeSelector =
         new RouteSelector(
             address,
             uri,
             client.getProxySelector(),
             client.getConnectionPool(),
             Dns.DEFAULT,
             client.getRoutesDatabase());
   }
   connection = routeSelector.next(method);
   if (!connection.isConnected()) {
     connection.connect(client.getConnectTimeout(), client.getReadTimeout(), getTunnelConfig());
     client.getConnectionPool().maybeShare(connection);
     client.getRoutesDatabase().connected(connection.getRoute());
   } else if (!connection.isSpdy()) {
     connection.updateReadTimeout(client.getReadTimeout());
   }
   connected(connection);
   if (connection.getRoute().getProxy() != client.getProxy()) {
     // Update the request line if the proxy changed; it may need a host name.
     requestHeaders.getHeaders().setRequestLine(getRequestLine());
   }
 }
Пример #4
0
  /**
   * Flushes the remaining request header and body, parses the HTTP response headers and starts
   * reading the HTTP response body if it exists.
   */
  public final void readResponse() throws IOException {
    if (hasResponse()) {
      responseHeaders.setResponseSource(responseSource);
      return;
    }

    if (responseSource == null) {
      throw new IllegalStateException("readResponse() without sendRequest()");
    }

    if (!responseSource.requiresConnection()) {
      return;
    }

    if (sentRequestMillis == -1) {
      if (requestBodyOut instanceof RetryableOutputStream) {
        int contentLength = ((RetryableOutputStream) requestBodyOut).contentLength();
        requestHeaders.setContentLength(contentLength);
      }
      transport.writeRequestHeaders();
    }

    if (requestBodyOut != null) {
      requestBodyOut.close();
      if (requestBodyOut instanceof RetryableOutputStream) {
        transport.writeRequestBody((RetryableOutputStream) requestBodyOut);
      }
    }

    transport.flushRequest();

    responseHeaders = transport.readResponseHeaders();
    responseHeaders.setLocalTimestamps(sentRequestMillis, System.currentTimeMillis());
    responseHeaders.setResponseSource(responseSource);

    if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
      if (cachedResponseHeaders.validate(responseHeaders)) {
        release(false);
        ResponseHeaders combinedHeaders = cachedResponseHeaders.combine(responseHeaders);
        this.responseHeaders = combinedHeaders;

        // Update the cache after applying the combined headers but before initializing the content
        // stream, otherwise the Content-Encoding header (if present) will be stripped from the
        // combined headers and not end up in the cache file if transparent gzip compression is
        // turned on.
        OkResponseCache responseCache = client.getOkResponseCache();
        responseCache.trackConditionalCacheHit();
        responseCache.update(cacheResponse, policy.getHttpConnectionToCache());

        initContentStream(cachedResponseBody);
        return;
      } else {
        Util.closeQuietly(cachedResponseBody);
      }
    }

    if (hasResponseBody()) {
      maybeCache(); // reentrant. this calls into user code which may call back into this!
    }

    initContentStream(transport.getTransferStream(cacheRequest));
  }
Пример #5
0
  /**
   * Populates requestHeaders with defaults and cookies.
   *
   * <p>This client doesn't specify a default {@code Accept} header because it doesn't know what
   * content types the application is interested in.
   */
  private void prepareRawRequestHeaders() throws IOException {
    requestHeaders.getHeaders().setRequestLine(getRequestLine());

    if (requestHeaders.getUserAgent() == null) {
      requestHeaders.setUserAgent(getDefaultUserAgent());
    }

    if (requestHeaders.getHost() == null) {
      requestHeaders.setHost(getOriginAddress(policy.getURL()));
    }

    if ((connection == null || connection.getHttpMinorVersion() != 0)
        && requestHeaders.getConnection() == null) {
      requestHeaders.setConnection("Keep-Alive");
    }

    if (requestHeaders.getAcceptEncoding() == null) {
      transparentGzip = true;
      requestHeaders.setAcceptEncoding("gzip");
    }

    if (hasRequestBody() && requestHeaders.getContentType() == null) {
      requestHeaders.setContentType("application/x-www-form-urlencoded");
    }

    long ifModifiedSince = policy.getIfModifiedSince();
    if (ifModifiedSince != 0) {
      requestHeaders.setIfModifiedSince(new Date(ifModifiedSince));
    }

    CookieHandler cookieHandler = client.getCookieHandler();
    if (cookieHandler != null) {
      requestHeaders.addCookies(
          cookieHandler.get(uri, requestHeaders.getHeaders().toMultimap(false)));
    }
  }