/*
 * Copyright 2011 Google 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.
 */

// Author: sligocki@google.com (Shawn Ligocki)

#include "net/instaweb/http/public/cache_url_async_fetcher.h"

#include "base/logging.h"
#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/async_fetch_with_lock.h"
#include "net/instaweb/http/public/http_cache.h"
#include "net/instaweb/http/public/http_value.h"
#include "net/instaweb/http/public/http_value_writer.h"
#include "net/instaweb/http/public/log_record.h"  // for AbstractLogRecord
#include "net/instaweb/http/public/logging_proto.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/http/public/url_async_fetcher.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/http_options.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/thread/sequence.h"


namespace net_instaweb {

// HTTP 501 Not Implemented: The server either does not recognize the
// request method, or it lacks the ability to fulfill the request.
const int CacheUrlAsyncFetcher::kNotInCacheStatus = HttpStatus::kNotImplemented;

namespace {

class CachePutFetch : public SharedAsyncFetch {
 public:
  CachePutFetch(const GoogleString& url, const GoogleString& fragment,
                AsyncFetch* base_fetch,
                ResponseHeaders::VaryOption respect_vary,
                bool default_cache_html, HTTPCache* cache,
                Histogram* backend_first_byte_latency, MessageHandler* handler)
      : SharedAsyncFetch(base_fetch),
        url_(url),
        fragment_(fragment),
        http_options_(request_context()->options()),
        respect_vary_(respect_vary),
        default_cache_html_(default_cache_html),
        cache_(cache),
        backend_first_byte_latency_(backend_first_byte_latency),
        handler_(handler),
        cacheable_(false),
        cache_value_writer_(&cache_value_, cache_),
        saved_headers_(http_options_),
        req_properties_(base_fetch->request_headers()->GetProperties()) {
    if (backend_first_byte_latency_ != NULL) {
      start_time_ms_ = cache_->timer()->NowMs();
    }
  }

  virtual ~CachePutFetch() {}

  virtual void HandleHeadersComplete() {
    // We compute the latency here as it's the spot where we're doing an
    // actual backend fetch and not potentially using the cache.
    int64 now_ms = cache_->timer()->NowMs();
    if (backend_first_byte_latency_ != NULL) {
      backend_first_byte_latency_->Add(now_ms - start_time_ms_);
    }
    ResponseHeaders* headers = response_headers();
    headers->FixDateHeaders(now_ms);
    bool is_html = headers->IsHtmlLike();
    const char* cache_control = headers->Lookup1(HttpAttributes::kCacheControl);
    if (default_cache_html_ && is_html &&
        // TODO(sligocki): Use some sort of computed
        // headers->HasExplicitCachingTtl() instead
        // of just checking for the existence of 2 headers.
        (cache_control == NULL || cache_control == StringPiece("public")) &&
        !headers->Has(HttpAttributes::kExpires)) {
      headers->Add(HttpAttributes::kCacheControl,
          "max-age=" + Integer64ToString(headers->implicit_cache_ttl_ms()));
    }
    headers->ComputeCaching();
    cacheable_ = headers->IsProxyCacheable(req_properties_, respect_vary_,
                                           ResponseHeaders::kHasValidator);
    if (cacheable_) {
      // Make a copy of the headers which we will send to the
      // cache_value_writer_ later.
      saved_headers_.CopyFrom(*headers);
    }

    SharedAsyncFetch::HandleHeadersComplete();
  }

  virtual bool HandleWrite(const StringPiece& content,
                           MessageHandler* handler) {
    bool ret = true;
    ret &= SharedAsyncFetch::HandleWrite(content, handler);
    if (cacheable_) {
      ret &= cache_value_writer_.Write(content, handler);
    }
    return ret;
  }

  virtual bool HandleFlush(MessageHandler* handler) {
    // Note cache_value_.Flush doesn't do anything.
    return SharedAsyncFetch::HandleFlush(handler);
  }

