HttpTransact::DecideCacheLookup(State* s)
{
  // Check if a client request is lookupable.
  if (s->redirect_info.redirect_in_process || s->cop_test_page) {
    // for redirect, we want to skip cache lookup and write into
    // the cache directly with the URL before the redirect
    s->cache_info.action = CACHE_DO_NO_ACTION;
    s->current.mode = GENERIC_PROXY;
  } else {
    if (is_request_cache_lookupable(s)) {
      s->cache_info.action = CACHE_DO_LOOKUP;
      s->current.mode = GENERIC_PROXY;
    } else {
      s->cache_info.action = CACHE_DO_NO_ACTION;
      s->current.mode = TUNNELLING_PROXY;
      HTTP_INCREMENT_TRANS_STAT(http_tunnels_stat);
    }
  }

  if (service_transaction_in_proxy_only_mode(s)) {
    s->cache_info.action = CACHE_DO_NO_ACTION;
    s->current.mode = TUNNELLING_PROXY;
    HTTP_INCREMENT_TRANS_STAT(http_throttled_proxy_only_stat);
  }
  // at this point the request is ready to continue down the
  // traffic server path.

  // now decide whether the cache can even be looked up.
  if (s->cache_info.action == CACHE_DO_LOOKUP) {
    DebugTxn("http_trans", "[DecideCacheLookup] Will do cache lookup.");
    DebugTxn("http_seq", "[DecideCacheLookup] Will do cache lookup");
    ink_assert(s->current.mode != TUNNELLING_PROXY);

    if (s->cache_info.lookup_url == NULL) {
      HTTPHdr* incoming_request = &s->hdr_info.client_request;

      if (s->txn_conf->maintain_pristine_host_hdr) {
        s->cache_info.lookup_url_storage.create(NULL);
        s->cache_info.lookup_url_storage.copy(incoming_request->url_get());
        s->cache_info.lookup_url = &s->cache_info.lookup_url_storage;
        // if the target isn't in the URL, put it in the copy for
        // cache lookup.
        incoming_request->set_url_target_from_host_field(s->cache_info.lookup_url);
      } else {
        // make sure the target is in the URL.
        incoming_request->set_url_target_from_host_field();
        s->cache_info.lookup_url = incoming_request->url_get();
      }

      // *somebody* wants us to not hack the host header in a reverse proxy setup.
      // In addition, they want us to reverse proxy for 6000 servers, which vary
      // the stupid content on the Host header!!!!
      // We could a) have 6000 alts (barf, puke, vomit) or b) use the original
      // host header in the url before doing all cache actions (lookups, writes, etc.)
      if (s->txn_conf->maintain_pristine_host_hdr) {
        char const* host_hdr;
        char const* port_hdr;
        int host_len, port_len;
        // So, the host header will have the original host header.
        if (incoming_request->get_host_port_values(&host_hdr, &host_len, &port_hdr, &port_len)) {
          int port = 0;
          if (port_hdr) {
            s->cache_info.lookup_url->host_set(host_hdr, host_len);
            port = ink_atoi(port_hdr, port_len);
          } else {
            s->cache_info.lookup_url->host_set(host_hdr, host_len);
          }
          s->cache_info.lookup_url->port_set(port);
        }
      }
      ink_assert(s->cache_info.lookup_url->valid() == true);
    }

    TRANSACT_RETURN(SM_ACTION_CACHE_LOOKUP, NULL);
  } else {
    ink_assert(s->cache_info.action != CACHE_DO_LOOKUP && s->cache_info.action != CACHE_DO_SERVE);

    DebugTxn("http_trans", "[DecideCacheLookup] Will NOT do cache lookup.");
    DebugTxn("http_seq", "[DecideCacheLookup] Will NOT do cache lookup");
    // If this is a push request, we need send an error because
    //   since what ever was sent is not cachable
    if (s->method == HTTP_WKSIDX_PUSH) {
      HandlePushError(s, "Request Not Cachable");
      return;
    }
    // for redirect, we skipped cache lookup to do the automatic redirection
    if (s->redirect_info.redirect_in_process) {
      // without calling out the CACHE_LOOKUP_COMPLETE_HOOK
      s->cache_info.action = CACHE_DO_WRITE;
      LookupSkipOpenServer(s);
    } else {
      // calling out CACHE_LOOKUP_COMPLETE_HOOK even when the cache
      // lookup is skipped
      s->cache_lookup_result = HttpTransact::CACHE_LOOKUP_SKIPPED;
      if (s->force_dns) {
        TRANSACT_RETURN(SM_ACTION_API_CACHE_LOOKUP_COMPLETE, LookupSkipOpenServer);
      } else {
        // Returning to dns lookup as cache lookup is skipped
        TRANSACT_RETURN(SM_ACTION_API_CACHE_LOOKUP_COMPLETE, CallOSDNSLookup);
      }
    }
  }

  return;
}