void spewInternal() {
      if (pending.remaining() > 0) {
        com.koushikdutta.async.Util.emitAllData(BodySpewer.this, pending);
        if (pending.remaining() > 0) return;
      }

      // fill pending
      try {
        while (pending.remaining() == 0) {
          ByteBuffer buffer = ByteBuffer.allocate(8192);
          int read = cacheResponse.getBody().read(buffer.array());
          if (read == -1) {
            allowEnd = true;
            report(null);
            return;
          }
          buffer.limit(read);
          pending.add(buffer);
          com.koushikdutta.async.Util.emitAllData(BodySpewer.this, pending);
        }
      } catch (IOException e) {
        allowEnd = true;
        report(e);
      }
    }
예제 #2
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();
    }
  }
예제 #3
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;
    }
  }
예제 #4
0
 // Tries to get head and body from cache, return true if has got this time
 // or
 // already got before
 private boolean getFromCache() throws IOException {
   if (useCaches && null != responseCache && !hasTriedCache) {
     hasTriedCache = true;
     if (null == resHeader) {
       resHeader = new Header();
     }
     cacheResponse = responseCache.get(uri, method, resHeader.getFieldMap());
     if (null != cacheResponse) {
       Map<String, List<String>> headMap = cacheResponse.getHeaders();
       if (null != headMap) {
         resHeader = new Header(headMap);
       }
       is = cacheResponse.getBody();
       if (null != is) {
         return true;
       }
     }
   }
   if (hasTriedCache && null != is) {
     return true;
   }
   return false;
 }
  // step 1) see if we can serve request from the cache directly.
  // also see if this can be turned into a conditional cache request.
  @Override
  public Cancellable getSocket(final GetSocketData data) {
    if (cache == null) return null;

    if (!caching) return null;
    if (data.request.getHeaders().isNoCache()) return null;
    //        Log.i(LOGTAG, "getting cache socket: " + request.getUri().toString());

    String key = uriToKey(data.request.getUri());
    DiskLruCache.Snapshot snapshot;
    Entry entry;
    try {
      snapshot = cache.get(key);
      if (snapshot == null) {
        //                Log.i(LOGTAG, "snapshot fail");
        return null;
      }
      entry = new Entry(snapshot.getInputStream(ENTRY_METADATA));
    } catch (IOException e) {
      // Give up because the cache cannot be read.
      return null;
    }

    if (!entry.matches(
        data.request.getUri(),
        data.request.getMethod(),
        data.request.getHeaders().getHeaders().toMultimap())) {
      snapshot.close();
      return null;
    }

    ResponseSource responseSource = ResponseSource.NETWORK;

    CacheResponse candidate =
        entry.isHttps()
            ? new EntrySecureCacheResponse(entry, snapshot)
            : new EntryCacheResponse(entry, snapshot);

    Map<String, List<String>> responseHeadersMap;
    InputStream cachedResponseBody;
    try {
      responseHeadersMap = candidate.getHeaders();
      cachedResponseBody = candidate.getBody();
    } catch (Exception e) {
      return null;
    }
    if (responseHeadersMap == null || cachedResponseBody == null) {
      try {
        cachedResponseBody.close();
      } catch (Exception e) {
      }
      return null;
    }

    RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap);
    ResponseHeaders cachedResponseHeaders =
        new ResponseHeaders(data.request.getUri(), rawResponseHeaders);

    long now = System.currentTimeMillis();
    responseSource = cachedResponseHeaders.chooseResponseSource(now, data.request.getHeaders());

    if (responseSource == ResponseSource.CACHE) {
      cacheStoreCount++;
      final CachedSocket socket =
          entry.isHttps()
              ? new CachedSSLSocket((EntrySecureCacheResponse) candidate)
              : new CachedSocket((EntryCacheResponse) candidate);

      client
          .getServer()
          .post(
              new Runnable() {
                @Override
                public void run() {
                  data.connectCallback.onConnectCompleted(null, socket);
                  socket.spewInternal();
                }
              });
    } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
      CacheData cacheData = new CacheData();
      cacheData.cachedResponseHeaders = cachedResponseHeaders;
      cacheData.candidate = candidate;
      data.state.putParcelable("cache-data", cacheData);

      return null;
    } else {
      // NETWORK or other
      try {
        cachedResponseBody.close();
      } catch (Exception e) {
      }
      return null;
    }

    return new SimpleCancelable();
  }