  virtual void HandleDone(bool success) {
    DCHECK_EQ(request_headers()->method(), RequestHeaders::kGet);
    // We do not cache empty 200 responses. (Empty 404, 500 are fine.)
    // https://github.com/pagespeed/mod_pagespeed/issues/1050
    const bool empty_200 =
        (response_headers()->status_code() == HttpStatus::kOK &&
         cache_value_.contents_size() == 0);
    const bool insert_into_cache = (success &&
                                    cacheable_ &&
                                    !empty_200 &&
                                    cache_value_writer_.has_buffered());

    if (insert_into_cache) {
      // The X-Original-Content-Length header will have been added after
      // HandleHeadersComplete(), so extract its value and add it to the
      // saved headers.
      const char* orig_content_length = extra_response_headers()->Lookup1(
          HttpAttributes::kXOriginalContentLength);
      int64 ocl;
      if (orig_content_length != NULL &&
          StringToInt64(orig_content_length, &ocl)) {
        saved_headers_.SetOriginalContentLength(ocl);
      }
      // Finalize the headers.
      cache_value_writer_.SetHeaders(&saved_headers_);
    } else {
      // Set is_original_resource_cacheable.
      log_record()->SetIsOriginalResourceCacheable(false);
    }

    // Finish fetch.
    SharedAsyncFetch::HandleDone(success);
    // Note: SharedAsyncFetch::base_fetch_ and other things that refer to that,
    // like request_context() cannot be accessed or used any more.

    // Add result to cache.
    if (insert_into_cache) {
      cache_->Put(url_, fragment_, req_properties_, http_options_,
                  &cache_value_, handler_);
    }
    // Note: We explicitly do not remember fetch failure, uncacheable nor
    // empty resources here since we still want to proxy those through every
    // time they are requested.
    // TODO(sligocki): Maybe we should be remembering failures.
    delete this;
  }

 private:
  const GoogleString url_;
  const GoogleString fragment_;
  const HttpOptions http_options_;
  // TODO(sligocki): Remove and use http_options_.respect_vary instead.
  ResponseHeaders::VaryOption respect_vary_;
  bool default_cache_html_;
  HTTPCache* cache_;
  Histogram* backend_first_byte_latency_;
  MessageHandler* handler_;

  bool cacheable_;
  HTTPValue cache_value_;
  HTTPValueWriter cache_value_writer_;
  int64 start_time_ms_;  // only used if backend_first_byte_latency_ != NULL
  ResponseHeaders saved_headers_;
  RequestHeaders::Properties req_properties_;

  DISALLOW_COPY_AND_ASSIGN(CachePutFetch);
};

class CacheFindCallback : public HTTPCache::Callback {
 public:
  class BackgroundFreshenFetch : public AsyncFetchWithLock {
   public:
    explicit BackgroundFreshenFetch(
        const Hasher* lock_hasher,
        const RequestContextPtr& request_context,
        const GoogleString& url,
        NamedLockManager* lock_manager,
        MessageHandler* message_handler,
        CacheFindCallback* callback,
        CacheUrlAsyncFetcher::AsyncOpHooks* async_op_hooks)
        : AsyncFetchWithLock(
              lock_hasher, request_context, url, url /* cache_key*/,
              lock_manager, message_handler),
          callback_(callback),
          async_op_hooks_(async_op_hooks) {
      async_op_hooks_->StartAsyncOp();
    }

    virtual ~BackgroundFreshenFetch() {
      async_op_hooks_->FinishAsyncOp();
    }

    virtual void StartFetch(
        UrlAsyncFetcher* fetcher, MessageHandler* handler) {
      AsyncFetch* fetch = callback_->WrapCachePutFetchAndConditionalFetch(this);
      fetcher->Fetch(url(), handler, fetch);
    }

    virtual bool ShouldYieldToRedundantFetchInProgress() {
      return true;
    }

    virtual bool IsBackgroundFetch() const { return true; }

   private:
    CacheFindCallback* callback_;
    CacheUrlAsyncFetcher::AsyncOpHooks* async_op_hooks_;

    DISALLOW_COPY_AND_ASSIGN(BackgroundFreshenFetch);
  };

