HttpTransact::is_response_cacheable(State* s, HTTPHdr* request, HTTPHdr* response)
{
  // If the use_client_target_addr is specified but the client
  // specified OS addr does not match any of trafficserver's looked up
  // host addresses, do not allow cache.  This may cause DNS cache poisoning
  // of other trafficserver clients. The flag is set in the
  // process_host_db_info method
  if (!s->dns_info.lookup_validated
    && s->client_info.is_transparent) {
    DebugTxn("http_trans", "[is_response_cacheable] " "Lookup not validated.  Possible DNS cache poison.  Don't cache");
    return false;
  }

  // if method is not GET or HEAD, do not cache.
  // Note: POST is also cacheable with Expires or Cache-control.
  // but due to INKqa11567, we are not caching POST responses.
  // Basically, the problem is the resp for POST url1 req should not
  // be served to a GET url1 request, but we just match URL not method.
  int req_method = request->method_get_wksidx();
  if (!(HttpTransactHeaders::is_method_cacheable(s->http_config_param, req_method)) && s->api_req_cacheable == false) {
    DebugTxn("http_trans", "[is_response_cacheable] " "only GET, and some HEAD and POST are cachable");
    return false;
  }
  // DebugTxn("http_trans", "[is_response_cacheable] method is cacheable");
  // If the request was not looked up in the cache, the response
  // should not be cached (same subsequent requests will not be
  // looked up, either, so why cache this).
  if (!(is_request_cache_lookupable(s))) {
    DebugTxn("http_trans", "[is_response_cacheable] " "request is not cache lookupable, response is not cachable");
    return (false);
  }
  // already has a fresh copy in the cache
  if (s->range_setup == RANGE_NOT_HANDLED)
    return false;

  // Check whether the response is cachable based on its cookie
  // If there are cookies in response but a ttl is set, allow caching
  if ((s->cache_control.ttl_in_cache <= 0) &&
      do_cookies_prevent_caching((int) s->txn_conf->cache_responses_to_cookies, request, response)) {
    DebugTxn("http_trans", "[is_response_cacheable] " "response has uncachable cookies, response is not cachable");
    return (false);
  }
  // if server spits back a WWW-Authenticate
  if ((s->txn_conf->cache_ignore_auth) == 0 && response->presence(MIME_PRESENCE_WWW_AUTHENTICATE)) {
    DebugTxn("http_trans", "[is_response_cacheable] " "response has WWW-Authenticate, response is not cachable");
    return (false);
  }
  // does server explicitly forbid storing?
  // If OS forbids storing but a ttl is set, allow caching
  if (!s->cache_info.directives.does_server_permit_storing &&
      !s->cache_control.ignore_server_no_cache && (s->cache_control.ttl_in_cache <= 0)) {
    DebugTxn("http_trans", "[is_response_cacheable] server does not permit storing and config file does not "
          "indicate that server directive should be ignored");
    return (false);
  }
  // DebugTxn("http_trans", "[is_response_cacheable] server permits storing");

  // does config explicitly forbid storing?
  // ttl overides other config parameters
  if ((!s->cache_info.directives.does_config_permit_storing &&
       !s->cache_control.ignore_server_no_cache &&
       (s->cache_control.ttl_in_cache <= 0)) || (s->cache_control.never_cache)) {
    DebugTxn("http_trans", "[is_response_cacheable] config doesn't allow storing, and cache control does not "
          "say to ignore no-cache and does not specify never-cache or a ttl");
    return (false);
  }
  // DebugTxn("http_trans", "[is_response_cacheable] config permits storing");

  // does client explicitly forbid storing?
  if (!s->cache_info.directives.does_client_permit_storing && !s->cache_control.ignore_client_no_cache) {
    DebugTxn("http_trans", "[is_response_cacheable] client does not permit storing, "
          "and cache control does not say to ignore client no-cache");
    return (false);
  }
  DebugTxn("http_trans", "[is_response_cacheable] client permits storing");

  HTTPStatus response_code = response->status_get();

  // caching/not-caching based on required headers
  // only makes sense when the server sends back a
  // 200 and a document.
  if (response_code == HTTP_STATUS_OK) {
    // If a ttl is set: no header required for caching
    // otherwise: follow parameter http.cache.required_headers
    if (s->cache_control.ttl_in_cache <= 0) {
      uint32_t cc_mask = (MIME_COOKED_MASK_CC_MAX_AGE | MIME_COOKED_MASK_CC_S_MAXAGE);
      // server did not send expires header or last modified
      // and we are configured to not cache without them.
      switch (s->txn_conf->cache_required_headers) {
      case HttpConfigParams::CACHE_REQUIRED_HEADERS_NONE:
        DebugTxn("http_trans", "[is_response_cacheable] " "no response headers required");
        break;

      case HttpConfigParams::CACHE_REQUIRED_HEADERS_AT_LEAST_LAST_MODIFIED:
        if (!response->presence(MIME_PRESENCE_EXPIRES) && !(response->get_cooked_cc_mask() & cc_mask) &&
            !response->get_last_modified()) {
          DebugTxn("http_trans", "[is_response_cacheable] " "last_modified, expires, or max-age is required");

          s->squid_codes.hit_miss_code = ((response->get_date() == 0) ? (SQUID_MISS_HTTP_NO_DLE) : (SQUID_MISS_HTTP_NO_LE));
          return (false);
        }
        break;

      case HttpConfigParams::CACHE_REQUIRED_HEADERS_CACHE_CONTROL:
        if (!response->presence(MIME_PRESENCE_EXPIRES) && !(response->get_cooked_cc_mask() & cc_mask)) {
          DebugTxn("http_trans", "[is_response_cacheable] " "expires header or max-age is required");
          return (false);
        }
        break;

      default:
        break;
      }
    }
  }
  // do not cache partial content - Range response
  if (response_code == HTTP_STATUS_PARTIAL_CONTENT || response_code == HTTP_STATUS_RANGE_NOT_SATISFIABLE) {
    DebugTxn("http_trans", "[is_response_cacheable] " "response code %d - don't cache", response_code);
    return false;
  }

  // check if cache control overrides default cacheability
  int indicator;
  indicator = response_cacheable_indicated_by_cc(response);
  if (indicator > 0) {          // cacheable indicated by cache control header
    DebugTxn("http_trans", "[is_response_cacheable] YES by response cache control");
    // even if it is authenticated, this is cacheable based on regular rules
    s->www_auth_content = CACHE_AUTH_NONE;
    return true;
  } else if (indicator < 0) {   // not cacheable indicated by cache control header

    // If a ttl is set, allow caching even if response contains
    // Cache-Control headers to prevent caching
    if (s->cache_control.ttl_in_cache > 0) {
      DebugTxn("http_trans", "[is_response_cacheable] Cache-control header directives in response overridden by ttl in cache.config");
    } else if (!s->cache_control.ignore_server_no_cache) {
      DebugTxn("http_trans", "[is_response_cacheable] NO by response cache control");
      return false;
    }
  }
  // else no indication by cache control header
  // continue to determine cacheability

  // if client contains Authorization header,
  // only cache if response has proper Cache-Control
 // if (s->www_auth_content == CACHE_AUTH_FRESH) {
    // response to the HEAD request
  //  return false;
  //} else if (s->www_auth_content == CACHE_AUTH_TRUE ||
   //          (s->www_auth_content == CACHE_AUTH_NONE && request->presence(MIME_PRESENCE_AUTHORIZATION))) {
   // if (!s->cache_control.cache_auth_content || response_code != HTTP_STATUS_OK || req_method != HTTP_WKSIDX_GET)
    //  return false;
  //}
  // s->www_auth_content == CACHE_AUTH_STALE silently continues

  if (response->presence(MIME_PRESENCE_EXPIRES)) {
    DebugTxn("http_trans", "[is_response_cacheable] YES response w/ Expires");
    return true;
  }
  // if it's a 302 or 307 and no positive indicator from cache-control, reject
  if (response_code == HTTP_STATUS_MOVED_TEMPORARILY || response_code == HTTP_STATUS_TEMPORARY_REDIRECT) {
    DebugTxn("http_trans", "[is_response_cacheable] cache-control or expires header is required for 302");
    return false;
  }
  // if it's a POST request and no positive indicator from cache-control
  if (req_method == HTTP_WKSIDX_POST) {
    // allow caching for a POST requests w/o Expires but with a ttl
    if (s->cache_control.ttl_in_cache > 0) {
      DebugTxn("http_trans", "[is_response_cacheable] POST method with a TTL");
    } else {
      DebugTxn("http_trans", "[is_response_cacheable] NO POST w/o Expires or CC");
      return false;
    }
  }
  // the plugin may decide we don't want to cache the response
  if (s->api_server_response_no_store) {
    return (false);
  }
  // default cacheability
  if (!s->txn_conf->negative_caching_enabled) {
    if ((response_code == HTTP_STATUS_OK) ||
        (response_code == HTTP_STATUS_NOT_MODIFIED) ||
        (response_code == HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION) ||
        (response_code == HTTP_STATUS_MOVED_PERMANENTLY) ||
        (response_code == HTTP_STATUS_MULTIPLE_CHOICES) || (response_code == HTTP_STATUS_GONE)) {
      DebugTxn("http_trans", "[is_response_cacheable] YES by default ");
      return true;
    } else {
      DebugTxn("http_trans", "[is_response_cacheable] NO by default");
      return false;
    }
  }
  if (response_code == HTTP_STATUS_SEE_OTHER ||
      response_code == HTTP_STATUS_UNAUTHORIZED ||
      response_code == HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED)
    return false;
  // let is_negative_caching_approriate decide what to do
  return true;
/* Since we weren't caching response obtained with
   Authorization (the cache control stuff was commented out previously)
   I've moved this check to is_request_cache_lookupable().
   We should consider this matter further.  It is unclear
   how many sites actually add Cache-Control headers for Authorized content.

    // if client contains Authorization header, only cache if response
    // has proper Cache-Control flags, as in RFC2068, section 14.8.
    if (request->field_presence(MIME_PRESENCE_AUTHORIZATION)) {
//         if (! (response->is_cache_control_set(HTTP_VALUE_MUST_REVALIDATE)) &&
//             ! (response->is_cache_control_set(HTTP_VALUE_PROXY_REVALIDATE)) &&
//             ! (response->is_cache_control_set(HTTP_VALUE_PUBLIC))) {

            DebugTxn("http_trans", "[is_response_cacheable] request has AUTHORIZATION - not cacheable");
            return(false);
//         }
//      else {
//          DebugTxn("http_trans","[is_response_cacheable] request has AUTHORIZATION, "
//                "but response has a cache-control that allows caching");
//      }
    }
*/
}