  CacheFindCallback(const Hasher* lock_hasher,
                    NamedLockManager* lock_manager,
                    const GoogleString& url,
                    const GoogleString& fragment,
                    AsyncFetch* base_fetch,
                    CacheUrlAsyncFetcher* owner,
                    CacheUrlAsyncFetcher::AsyncOpHooks* async_op_hooks,
                    MessageHandler* handler)
      : HTTPCache::Callback(base_fetch->request_context(),
                            base_fetch->request_headers()->GetProperties()),
        lock_hasher_(lock_hasher),
        lock_manager_(lock_manager),
        url_(url),
        base_fetch_(base_fetch),
        cache_(owner->http_cache()),
        fragment_(fragment),
        async_op_hooks_(async_op_hooks),
        fetcher_(owner->fetcher()),
        backend_first_byte_latency_(
            owner->backend_first_byte_latency_histogram()),
        fallback_responses_served_(owner->fallback_responses_served()),
        fallback_responses_served_while_revalidate_(
            owner->fallback_responses_served_while_revalidate()),
        num_conditional_refreshes_(owner->num_conditional_refreshes()),
        num_proactively_freshen_user_facing_request_(
            owner->num_proactively_freshen_user_facing_request()),
        handler_(handler),
        http_options_(base_fetch->request_context()->options()),
        respect_vary_(ResponseHeaders::GetVaryOption(owner->respect_vary())),
        ignore_recent_fetch_failed_(owner->ignore_recent_fetch_failed()),
        serve_stale_if_fetch_error_(owner->serve_stale_if_fetch_error()),
        default_cache_html_(owner->default_cache_html()),
        proactively_freshen_user_facing_request_(
            owner->proactively_freshen_user_facing_request()),
        serve_stale_while_revalidate_threshold_sec_(
            owner->serve_stale_while_revalidate_threshold_sec()) {
    // Note that this is a cache lookup: there are no request-headers.  At
    // this level, we have already made a policy decision that any Vary
    // headers present will be ignored.  See
    // https://modpagespeed.com/doc/configuration#respectvary
    set_response_headers(base_fetch->response_headers());
  }
  virtual ~CacheFindCallback() {}

  virtual void Done(HTTPCache::FindResult find_result) {
    if (response_sequence_ == NULL) {
      Finish(find_result);
    } else {
      response_sequence_->Add(MakeFunction(
          this, &CacheFindCallback::Finish, find_result));
    }
  }

  void Finish(HTTPCache::FindResult find_result) {
    switch (find_result.status) {
      case HTTPCache::kFound: {
        VLOG(1) << "Found in cache: " << url_ << " (" << fragment_ << ")";
        http_value()->ExtractHeaders(response_headers(), handler_);

        bool is_imminently_expiring = false;

        // Respond with a 304 if the If-Modified-Since / If-None-Match values
        // are equal to those in the request.
        if (ShouldReturn304()) {
          response_headers()->Clear();
          response_headers()->SetStatusAndReason(HttpStatus::kNotModified);
          response_headers()->ComputeCaching();
          is_imminently_expiring = IsImminentlyExpiring(*response_headers());
          base_fetch_->HeadersComplete();
        } else if (base_fetch_->request_headers()->method() !=
                   RequestHeaders::kHead) {
          DCHECK_EQ(base_fetch_->request_headers()->method(),
                    RequestHeaders::kGet);

          // Before calling HeadersComplete, record the content-length so that
          // http server gaskets have an opportunity to examine
          // content_length_known() in HandleHeadersComplete and thereby serve
          // non-chunked responses.
          StringPiece contents;
          http_value()->ExtractContents(&contents);
          base_fetch_->set_content_length(contents.size());
          response_headers()->ComputeCaching();
          is_imminently_expiring = IsImminentlyExpiring(*response_headers());
          base_fetch_->HeadersComplete();

          // TODO(sligocki): We are writing all the content in one shot, this
          // fact might be useful to the HtmlParser if this is HTML. Perhaps
          // we should add an API for conveying that information, which can
          // be detected via AsyncFetch::content_length_known().
          base_fetch_->Write(contents, handler_);
        } else {
          response_headers()->ComputeCaching();
          is_imminently_expiring = IsImminentlyExpiring(*response_headers());
        }

        if (fetcher_ != NULL &&
            proactively_freshen_user_facing_request_ &&
            async_op_hooks_ != NULL &&
            is_imminently_expiring) {
          // Triggers the background fetch to freshen the value in cache if
          // resource is about to expire.
          if (num_proactively_freshen_user_facing_request_ != NULL) {
            num_proactively_freshen_user_facing_request_->Add(1);
          }
          TriggerBackgroundFreshenFetch();
        }

        base_fetch_->Done(true);
        break;
      }
      // Note: currently no resources fetched through CacheUrlAsyncFetcher
      // will be marked RememberFetchFailedOrNotCacheable.
      // TODO(sligocki): Should we mark resources as such in this class?
      case HTTPCache::kRecentFailure:
        VLOG(1) << "RecentFetchFailed, NotCacheable or Empty: "
                << url_ << " (" << fragment_ << ")";
        if (!ignore_recent_fetch_failed_) {
          base_fetch_->Done(false);
          break;
        } else {
          // If we are ignoring advice of kRecentFetchFailedOrNotCacheable,
          // we will refetch the resource as we would for kNotFound.
          //
          // For example, we should do this for fetches that are being proxied.
          FALLTHROUGH_INTENDED;
        }
      case HTTPCache::kNotFound: {
        VLOG(1) << "Did not find in cache: "
                << url_ << " (" << fragment_ << ")";
        if (fetcher_ == NULL) {
          // Set status code to indicate reason we failed Fetch.
          DCHECK(!base_fetch_->headers_complete());
          base_fetch_->response_headers()->set_status_code(
              CacheUrlAsyncFetcher::kNotInCacheStatus);
          base_fetch_->Done(false);
        } else {
          AsyncFetch* base_fetch = base_fetch_;
          if (request_headers()->method() == RequestHeaders::kGet) {
            // Only cache GET results as they can be used for HEAD requests,
            // but not vice versa.
            // TODO(gee): It is possible to cache HEAD results as well, but we
            // must add code to ensure we do not serve GET requests using HEAD
            // responses.
            if (ServedStaleContentWhileRevalidate(base_fetch)) {
              // Serve stale content while revalidate in the background.
              break;
            }
            if (serve_stale_if_fetch_error_) {
              // If fallback_http_value() is populated, use it in case the
              // fetch fails. Note that this is only populated if the
              // response in cache is stale.
              FallbackSharedAsyncFetch* fallback_fetch =
                  new FallbackSharedAsyncFetch(
                      base_fetch_, fallback_http_value(), handler_);
              fallback_fetch->set_fallback_responses_served(
                  fallback_responses_served_);
              base_fetch = fallback_fetch;
            }

            base_fetch = WrapCachePutFetchAndConditionalFetch(base_fetch);
          }

          fetcher_->Fetch(url_, handler_, base_fetch);
        }
        break;
      }
    }

    delete this;
  }

  virtual bool IsCacheValid(const GoogleString& key,
                            const ResponseHeaders& headers) {
    // base_fetch_ already has the key (URL + fragment).
    return base_fetch_->IsCachedResultValid(headers);
  }

  virtual ResponseHeaders::VaryOption RespectVaryOnResources() const {
    return respect_vary_;
  }

  void set_response_sequence(Sequence* sequence) {
    response_sequence_ = sequence;
  }

 private:
  bool ServedStaleContentWhileRevalidate(AsyncFetch* base_fetch) {
    if (serve_stale_while_revalidate_threshold_sec_ == 0 ||
        fallback_http_value() == NULL ||
        fallback_http_value()->Empty()) {
      return false;
    }
    ResponseHeaders* response_headers = base_fetch->response_headers();
    if (!fallback_http_value()->ExtractHeaders(response_headers, handler_)) {
      // Returns false if it fails to extract headers.
      response_headers->Clear();
      return false;
    }
    response_headers->ComputeCaching();
    const int64 expiry_ms = response_headers->CacheExpirationTimeMs();
    const int64 now_ms = cache_->timer()->NowMs();
    const int64 serve_stale_threshold_ms =
        serve_stale_while_revalidate_threshold_sec_ * 1000;
    if (now_ms > expiry_ms +  serve_stale_threshold_ms ||
        response_headers->IsHtmlLike()) {
      // Serve non-html request with fallback http value if resource
      // was expired within serve_stale_while_revalidate_threshold_ms_.
      response_headers->Clear();
      return false;
    }
    if (fallback_responses_served_while_revalidate_ != NULL) {
      fallback_responses_served_while_revalidate_->Add(1);
    }
    // CacheControl header is changed to private, max-age=0 to avoid caching
    // of the resource either by browser or intermediate proxy as stale
    // content should be served only for this request, any future requests
    // should be served with fresh content.
    response_headers->Replace(HttpAttributes::kCacheControl,
                              "private, max-age=0");
    response_headers->RemoveAll(HttpAttributes::kExpires);
    response_headers->ComputeCaching();
    base_fetch_->HeadersComplete();
    StringPiece contents;
    fallback_http_value()->ExtractContents(&contents);
    base_fetch_->Write(contents, handler_);

    // Issue a background fetch to update the cache with a fresh value so
    // that future request will be responded with fresh content.
    TriggerBackgroundFreshenFetch();
    base_fetch_->Done(true);
    return true;
  }

  void TriggerBackgroundFreshenFetch() {
    AsyncFetchWithLock* fetch = new BackgroundFreshenFetch(
        lock_hasher_,
        base_fetch_->request_context(),
        url_,
        lock_manager_,
        handler_,
        this,
        async_op_hooks_);
    RequestHeaders* request_headers = fetch->request_headers();
    request_headers->CopyFrom(*base_fetch_->request_headers());
    DCHECK(request_headers->method() == RequestHeaders::kGet ||
           request_headers->method() == RequestHeaders::kHead);
    // It's possible for us to trigger a background freshen on a HEAD.
    // If so, actually send the GET request, since we don't want to be
    // trying to cache a HEAD response.
    request_headers->set_method(RequestHeaders::kGet);
    fetch->Start(fetcher_);
  }

  bool ShouldReturn304() const {
    if (ConditionalHeadersMatch(HttpAttributes::kIfNoneMatch,
                                HttpAttributes::kEtag)) {
      // If the Etag matches, return a 304.
      return true;
    }
    // Otherwise, return a 304 only if there was no If-None-Match header in the
    // request and the last modified timestamp matches.
    // (from http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)
    return request_headers()->Lookup1(HttpAttributes::kIfNoneMatch) == NULL &&
        ConditionalHeadersMatch(HttpAttributes::kIfModifiedSince,
                                HttpAttributes::kLastModified);
  }

  bool ConditionalHeadersMatch(const StringPiece& request_header,
                               const StringPiece& response_header) const {
    const char* request_header_value =
        request_headers()->Lookup1(request_header);
    const char* response_header_value =
        response_headers()->Lookup1(response_header);
    return request_header_value != NULL && response_header_value != NULL &&
        strcmp(request_header_value, response_header_value) == 0;
  }

  const RequestHeaders* request_headers() const {
    return base_fetch_->request_headers();
  }
  RequestHeaders* request_headers() { return base_fetch_->request_headers(); }

  bool IsImminentlyExpiring(const ResponseHeaders& headers) const {
    return ResponseHeaders::IsImminentlyExpiring(
        headers.date_ms(),
        headers.CacheExpirationTimeMs(),
        cache_->timer()->NowMs(),
        headers.http_options());
  }

  AsyncFetch* WrapCachePutFetchAndConditionalFetch(AsyncFetch* base_fetch) {
    CachePutFetch* put_fetch = new CachePutFetch(
        url_, fragment_, base_fetch, respect_vary_, default_cache_html_, cache_,
        backend_first_byte_latency_, handler_);
    DCHECK_EQ(response_headers(), base_fetch_->response_headers());

    // Remove any Etags added by us before sending the request out. This is the
    // etags generated by server and upstream original code would not
    // understand them.
    const char* etag = request_headers()->Lookup1(
        HttpAttributes::kIfNoneMatch);
    if (etag != NULL &&
        StringCaseStartsWith(etag, HTTPCache::kEtagPrefix)) {
      put_fetch->request_headers()->RemoveAll(
          HttpAttributes::kIfNoneMatch);
    }

    ConditionalSharedAsyncFetch* conditional_fetch =
        new ConditionalSharedAsyncFetch(
            put_fetch, fallback_http_value(), handler_);
    conditional_fetch->set_num_conditional_refreshes(
        num_conditional_refreshes_);
    return conditional_fetch;
  }

  const Hasher* lock_hasher_;
  NamedLockManager* lock_manager_;
  const GoogleString url_;
  RequestHeaders request_headers_;
  AsyncFetch* base_fetch_;
  HTTPCache* cache_;
  GoogleString fragment_;
  CacheUrlAsyncFetcher::AsyncOpHooks* async_op_hooks_;
  UrlAsyncFetcher* fetcher_;
  Histogram* backend_first_byte_latency_;
  Variable* fallback_responses_served_;
  Variable* fallback_responses_served_while_revalidate_;
  Variable* num_conditional_refreshes_;
  Variable* num_proactively_freshen_user_facing_request_;
  MessageHandler* handler_;

  const HttpOptions http_options_;
  // TODO(sligocki): Remove and use http_options_.respect_vary instead.
  ResponseHeaders::VaryOption respect_vary_;
  bool ignore_recent_fetch_failed_;
  bool serve_stale_if_fetch_error_;
  bool default_cache_html_;
  bool proactively_freshen_user_facing_request_;
  int64 serve_stale_while_revalidate_threshold_sec_;
  Sequence* response_sequence_;

  DISALLOW_COPY_AND_ASSIGN(CacheFindCallback);
};

}  // namespace

CacheUrlAsyncFetcher::CacheUrlAsyncFetcher(const Hasher* lock_hasher,
                                           NamedLockManager* lock_manager,
                                           HTTPCache* cache,
                                           const GoogleString& fragment,
                                           AsyncOpHooks* async_op_hooks,
                                           UrlAsyncFetcher* fetcher)
    : lock_hasher_(lock_hasher),
      lock_manager_(lock_manager),
      http_cache_(cache),
      fragment_(fragment),
      fetcher_(fetcher),
      async_op_hooks_(async_op_hooks),
      backend_first_byte_latency_(NULL),
      fallback_responses_served_(NULL),
      fallback_responses_served_while_revalidate_(NULL),
      num_conditional_refreshes_(NULL),
      num_proactively_freshen_user_facing_request_(NULL),
      respect_vary_(false),
      ignore_recent_fetch_failed_(false),
      serve_stale_if_fetch_error_(false),
      default_cache_html_(false),
      proactively_freshen_user_facing_request_(false),
      own_fetcher_(false),
      serve_stale_while_revalidate_threshold_sec_(0),
      response_sequence_(NULL) {
}

CacheUrlAsyncFetcher::~CacheUrlAsyncFetcher() {
  if (own_fetcher_) {
    delete fetcher_;
    fetcher_ = NULL;
  }
}

void CacheUrlAsyncFetcher::Fetch(
    const GoogleString& url, MessageHandler* handler, AsyncFetch* base_fetch) {
  switch (base_fetch->request_headers()->method()) {
    case RequestHeaders::kHead:
      // HEAD is identical to GET, with the body trimmed.  Even though we are
      // able to respond to HEAD requests with a cached value from a GET
      // response, at this point we do not allow caching of HEAD responses from
      // the origin, so mark the "original" resource as uncacheable.
      base_fetch->log_record()->SetIsOriginalResourceCacheable(false);
      FALLTHROUGH_INTENDED;
    case RequestHeaders::kGet:
      {
        CacheFindCallback* find_callback =
            new CacheFindCallback(
                lock_hasher_,
                lock_manager_,
                url,
                fragment_,
                base_fetch,
                this,
                async_op_hooks_,
                handler);
        find_callback->set_response_sequence(response_sequence_);
        http_cache_->Find(url, fragment_, handler, find_callback);
      }
      return;

    default:
      // POST may not be idempotent and thus we must not serve a cached value
      // from a prior request.
      // TODO(gee): What about the other methods?
      break;
  }

  // Original resource not cacheable.
  base_fetch->log_record()->SetIsOriginalResourceCacheable(false);
  if (fetcher_ != NULL) {
    fetcher_->Fetch(url, handler, base_fetch);
  } else {
    // Set status code to indicate reason we failed Fetch.
    DCHECK(!base_fetch->headers_complete());
    base_fetch->response_headers()->set_status_code(kNotInCacheStatus);
    base_fetch->Done(false);
  }
}

CacheUrlAsyncFetcher::AsyncOpHooks::~AsyncOpHooks() {
}

}  // namespace net_instaweb
