/** @file

  A brief file description

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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.
 */

#include "proxy/http/HttpConfig.h"
#include "tscore/ink_inet.h"
#include "tsutil/ts_bw_format.h"

#include "tscore/ink_platform.h"

#include <strings.h>
#include <cmath>

using namespace std::literals;

#include "proxy/http/HttpTransact.h"
#include "proxy/http/HttpTransactHeaders.h"
#include "proxy/http/HttpSM.h"
#include "proxy/http/HttpCacheSM.h" //Added to get the scope of HttpCacheSM object - YTS Team, yamsat
#include "proxy/http/HttpDebugNames.h"
#include <ctime>
#include "tscore/ParseRules.h"
#include "tscore/Filenames.h"
#include "proxy/hdrs/HTTP.h"
#include "proxy/hdrs/HdrUtils.h"
#include "proxy/logging/Log.h"
#include "proxy/logging/LogUtils.h"
#include "proxy/CacheControl.h"
#include "proxy/ControlMatcher.h"
#include "proxy/ReverseProxy.h"
#include "proxy/http/HttpBodyFactory.h"
#include "proxy/IPAllow.h"
#include "iocore/utils/Machine.h"
#include "ts/ats_probe.h"

DbgCtl HttpTransact::State::_dbg_ctl{"http"};

namespace
{
char const Dns_error_body[] = "connect#dns_failed";

/// Buffer for some error logs.
thread_local std::string error_bw_buffer;

DbgCtl dbg_ctl_http{"http"};
DbgCtl dbg_ctl_http_error{"http_error"};
DbgCtl dbg_ctl_http_hdrs{"http_hdrs"};
DbgCtl dbg_ctl_http_hdr_space{"http_hdr_space"};
DbgCtl dbg_ctl_http_trans{"http_trans"};
DbgCtl dbg_ctl_http_transact{"http_transact"};
DbgCtl dbg_ctl_http_redirect{"http_redirect"};
DbgCtl dbg_ctl_http_timeout{"http_timeout"};
DbgCtl dbg_ctl_http_seq{"http_seq"};
DbgCtl dbg_ctl_http_match{"http_match"};
DbgCtl dbg_ctl_http_chdr_describe{"http_chdr_describe"};
DbgCtl dbg_ctl_http_trans_upgrade{"http_trans_upgrade"};
DbgCtl dbg_ctl_http_trans_websocket{"http_trans_websocket"};
DbgCtl dbg_ctl_http_trans_websocket_upgrade_pre_remap{"http_trans_websocket_upgrade_pre_remap"};
DbgCtl dbg_ctl_http_trans_websocket_upgrade_post_remap{"http_trans_websocket_upgrade_post_remap"};
DbgCtl dbg_ctl_parent_down{"parent_down"};
DbgCtl dbg_ctl_url_rewrite{"url_rewrite"};
DbgCtl dbg_ctl_ip_allow{"ip_allow"};
} // namespace

// Support ip_resolve override.
const MgmtConverter HttpTransact::HOST_RES_CONV{[](const void *data) -> std::string_view {
                                                  const HostResData *host_res_data = static_cast<const HostResData *>(data);
                                                  return host_res_data->conf_value;
                                                },
                                                [](void *data, std::string_view src) -> void {
                                                  HostResData *res_data = static_cast<HostResData *>(data);
                                                  parse_host_res_preference(src.data(), res_data->order);
                                                }};

static char range_type[] = "multipart/byteranges; boundary=RANGE_SEPARATOR";
#define RANGE_NUMBERS_LENGTH 60

#define TRANSACT_SETUP_RETURN(n, r) \
  s->next_action           = n;     \
  s->transact_return_point = r;     \
  SpecificDbg((s->state_machine && s->state_machine->debug_on), dbg_ctl_http_trans, "Next action %s; %s", #n, #r);

#define TRANSACT_RETURN(n, r) \
  TRANSACT_SETUP_RETURN(n, r) \
  return;

#define TRANSACT_RETURN_VAL(n, r, v) \
  TRANSACT_SETUP_RETURN(n, r)        \
  return v;

#define SET_UNPREPARE_CACHE_ACTION(C)                                        \
  {                                                                          \
    if (C.action == HttpTransact::CacheAction_t::PREPARE_TO_DELETE) {        \
      C.action = HttpTransact::CacheAction_t::DELETE;                        \
    } else if (C.action == HttpTransact::CacheAction_t::PREPARE_TO_UPDATE) { \
      C.action = HttpTransact::CacheAction_t::UPDATE;                        \
    } else {                                                                 \
      C.action = HttpTransact::CacheAction_t::WRITE;                         \
    }                                                                        \
  }

#define TxnDbg(ctl, fmt, ...) \
  SpecificDbg((s->state_machine->debug_on), ctl, "[%" PRId64 "] " fmt, s->state_machine->sm_id, ##__VA_ARGS__)

extern HttpBodyFactory *body_factory;

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static bool
bypass_ok(HttpTransact::State *s)
{
  if (s->response_action.handled) {
    return s->response_action.action.goDirect;
  } else if (nullptr != s->next_hop_strategy) {
    // remap strategies do not support the TSHttpTxnParentProxySet API.
    return s->next_hop_strategy->go_direct;
  } else if (nullptr != s->parent_params) {
    return s->parent_result.bypass_ok();
  }
  return false;
}

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static bool
is_api_result(HttpTransact::State *s)
{
  bool r = false;
  if (nullptr != s->next_hop_strategy) {
    // remap strategies do not support the TSHttpTxnParentProxySet API.
    r = false;
  } else if (nullptr != s->parent_params) {
    r = s->parent_result.is_api_result();
  }
  return r;
}

// wrapper to get the max_retries.
// Does NOT check the strategy; if strategy exists, strategy->responseIsRetryable should be called instead.
inline static unsigned
max_retries(HttpTransact::State *s, ParentRetry_t method)
{
  if (s->parent_params) {
    return s->parent_result.max_retries(method);
  }
  return 0;
}

// wrapper to get the numParents.
// Does NOT check the strategy; if strategy exists, strategy->responseIsRetryable should be called instead.
inline static uint32_t
numParents(HttpTransact::State *s)
{
  if (s->parent_params) {
    return s->parent_params->numParents(&s->parent_result);
  }
  return 0;
}

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static bool
parent_is_proxy(HttpTransact::State *s)
{
  if (s->response_action.handled) {
    return s->response_action.action.parentIsProxy;
  } else if (nullptr != s->next_hop_strategy) {
    return s->next_hop_strategy->parent_is_proxy;
  } else if (nullptr != s->parent_params) {
    return s->parent_result.parent_is_proxy();
  }
  return false;
}

// wrapper to get the parent.config retry type.
// Does NOT check the strategy; if strategy exists, strategy->responseIsRetryable should be called instead.
inline static ParentRetry_t
retry_type(HttpTransact::State *s)
{
  if (s->parent_params) {
    return s->parent_result.retry_type();
  }
  return ParentRetry_t::NONE;
}

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static void
findParent(HttpTransact::State *s)
{
  Metrics::Counter::increment(http_rsb.parent_count);
  if (s->response_action.handled) {
    s->parent_result.hostname = s->response_action.action.hostname;
    s->parent_result.port     = s->response_action.action.port;
    s->parent_result.retry    = s->response_action.action.is_retry;
    if (!s->response_action.action.fail) {
      s->parent_result.result = ParentResultType::SPECIFIED;
    } else if (s->response_action.action.goDirect) {
      s->parent_result.result = ParentResultType::DIRECT;
    } else {
      s->parent_result.result = ParentResultType::FAIL;
    }
  } else if (nullptr != s->next_hop_strategy) {
    s->next_hop_strategy->findNextHop(reinterpret_cast<TSHttpTxn>(s->state_machine));
  } else if (nullptr != s->parent_params) {
    s->parent_params->findParent(&s->request_data, &s->parent_result, s->txn_conf->parent_fail_threshold,
                                 s->txn_conf->parent_retry_time);
  }
}

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static void
markParentDown(HttpTransact::State *s)
{
  TxnDbg(dbg_ctl_http_trans, "enable_parent_timeout_markdowns: %d, disable_parent_markdowns: %d",
         s->txn_conf->enable_parent_timeout_markdowns, s->txn_conf->disable_parent_markdowns);

  if (s->txn_conf->disable_parent_markdowns == 1) {
    TxnDbg(dbg_ctl_http_trans, "parent markdowns are disabled for this request");
    return;
  }

  if (s->current.state == HttpTransact::INACTIVE_TIMEOUT) {
    if (s->txn_conf->enable_parent_timeout_markdowns == 0) {
      return;
    }
    Metrics::Counter::increment(http_rsb.total_parent_marked_down_timeout);
  }
  // Increment metric when config allows ATS to mark parent down
  Metrics::Counter::increment(http_rsb.total_parent_marked_down_count);

  if (s->response_action.handled) {
    // Do nothing. If a plugin handled the response, let it handle markdown.
  } else if (nullptr != s->next_hop_strategy) {
    s->next_hop_strategy->markNextHop(reinterpret_cast<TSHttpTxn>(s->state_machine), s->parent_result.hostname,
                                      s->parent_result.port, NHCmd::MARK_DOWN);
  } else if (nullptr != s->parent_params) {
    s->parent_params->markParentDown(&s->parent_result, s->txn_conf->parent_fail_threshold, s->txn_conf->parent_retry_time);
  }
}

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static void
markParentUp(HttpTransact::State *s)
{
  if (s->response_action.handled) {
    // Do nothing. If a plugin handled the response, let it handle markdown
  } else if (nullptr != s->next_hop_strategy) {
    s->next_hop_strategy->markNextHop(reinterpret_cast<TSHttpTxn>(s->state_machine), s->parent_result.hostname,
                                      s->parent_result.port, NHCmd::MARK_UP);
  } else if (nullptr != s->parent_params) {
    s->parent_params->markParentUp(&s->parent_result);
  }
}

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static bool
parentExists(HttpTransact::State *s)
{
  if (s->response_action.handled) {
    return s->response_action.action.nextHopExists;
  } else if (nullptr != s->next_hop_strategy) {
    return s->next_hop_strategy->nextHopExists(reinterpret_cast<TSHttpTxn>(s->state_machine));
  } else if (nullptr != s->parent_params) {
    return s->parent_params->parentExists(&s->request_data);
  } else {
    return false;
  }
}

// wrapper to choose between a remap next hop strategy or use parent.config
// remap next hop strategy is preferred
inline static void
nextParent(HttpTransact::State *s)
{
  TxnDbg(dbg_ctl_parent_down, "connection to parent %s failed, conn_state: %s, request to origin: %s", s->parent_result.hostname,
         HttpDebugNames::get_server_state_name(s->current.state), s->request_data.get_host());
  Metrics::Counter::increment(http_rsb.parent_count);
  if (s->response_action.handled) {
    s->parent_result.hostname = s->response_action.action.hostname;
    s->parent_result.port     = s->response_action.action.port;
    s->parent_result.retry    = s->response_action.action.is_retry;
    if (!s->response_action.action.fail) {
      s->parent_result.result = ParentResultType::SPECIFIED;
    } else if (s->response_action.action.goDirect) {
      s->parent_result.result = ParentResultType::DIRECT;
    } else {
      s->parent_result.result = ParentResultType::FAIL;
    }
  } else if (nullptr != s->next_hop_strategy) {
    // NextHop only has a findNextHop() function.
    s->next_hop_strategy->findNextHop(reinterpret_cast<TSHttpTxn>(s->state_machine));
  } else if (nullptr != s->parent_params) {
    s->parent_params->nextParent(&s->request_data, &s->parent_result, s->txn_conf->parent_fail_threshold,
                                 s->txn_conf->parent_retry_time);
  }
}

inline static bool
is_localhost(std::string_view name)
{
  return name == "127.0.0.1"sv;
}

bool
HttpTransact::is_response_valid(State *s, HTTPHdr *incoming_response)
{
  if (s->current.state != CONNECTION_ALIVE) {
    ink_assert((s->current.state == CONNECTION_ERROR) || (s->current.state == OPEN_RAW_ERROR) ||
               (s->current.state == PARSE_ERROR) || (s->current.state == CONNECTION_CLOSED) ||
               (s->current.state == INACTIVE_TIMEOUT) || (s->current.state == ACTIVE_TIMEOUT) ||
               s->current.state == OUTBOUND_CONGESTION || s->current.state == BAD_INCOMING_RESPONSE);

    s->hdr_info.response_error = ResponseError_t::CONNECTION_OPEN_FAILED;
    return false;
  }

  s->hdr_info.response_error = check_response_validity(s, incoming_response);

  switch (s->hdr_info.response_error) {
#ifdef REALLY_NEED_TO_CHECK_DATE_VALIDITY
  case ResponseError_t::BOGUS_OR_NO_DATE_IN_RESPONSE:
    // We could modify the response to add the date, if need be.
    //          incoming_response->set_date(s->request_sent_time);
    return true;
#endif
  case ResponseError_t::NO_RESPONSE_HEADER_ERROR:
    TxnDbg(dbg_ctl_http_trans, "No errors in response");
    return true;

  case ResponseError_t::MISSING_REASON_PHRASE:
    TxnDbg(dbg_ctl_http_trans, "Response Error: Missing reason phrase - allowing");
    return true;

  case ResponseError_t::STATUS_CODE_SERVER_ERROR:
    TxnDbg(dbg_ctl_http_trans, "Response Error: Origin Server returned 500 - allowing");
    return true;

  case ResponseError_t::CONNECTION_OPEN_FAILED:
    TxnDbg(dbg_ctl_http_trans, "Response Error: connection open failed");
    s->current.state = CONNECTION_ERROR;
    return false;

  case ResponseError_t::NON_EXISTANT_RESPONSE_HEADER:
    TxnDbg(dbg_ctl_http_trans, "Response Error: No response header");
    s->current.state = BAD_INCOMING_RESPONSE;
    return false;

  case ResponseError_t::NOT_A_RESPONSE_HEADER:
    TxnDbg(dbg_ctl_http_trans, "Response Error: Not a response header");
    s->current.state = BAD_INCOMING_RESPONSE;
    return false;

  case ResponseError_t::MISSING_STATUS_CODE:
    TxnDbg(dbg_ctl_http_trans, "Response Error: Missing status code");
    s->current.state = BAD_INCOMING_RESPONSE;
    return false;

  default:
    TxnDbg(dbg_ctl_http_trans, "Errors in response");
    s->current.state = BAD_INCOMING_RESPONSE;
    return false;
  }
}

inline static ParentRetry_t
response_is_retryable(HttpTransact::State *s, HTTPStatus response_code)
{
  if (!HttpTransact::is_response_valid(s, &s->hdr_info.server_response) || s->current.request_to != ResolveInfo::PARENT_PROXY) {
    return ParentRetry_t::NONE;
  }
  if (s->response_action.handled) {
    return s->response_action.action.responseIsRetryable ? ParentRetry_t::SIMPLE : ParentRetry_t::NONE;
  }
  if (nullptr != s->next_hop_strategy) {
    return s->next_hop_strategy->responseIsRetryable(s->state_machine->sm_id, s->current, response_code);
  }

  if (nullptr != s->parent_params && !s->parent_result.response_is_retryable(s->parent_result.retry_type(), response_code)) {
    return ParentRetry_t::NONE;
  }
  const ParentRetry_t s_retry_type = retry_type(s);
  // If simple or both, check if code is simple-retryable and for retry attempts
  if ((s_retry_type == ParentRetry_t::SIMPLE || s_retry_type == ParentRetry_t::BOTH) &&
      s->parent_result.response_is_retryable(ParentRetry_t::SIMPLE, response_code) &&
      s->current.simple_retry_attempts < max_retries(s, ParentRetry_t::SIMPLE)) {
    TxnDbg(dbg_ctl_http_trans, "saw parent retry simple first in trans");
    if (s->current.simple_retry_attempts < numParents(s)) {
      return ParentRetry_t::SIMPLE;
    }
    return ParentRetry_t::NONE;
  }
  // If unavailable or both, check if code is unavailable-retryable AND also not simple-retryable, then unavailable retry attempts
  if ((s_retry_type == ParentRetry_t::UNAVAILABLE_SERVER || s_retry_type == ParentRetry_t::BOTH) &&
      s->parent_result.response_is_retryable(ParentRetry_t::UNAVAILABLE_SERVER, response_code) &&
      !s->parent_result.response_is_retryable(ParentRetry_t::SIMPLE, response_code) &&
      s->current.unavailable_server_retry_attempts < max_retries(s, ParentRetry_t::UNAVAILABLE_SERVER)) {
    TxnDbg(dbg_ctl_http_trans, "saw parent retry unavailable first in trans");
    if (s->current.unavailable_server_retry_attempts < numParents(s)) {
      return ParentRetry_t::UNAVAILABLE_SERVER;
    }
    return ParentRetry_t::NONE;
  }
  return ParentRetry_t::NONE;
}

inline static void
simple_or_unavailable_server_retry(HttpTransact::State *s)
{
  if (!HttpTransact::is_response_valid(s, &s->hdr_info.server_response)) {
    return; // must return now if the response isn't valid, before calling http_hdr_status_get on uninitialized data
  }

  HTTPStatus server_response = http_hdr_status_get(s->hdr_info.server_response.m_http);
  switch (response_is_retryable(s, server_response)) {
  case ParentRetry_t::SIMPLE:
    s->current.state      = HttpTransact::PARENT_RETRY;
    s->current.retry_type = ParentRetry_t::SIMPLE;
    break;
  case ParentRetry_t::UNAVAILABLE_SERVER:
    s->current.state      = HttpTransact::PARENT_RETRY;
    s->current.retry_type = ParentRetry_t::UNAVAILABLE_SERVER;
    break;
  case ParentRetry_t::BOTH:
    ink_assert(!"response_is_retryable should return an exact retry type, never both");
    break;
  case ParentRetry_t::NONE:
    break; // no retry
  }
}

inline static bool
is_request_conditional(HTTPHdr *header)
{
  uint64_t mask = (MIME_PRESENCE_IF_UNMODIFIED_SINCE | MIME_PRESENCE_IF_MODIFIED_SINCE | MIME_PRESENCE_IF_RANGE |
                   MIME_PRESENCE_IF_MATCH | MIME_PRESENCE_IF_NONE_MATCH);
  return (header->presence(mask) &&
          (header->method_get_wksidx() == HTTP_WKSIDX_GET || header->method_get_wksidx() == HTTP_WKSIDX_HEAD));
}

static inline bool
is_port_in_range(int port, HttpConfigPortRange *pr)
{
  while (pr) {
    if (pr->low == -1) {
      return true;
    } else if ((pr->low <= port) && (pr->high >= port)) {
      return true;
    }

    pr = pr->next;
  }

  return false;
}

inline static void
update_cache_control_information_from_config(HttpTransact::State *s)
{
  getCacheControl(&s->cache_control, &s->request_data, s->txn_conf);

  s->cache_info.directives.does_config_permit_lookup  &= (s->cache_control.never_cache == false);
  s->cache_info.directives.does_config_permit_storing &= (s->cache_control.never_cache == false);

  s->cache_info.directives.does_client_permit_storing =
    HttpTransact::does_client_request_permit_storing(&s->cache_control, &s->hdr_info.client_request);

  s->cache_info.directives.does_client_permit_lookup = HttpTransact::does_client_request_permit_cached_response(
    s->txn_conf, &s->cache_control, &s->hdr_info.client_request, s->via_string);

  s->cache_info.directives.does_client_permit_dns_storing =
    HttpTransact::does_client_request_permit_dns_caching(&s->cache_control, &s->hdr_info.client_request);

  if (s->client_info.http_version == HTTP_0_9) {
    s->cache_info.directives.does_client_permit_lookup  = false;
    s->cache_info.directives.does_client_permit_storing = false;
  }

  // Less than 0 means it wasn't overridden, so leave it alone.
  if (s->cache_control.cache_responses_to_cookies >= 0) {
    s->my_txn_conf().cache_responses_to_cookies = s->cache_control.cache_responses_to_cookies;
  }
}

bool
HttpTransact::is_server_negative_cached(State *s)
{
  if (s->dns_info.active && s->dns_info.active->last_fail_time() != TS_TIME_ZERO &&
      s->dns_info.active->last_fail_time() + s->txn_conf->down_server_timeout > ts_clock::from_time_t(s->client_request_time)) {
    return true;
  } else {
    // Make sure some nasty clock skew has not happened
    //  Use the server timeout to set an upperbound as to how far in the
    //   future we should tolerate bogus last failure times.  This sets
    //   the upper bound to the time that we would ever consider a server
    //   down to 2*down_server_timeout
    if (s->dns_info.active &&
        ts_clock::from_time_t(s->client_request_time) + s->txn_conf->down_server_timeout < s->dns_info.active->last_fail_time()) {
      s->dns_info.active->mark_up();
      ink_assert(!"extreme clock skew");
      return true;
    }
    return false;
  }
}

inline static void
update_current_info(HttpTransact::CurrentInfo *into, HttpTransact::ConnectionAttributes *from,
                    ResolveInfo::UpstreamResolveStyle who, bool clear_retry_attempts)
{
  into->request_to = who;
  into->server     = from;
  if (clear_retry_attempts) {
    into->retry_attempts.clear();
  }
}

inline static void
update_dns_info(ResolveInfo *dns, HttpTransact::CurrentInfo *from)
{
  dns->looking_up  = from->request_to;
  dns->lookup_name = from->server->name;
  if (dns->os_addr_style != ResolveInfo::OS_Addr::USE_API) {
    dns->resolved_p = false;
  }
}

inline static HTTPHdr *
find_appropriate_cached_resp(HttpTransact::State *s)
{
  HTTPHdr *c_resp = nullptr;

  if (s->cache_info.object_store.valid()) {
    c_resp = s->cache_info.object_store.response_get();
    if (c_resp != nullptr && c_resp->valid()) {
      return c_resp;
    }
  }

  ink_assert(s->cache_info.object_read != nullptr);
  return s->cache_info.object_read->response_get();
}

int response_cacheable_indicated_by_cc(HTTPHdr *response, bool ignore_no_store_and_no_cache_directives);

inline static bool
is_negative_caching_appropriate(HttpTransact::State *s)
{
  if (!s->txn_conf->negative_caching_enabled || !s->hdr_info.server_response.valid()) {
    return false;
  }

  auto status = static_cast<int>(s->hdr_info.server_response.status_get());
  if (s->txn_conf->negative_caching_list.contains(status)) {
    TxnDbg(dbg_ctl_http_trans, "%d is eligible for negative caching", status);
    return true;
  } else {
    TxnDbg(dbg_ctl_http_trans, "%d is NOT eligible for negative caching", status);
    return false;
  }
}

inline static ResolveInfo::UpstreamResolveStyle
find_server_and_update_current_info(HttpTransact::State *s)
{
  auto host{s->hdr_info.client_request.host_get()};

  if (is_localhost(host)) {
    // Do not forward requests to local_host onto a parent.
    // I just wanted to do this for cop heartbeats, someone else
    // wanted it for all requests to local_host.
    TxnDbg(dbg_ctl_http_trans, "request is from localhost, so bypass parent");
    s->parent_result.result = ParentResultType::DIRECT;
  } else if (s->method == HTTP_WKSIDX_CONNECT && s->http_config_param->disable_ssl_parenting) {
    if (s->parent_result.result == ParentResultType::SPECIFIED) {
      nextParent(s);
    } else {
      findParent(s);
    }
    if (!s->parent_result.is_some() || is_api_result(s) || parent_is_proxy(s)) {
      TxnDbg(dbg_ctl_http_trans, "request not cacheable, so bypass parent");
      s->parent_result.result = ParentResultType::DIRECT;
    }
  } else if (s->txn_conf->uncacheable_requests_bypass_parent && s->txn_conf->no_dns_forward_to_parent == 0 &&
             !HttpTransact::is_request_cache_lookupable(s)) {
    // request not lookupable and cacheable, so bypass parent if the parent is not an origin server.
    // Note that the configuration of the proxy as well as the request
    // itself affects the result of is_request_cache_lookupable();
    // we are assuming both child and parent have similar configuration
    // with respect to whether a request is cacheable or not.
    // For example, the cache_urls_that_look_dynamic variable.
    if (s->parent_result.result == ParentResultType::SPECIFIED) {
      nextParent(s);
    } else {
      findParent(s);
    }
    if (!s->parent_result.is_some() || is_api_result(s) || parent_is_proxy(s)) {
      TxnDbg(dbg_ctl_http_trans, "request not cacheable, so bypass parent");
      s->parent_result.result = ParentResultType::DIRECT;
    }
  } else {
    switch (s->parent_result.result) {
    case ParentResultType::UNDEFINED:
      findParent(s);
      break;
    case ParentResultType::SPECIFIED:
      nextParent(s);

      // Hack!
      // We already have a parent that failed, if we are now told
      //  to go the origin server, we can only obey this if we
      //  dns'ed the origin server
      if (s->parent_result.result == ParentResultType::DIRECT && s->txn_conf->no_dns_forward_to_parent != 0) {
        ink_assert(!s->server_info.dst_addr.isValid());
        s->parent_result.result = ParentResultType::FAIL;
      }
      break;
    case ParentResultType::FAIL:
      // Check to see if should bypass the parent and go direct
      //   We can only do this if
      //   1) the config permitted us to dns the origin server
      //   2) the config permits us
      //   3) the parent was not set from API
      if (s->txn_conf->no_dns_forward_to_parent == 0 && bypass_ok(s) && parent_is_proxy(s) &&
          !s->parent_params->apiParentExists(&s->request_data)) {
        s->parent_result.result = ParentResultType::DIRECT;
      }
      break;
    default:
      ink_assert(0);
    // FALL THROUGH
    case ParentResultType::DIRECT:
      //              // if we have already decided to go direct
      //              // dont bother calling nextParent.
      //              // do nothing here, guy.
      break;
    }
  }

  switch (s->parent_result.result) {
  case ParentResultType::SPECIFIED:
    s->parent_info.name = s->arena.str_store(s->parent_result.hostname, strlen(s->parent_result.hostname));
    update_current_info(&s->current, &s->parent_info, ResolveInfo::PARENT_PROXY, false);
    update_dns_info(&s->dns_info, &s->current);
    ink_assert(s->dns_info.looking_up == ResolveInfo::PARENT_PROXY);
    s->next_hop_scheme = URL_WKSIDX_HTTP;

    return ResolveInfo::PARENT_PROXY;
  case ParentResultType::FAIL:
    // No more parents - need to return an error message
    s->current.request_to = ResolveInfo::HOST_NONE;
    return ResolveInfo::HOST_NONE;

  case ParentResultType::DIRECT:
    // if the configuration does not allow the origin to be dns'd
    // we're unable to go direct to the origin.
    if (s->txn_conf->no_dns_forward_to_parent) {
      Warning("no available parents and the config proxy.config.http.no_dns_just_forward_to_parent, prevents origin lookups.");
      s->parent_result.result = ParentResultType::FAIL;
      return ResolveInfo::HOST_NONE;
    }
  /* fall through */
  default:
    update_current_info(&s->current, &s->server_info, ResolveInfo::ORIGIN_SERVER, false);
    update_dns_info(&s->dns_info, &s->current);
    ink_assert(s->dns_info.looking_up == ResolveInfo::ORIGIN_SERVER);
    s->next_hop_scheme = s->scheme;
    return ResolveInfo::ORIGIN_SERVER;
  }
}

inline static bool
do_cookies_prevent_caching(int cookies_conf, HTTPHdr *request, HTTPHdr *response, HTTPHdr *cached_request = nullptr)
{
  enum class CookiesConfig {
    CACHE_NONE             = 0, // do not cache any responses to cookies
    CACHE_ALL              = 1, // cache for any content-type (ignore cookies)
    CACHE_IMAGES           = 2, // cache only for image types
    CACHE_ALL_BUT_TEXT     = 3, // cache for all but text content-types
    CACHE_ALL_BUT_TEXT_EXT = 4  // cache for all but text content-types except with OS response
                                // without "Set-Cookie" or with "Cache-Control: public"
  };

#ifdef DEBUG
  ink_assert(request->type_get() == HTTPType::REQUEST);
  ink_assert(response->type_get() == HTTPType::RESPONSE);
  if (cached_request) {
    ink_assert(cached_request->type_get() == HTTPType::REQUEST);
  }
#endif

  // Can cache all regardless of cookie header - just ignore all cookie headers
  if (static_cast<CookiesConfig>(cookies_conf) == CookiesConfig::CACHE_ALL) {
    return false;
  }

  // It is considered that Set-Cookie headers can be safely ignored
  // for non text content types if Cache-Control private is not set.
  // This enables a bigger hit rate, which currently outweighs the risk of
  // breaking origin servers that truly intend to set a cookie with other
  // objects such as images.
  // At this time, it is believed that only advertisers do this, and that
  // customers won't care about it.

  // If the response does not have a Set-Cookie header and
  // the response does not have a Cookie header and
  // the object is not cached or the request does not have a Cookie header
  // then cookies do not prevent caching.
  if (!response->presence(MIME_PRESENCE_SET_COOKIE) && !request->presence(MIME_PRESENCE_COOKIE) &&
      (cached_request == nullptr || !cached_request->presence(MIME_PRESENCE_COOKIE))) {
    return false;
  }

  // Do not cache if cookies option is CookiesConfig::CACHE_NONE
  // and a Cookie is detected
  if (static_cast<CookiesConfig>(cookies_conf) == CookiesConfig::CACHE_NONE) {
    return true;
  }
  // All other options depend on the Content-Type
  auto content_type{response->value_get(static_cast<std::string_view>(MIME_FIELD_CONTENT_TYPE))};

  if (static_cast<CookiesConfig>(cookies_conf) == CookiesConfig::CACHE_IMAGES) {
    if (content_type.starts_with("image"sv)) {
      // Images can be cached
      return false;
    }
    return true; // do not cache if  CookiesConfig::CACHE_IMAGES && content_type != "image"
  }
  // CookiesConfig::CACHE_ALL_BUT_TEXT || CookiesConfig::CACHE_ALL_BUT_TEXT_EXT
  // Note: if the configuration is bad, we consider
  // CookiesConfig::CACHE_ALL_BUT_TEXT to be the default

  if (content_type.starts_with("text"sv)) { // content type  - "text"
    // Text objects cannot be cached unless the option is
    // CookiesConfig::CACHE_ALL_BUT_TEXT_EXT.
    // Furthermore, if there is a Set-Cookie header, then
    // Cache-Control must be set.
    if (static_cast<CookiesConfig>(cookies_conf) == CookiesConfig::CACHE_ALL_BUT_TEXT_EXT &&
        ((!response->presence(MIME_PRESENCE_SET_COOKIE)) || response->is_cache_control_set(HTTP_VALUE_PUBLIC.c_str()))) {
      return false;
    }
    return true;
  }
  return false; // Non text objects can be cached
}

inline static bool
does_method_require_cache_copy_deletion(const OverridableHttpConfigParams *http_config_param, const int method)
{
  return ((method != HTTP_WKSIDX_GET) &&
          (method == HTTP_WKSIDX_DELETE || method == HTTP_WKSIDX_PURGE || method == HTTP_WKSIDX_PUT ||
           (http_config_param->cache_post_method != 1 && method == HTTP_WKSIDX_POST)));
}

inline static bool
does_method_effect_cache(int method)
{
  return ((method == HTTP_WKSIDX_GET || method == HTTP_WKSIDX_DELETE || method == HTTP_WKSIDX_PURGE || method == HTTP_WKSIDX_PUT ||
           method == HTTP_WKSIDX_POST));
}

inline static HttpTransact::StateMachineAction_t
how_to_open_connection(HttpTransact::State *s)
{
  ink_assert((s->pending_work == nullptr) || (s->current.request_to == ResolveInfo::PARENT_PROXY));

  // Originally we returned which type of server to open
  // Now, however, we may want to issue a cache
  // operation first in order to lock the cache
  // entry to prevent multiple origin server requests
  // for the same document.
  // The cache operation that we actually issue, of
  // course, depends on the specified "cache_action".
  // If there is no cache-action to be issued, just
  // connect to the server.
  switch (s->cache_info.action) {
  case HttpTransact::CacheAction_t::PREPARE_TO_DELETE:
  case HttpTransact::CacheAction_t::PREPARE_TO_UPDATE:
  case HttpTransact::CacheAction_t::PREPARE_TO_WRITE:
    s->transact_return_point = HttpTransact::handle_cache_write_lock;
    return HttpTransact::StateMachineAction_t::CACHE_ISSUE_WRITE;
  default:
    // This covers:
    // CacheAction_t::UNDEFINED, CacheAction_t::NO_ACTION, CacheAction_t::DELETE,
    // CacheAction_t::LOOKUP, CacheAction_t::REPLACE, CacheAction_t::SERVE,
    // CacheAction_t::SERVE_AND_DELETE, CacheAction_t::SERVE_AND_UPDATE,
    // CacheAction_t::UPDATE, CacheAction_t::WRITE, CacheAction_t::TOTAL_TYPES
    break;
  }

  HttpTransact::StateMachineAction_t connect_next_action = HttpTransact::StateMachineAction_t::ORIGIN_SERVER_OPEN;

  // Setting up a direct CONNECT tunnel enters OriginServerRawOpen. We always do that if we
  // are not forwarding CONNECT and are not going to a parent proxy.
  if (s->method == HTTP_WKSIDX_CONNECT) {
    if (s->txn_conf->forward_connect_method != 1 && s->parent_result.result != ParentResultType::SPECIFIED) {
      connect_next_action = HttpTransact::StateMachineAction_t::ORIGIN_SERVER_RAW_OPEN;
    }
  }

  if (!s->already_downgraded) { // false unless downgraded previously (possibly due to HTTP 505)
    (&s->hdr_info.server_request)->version_set(HTTP_1_1);
    HttpTransactHeaders::convert_request(s->current.server->http_version, &s->hdr_info.server_request);
  }

  return connect_next_action;
}

/*****************************************************************************
 *****************************************************************************
 ****                                                                     ****
 ****                 HttpTransact State Machine Handlers                 ****
 ****                                                                     ****
 **** What follow from here on are the state machine handlers - the code  ****
 **** which is called from HttpSM::set_next_state to specify              ****
 **** what action the state machine needs to execute next. These ftns     ****
 **** take as input just the state and set the next_action variable.      ****
 *****************************************************************************
 *****************************************************************************/
void
HttpTransact::BadRequest(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "parser marked request bad");
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);

  const char *body_factory_template = "request#syntax_error";
  HTTPStatus  status                = HTTPStatus::BAD_REQUEST;
  const char *reason                = "Invalid HTTP Request";

  switch (s->http_return_code) {
  case HTTPStatus::REQUEST_URI_TOO_LONG:
    body_factory_template = "request#uri_len_too_long";
    status                = s->http_return_code;
    reason                = "URI Too Long";
    break;
  case HTTPStatus::NOT_IMPLEMENTED:
    status                = s->http_return_code;
    reason                = "Field not implemented";
    body_factory_template = "transcoding#unsupported";
    break;
  case HTTPStatus::HTTPVER_NOT_SUPPORTED:
    status = s->http_return_code;
    reason = "Unsupported HTTP Version";
  default:
    break;
  }

  build_error_response(s, status, reason, body_factory_template);
  s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::PostActiveTimeoutResponse(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "post active timeout");
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
  build_error_response(s, HTTPStatus::REQUEST_TIMEOUT, "Active Timeout", "timeout#activity");
  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::PostInactiveTimeoutResponse(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "post inactive timeout");
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
  build_error_response(s, HTTPStatus::REQUEST_TIMEOUT, "Inactive Timeout", "timeout#inactivity");
  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::Forbidden(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "IpAllow marked request forbidden");
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
  s->http_return_code_setter_name = "ip_allow";
  build_error_response(s, HTTPStatus::FORBIDDEN, "Access Denied", "access#denied");
  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::SelfLoop(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "Request will selfloop.");
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::TooEarly(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "Early Data method is not safe");
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
  build_error_response(s, HTTPStatus::TOO_EARLY, "Too Early", "too#early");
  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::OriginDown(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "origin server is marked down");
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
  build_error_response(s, HTTPStatus::BAD_GATEWAY, "Origin Server Marked Down", "connect#failed_connect");
  Metrics::Counter::increment(http_rsb.down_server_no_requests);
  char            *url_str = s->hdr_info.client_request.url_string_get_ref(nullptr);
  std::string_view host_name{s->unmapped_url.host_get()};
  swoc::bwprint(error_bw_buffer, "CONNECT: down server no request to {} for host='{}' url='{}'", s->current.server->dst_addr,
                host_name, swoc::bwf::FirstOf(url_str, "<none>"));
  Log::error("%s", error_bw_buffer.c_str());

  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::HandleBlindTunnel(State *s)
{
  URL u;
  // IpEndpoint dest_addr;
  // ip_text_buffer new_host;

  TxnDbg(dbg_ctl_http_trans, "Entering HttpTransact::HandleBlindTunnel");

  // We set the version to 0.9 because once we know where we are going
  //   this blind ssl tunnel is indistinguishable from a "CONNECT 0.9"
  //   except for the need to suppression error messages
  HTTPVersion ver(0, 9);
  s->hdr_info.client_request.version_set(ver);

  // Initialize the state vars necessary to sending error responses
  bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);

  if (dbg_ctl_http_trans.on()) {
    auto host{s->hdr_info.client_request.url_get()->host_get()};
    TxnDbg(dbg_ctl_http_trans, "destination set to %.*s:%d", static_cast<int>(host.length()), host.data(),
           s->hdr_info.client_request.url_get()->port_get());
  }

  // Set the mode to tunnel so that we don't lookup the cache
  s->current.mode = ProxyMode_t::TUNNELLING;

  // Let the request work it's way through the code and
  //  we grab it again after the raw connection has been opened
  HandleRequest(s);
}

void
HttpTransact::StartRemapRequest(State *s)
{
  // Preserve effective url before remap, regardless of actual need for remap
  s->unmapped_url.create(s->hdr_info.client_request.url_get()->m_heap);
  s->unmapped_url.copy(s->hdr_info.client_request.url_get());

  if (s->api_skip_all_remapping) {
    TxnDbg(dbg_ctl_http_trans, "API request to skip remapping");

    s->hdr_info.client_request.set_url_target_from_host_field();

    // Since we're not doing remap, we still have to allow for these overridable
    // configurations to modify follow-redirect behavior. Someone could for example
    // have set them in a plugin other than conf_remap running in a prior hook.
    s->state_machine->enable_redirection = (s->txn_conf->number_of_redirections > 0);

    if (s->is_upgrade_request && s->post_remap_upgrade_return_point) {
      TRANSACT_RETURN(StateMachineAction_t::POST_REMAP_SKIP, s->post_remap_upgrade_return_point);
    }

    TRANSACT_RETURN(StateMachineAction_t::POST_REMAP_SKIP, HttpTransact::HandleRequest);
  }

  TxnDbg(dbg_ctl_http_trans, "START HttpTransact::StartRemapRequest");

  //////////////////////////////////////////////////////////////////
  // FIX: this logic seems awfully convoluted and hard to follow; //
  //      seems like we could come up with a more elegant and     //
  //      comprehensible design that generalized things           //
  //////////////////////////////////////////////////////////////////

  /////////////////////////////////////////////////////////////////
  // run the remap url-rewriting engine:                         //
  //                                                             //
  // * the variable <url_remap_success> is set true if           //
  //   the url was rewritten                                     //
  //                                                             //
  // * the variable <remap_redirect> is set to non-NULL if there //
  //   is a URL provided that the proxy is supposed to redirect  //
  //   requesters of a particular URL to.                        //
  /////////////////////////////////////////////////////////////////

  if (dbg_ctl_http_chdr_describe.on() || dbg_ctl_http_trans.on()) {
    TxnDbg(dbg_ctl_http_trans, "Before Remapping:");
    obj_describe(s->hdr_info.client_request.m_http, true);
  }
  dump_header(dbg_ctl_http_hdrs, &s->hdr_info.client_request, s->state_machine_id(), "Incoming Request");

  if (s->http_config_param->referer_filter_enabled) {
    s->filter_mask = URL_REMAP_FILTER_REFERER;
    if (s->http_config_param->referer_format_redirect) {
      s->filter_mask |= URL_REMAP_FILTER_REDIRECT_FMT;
    }
  }

  TxnDbg(dbg_ctl_http_trans, "END HttpTransact::StartRemapRequest");

  TxnDbg(dbg_ctl_http_trans, "Checking if transaction wants to upgrade");
  if (handle_upgrade_request(s)) {
    // everything should be handled by the upgrade handler.
    TxnDbg(dbg_ctl_http_trans, "Transaction will be upgraded by the appropriate upgrade handler.");
    return;
  }

  TRANSACT_RETURN(StateMachineAction_t::API_PRE_REMAP, HttpTransact::PerformRemap);
}

void
HttpTransact::PerformRemap(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "Inside PerformRemap");
  TRANSACT_RETURN(StateMachineAction_t::REMAP_REQUEST, HttpTransact::EndRemapRequest);
}

void
HttpTransact::EndRemapRequest(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "START HttpTransact::EndRemapRequest");

  HTTPHdr *incoming_request = &s->hdr_info.client_request;
  int      method           = incoming_request->method_get_wksidx();
  auto     host{incoming_request->host_get()};
  TxnDbg(dbg_ctl_http_trans, "EndRemapRequest host is %.*s", static_cast<int>(host.length()), host.data());
  if (s->state_machine->get_ua_txn()) {
    s->state_machine->get_ua_txn()->set_default_inactivity_timeout(HRTIME_SECONDS(s->txn_conf->default_inactivity_timeout));
  }

  // Setting enable_redirection according to HttpConfig (master or overridable). We
  // defer this as late as possible, to allow plugins to modify the overridable
  // configurations (e.g. conf_remap.so). We intentionally only modify this if
  // the configuration says so.
  s->state_machine->enable_redirection = (s->txn_conf->number_of_redirections > 0);

  ////////////////////////////////////////////////////////////////
  // if we got back a URL to redirect to, vector the user there //
  ////////////////////////////////////////////////////////////////
  if (s->remap_redirect != nullptr) {
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    const char *error_body_type;
    switch (s->http_return_code) {
    case HTTPStatus::MOVED_PERMANENTLY:
    case HTTPStatus::PERMANENT_REDIRECT:
    case HTTPStatus::SEE_OTHER:
    case HTTPStatus::USE_PROXY:
      error_body_type = "redirect#moved_permanently";
      break;
    case HTTPStatus::MOVED_TEMPORARILY:
    case HTTPStatus::TEMPORARY_REDIRECT:
      error_body_type = "redirect#moved_temporarily";
      break;
    default:
      if (HTTPStatus::NONE == s->http_return_code) {
        s->http_return_code = HTTPStatus::MOVED_TEMPORARILY;
        Warning("Changed status code from '0' to '%d'.", static_cast<int>(s->http_return_code));
      } else {
        Warning("Using invalid status code for redirect '%d'. Building a response for a temporary redirect.",
                static_cast<int>(s->http_return_code));
      }
      error_body_type = "redirect#moved_temporarily";
    }
    build_error_response(s, s->http_return_code, "Redirect", error_body_type);
    ats_free(s->remap_redirect);
    s->reverse_proxy = false;
    goto done;
  }
  /////////////////////////////////////////////////////
  // Quick HTTP filtering (primary key: http method) //
  /////////////////////////////////////////////////////
  process_quick_http_filter(s, method);
  /////////////////////////////////////////////////////////////////////////
  // We must close this connection if client_connection_enabled == false //
  /////////////////////////////////////////////////////////////////////////
  if (!s->client_connection_allowed) {
    s->http_return_code_setter_name = "ip_allow";
    build_error_response(s, HTTPStatus::FORBIDDEN, "Access Denied", "access#denied");
    s->reverse_proxy = false;
    goto done;
  }
  /////////////////////////////////////////////////////////////////
  // Check if remap plugin set HTTP return code and return body  //
  /////////////////////////////////////////////////////////////////
  if (s->http_return_code != HTTPStatus::NONE) {
    build_error_response(s, s->http_return_code, nullptr, nullptr);
    s->reverse_proxy = false;
    goto done;
  }

  ///////////////////////////////////////////////////////////////
  // if no mapping was found, handle the cases where:          //
  //                                                           //
  // (1) reverse proxy is on, and no URL host (server request) //
  // (2) no mappings are found, but mappings strictly required //
  ///////////////////////////////////////////////////////////////

  if (!s->url_remap_success) {
    /**
     * It's better to test redirect rules just after url_remap failed
     * Or those successfully remapped rules might be redirected
     **/
    if (handleIfRedirect(s)) {
      TxnDbg(dbg_ctl_http_trans, "END HttpTransact::RemapRequest");
      TRANSACT_RETURN(StateMachineAction_t::INTERNAL_CACHE_NOOP, nullptr);
    }

    if (!s->http_config_param->url_remap_required && !incoming_request->is_target_in_url()) {
      s->hdr_info.client_request.set_url_target_from_host_field();
    }

    /////////////////////////////////////////////////////////
    // check for: (1) reverse proxy is on, and no URL host //
    /////////////////////////////////////////////////////////
    if (s->http_config_param->reverse_proxy_enabled && !s->client_info.is_transparent && !incoming_request->is_target_in_url()) {
      /////////////////////////////////////////////////////////
      // the url mapping failed, reverse proxy was enabled,
      // and the request contains no host:
      //
      // * if there is an explanatory redirect, send there.
      // * if there was no host, send "no host" error.
      // * if there was a host, say "not found".
      /////////////////////////////////////////////////////////

      char *redirect_url     = s->http_config_param->reverse_proxy_no_host_redirect;
      int   redirect_url_len = s->http_config_param->reverse_proxy_no_host_redirect_len;

      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
      if (redirect_url) { /* there is a redirect url */
        build_error_response(s, HTTPStatus::MOVED_TEMPORARILY, "Redirect For Explanation", "request#no_host");
        s->hdr_info.client_response.value_set(
          static_cast<std::string_view>(MIME_FIELD_LOCATION),
          std::string_view{redirect_url, static_cast<std::string_view::size_type>(redirect_url_len)});
        // socket when there is no host. Need to handle DNS failure elsewhere.
      } else if (host.empty()) { /* no host */
        build_error_response(s, HTTPStatus::BAD_REQUEST, "Host Header Required", "request#no_host");
        s->squid_codes.log_code = SquidLogCode::ERR_INVALID_URL;
      } else {
        build_error_response(s, HTTPStatus::NOT_FOUND, "Not Found on Accelerator", "urlrouting#no_mapping");
        s->squid_codes.log_code = SquidLogCode::ERR_INVALID_URL;
      }
      s->reverse_proxy = false;
      goto done;
    } else if (s->http_config_param->url_remap_required) {
      ///////////////////////////////////////////////////////
      // the url mapping failed, but mappings are strictly //
      // required so return an error message.              //
      ///////////////////////////////////////////////////////
      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
      build_error_response(s, HTTPStatus::NOT_FOUND, "Not Found", "urlrouting#no_mapping");
      s->squid_codes.log_code = SquidLogCode::ERR_INVALID_URL;

      s->reverse_proxy = false;
      goto done;
    }
  } else {
    if (s->http_config_param->reverse_proxy_enabled) {
      s->req_flavor = HttpRequestFlavor_t::REVPROXY;
    }
  }
  s->reverse_proxy = true;
  s->server_info.is_transparent =
    s->state_machine->get_ua_txn() ? s->state_machine->get_ua_txn()->is_outbound_transparent() : false;

done:
  // We now set the active-timeout again, since it might have been changed as part of the remap rules.
  if (s->state_machine->get_ua_txn()) {
    s->state_machine->get_ua_txn()->set_active_timeout(HRTIME_SECONDS(s->txn_conf->transaction_active_timeout_in));
  }

  if (dbg_ctl_http_chdr_describe.on() || dbg_ctl_http_trans.on() || dbg_ctl_url_rewrite.on()) {
    TxnDbg(dbg_ctl_http_trans, "After Remapping:");
    obj_describe(s->hdr_info.client_request.m_http, true);
  }

  // If the client failed ACLs, send error response
  // This extra condition was added to separate it from the logic below that might allow
  // requests that use some types of plugins as that code was allowing requests that didn't
  // pass ACL checks. ACL mismatches are also not counted as invalid client requests
  if (!s->client_connection_allowed) {
    TxnDbg(dbg_ctl_http_trans, "END HttpTransact::EndRemapRequest: connection not allowed");
    TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
  }

  /*
    if s->reverse_proxy == false, we can assume remapping failed in some way
      -however-
    If an API setup a tunnel to fake the origin or proxy's response we will
    continue to handle the request (as this was likely the plugin author's intent)

    otherwise, 502/404 the request right now. /eric
  */
  if (!s->reverse_proxy && s->state_machine->plugin_tunnel_type == HttpPluginTunnel_t::NONE) {
    TxnDbg(dbg_ctl_http_trans, "END HttpTransact::EndRemapRequest");
    Metrics::Counter::increment(http_rsb.invalid_client_requests);
    TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
  } else {
    s->hdr_info.client_response.destroy(); // release the underlying memory.
    s->hdr_info.client_response.clear();   // clear the pointers.
    TxnDbg(dbg_ctl_http_trans, "END HttpTransact::EndRemapRequest");

    if (s->is_upgrade_request && s->post_remap_upgrade_return_point) {
      TRANSACT_RETURN(StateMachineAction_t::API_POST_REMAP, s->post_remap_upgrade_return_point);
    }

    TRANSACT_RETURN(StateMachineAction_t::API_POST_REMAP, HttpTransact::HandleRequest);
  }

  ink_assert(!"not reached");
}

bool
HttpTransact::handle_upgrade_request(State *s)
{
  HTTPHdr &request = s->hdr_info.client_request;
  s->method        = request.method_get_wksidx();

  // Quickest way to determine that this is defintely not an upgrade.
  /* RFC 6455 The method of the request MUST be GET, and the HTTP version MUST
        be at least 1.1. */
  if (!s->hdr_info.client_request.presence(MIME_PRESENCE_UPGRADE) ||
      !s->hdr_info.client_request.presence(MIME_PRESENCE_CONNECTION) || s->method != HTTP_WKSIDX_GET ||
      s->hdr_info.client_request.version_get() < HTTP_1_1) {
    return false;
  }

  MIMEField *upgrade_hdr    = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_UPGRADE));
  MIMEField *connection_hdr = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_CONNECTION));

  StrList          connection_hdr_vals;
  std::string_view upgrade_hdr_val;

  if (!upgrade_hdr || !connection_hdr || connection_hdr->value_get_comma_list(&connection_hdr_vals) == 0 ||
      (upgrade_hdr_val = upgrade_hdr->value_get()).data() == nullptr) {
    TxnDbg(dbg_ctl_http_trans_upgrade, "Transaction wasn't a valid upgrade request, proceeding as a normal HTTP request.");
    return false;
  }

  /*
   * In order for this request to be treated as a normal upgrade request we must have a Connection: Upgrade header
   * and a Upgrade: header, with a non-empty value, otherwise we just assume it's not an Upgrade Request, after
   * we've verified that, we will try to match this upgrade to a known upgrade type such as Websockets.
   */
  bool connection_contains_upgrade = false;
  // Next, let's validate that the Connection header contains an Upgrade key
  for (int i = 0; i < connection_hdr_vals.count; ++i) {
    Str *val = connection_hdr_vals.get_idx(i);
    if (ptr_len_casecmp(val->str, val->len, MIME_FIELD_UPGRADE.c_str(), static_cast<int>(MIME_FIELD_UPGRADE.length())) == 0) {
      connection_contains_upgrade = true;
      break;
    }
  }

  if (!connection_contains_upgrade) {
    TxnDbg(dbg_ctl_http_trans_upgrade,
           "Transaction wasn't a valid upgrade request, proceeding as a normal HTTP request, missing Connection upgrade header.");
    return false;
  }

  // Mark this request as an upgrade request.
  s->is_upgrade_request = true;

  /*
     RFC 6455
     The request MUST contain an |Upgrade| header field whose value
        MUST include the "websocket" keyword.
     The request MUST contain a |Connection| header field whose value
        MUST include the "Upgrade" token. // Checked Above
     The request MUST include a header field with the name
        |Sec-WebSocket-Key|.
     The request MUST include a header field with the name
        |Sec-WebSocket-Version|.  The value of this header field MUST be
        13.
   */
  if (hdrtoken_tokenize(upgrade_hdr_val.data(), upgrade_hdr_val.length(), &s->upgrade_token_wks) >= 0) {
    if (s->upgrade_token_wks == MIME_VALUE_WEBSOCKET.c_str()) {
      MIMEField *sec_websocket_key =
        s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_SEC_WEBSOCKET_KEY));
      MIMEField *sec_websocket_ver =
        s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_SEC_WEBSOCKET_VERSION));

      if (sec_websocket_key && sec_websocket_ver && sec_websocket_ver->value_get_int() == 13) {
        TxnDbg(dbg_ctl_http_trans_upgrade, "Transaction wants upgrade to websockets");
        handle_websocket_upgrade_pre_remap(s);
        return true;
      } else {
        TxnDbg(dbg_ctl_http_trans_upgrade, "Unable to upgrade connection to websockets, invalid headers (RFC 6455).");
      }
    } else if (s->upgrade_token_wks == MIME_VALUE_H2C.c_str()) {
      // We need to recognize h2c to not handle it as an error.
      // We just ignore the Upgrade header and respond to the request as though the Upgrade header field were absent.
      s->is_upgrade_request = false;
      return false;
    }
  } else {
    TxnDbg(dbg_ctl_http_trans_upgrade, "Transaction requested upgrade for unknown protocol: %s", upgrade_hdr_val.data());
  }

  build_error_response(s, HTTPStatus::BAD_REQUEST, "Invalid Upgrade Request", "request#syntax_error");

  // we want our modify_request method to just return while we fail out from here.
  // this seems like the preferred option because the user wanted to do an upgrade but sent a bad protocol.
  TRANSACT_RETURN_VAL(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr, true);
}

void
HttpTransact::handle_websocket_upgrade_pre_remap(State *s)
{
  TxnDbg(dbg_ctl_http_trans_websocket_upgrade_pre_remap, "Prepping transaction before remap.");

  /*
   * We will use this opportunity to set everything up so that during the remap stage we can deal with
   * ws:// and wss:// remap rules, and then we will take over again post remap.
   */
  s->is_websocket                    = true;
  s->post_remap_upgrade_return_point = HttpTransact::handle_websocket_upgrade_post_remap;

  /* let's modify the url scheme to be wss or ws, so remapping will happen as expected */
  URL *url = s->hdr_info.client_request.url_get();
  if (url->scheme_get_wksidx() == URL_WKSIDX_HTTP) {
    TxnDbg(dbg_ctl_http_trans_websocket_upgrade_pre_remap, "Changing scheme to WS for remapping.");
    url->scheme_set(std::string_view{URL_SCHEME_WS});
  } else if (url->scheme_get_wksidx() == URL_WKSIDX_HTTPS) {
    TxnDbg(dbg_ctl_http_trans_websocket_upgrade_pre_remap, "Changing scheme to WSS for remapping.");
    url->scheme_set(std::string_view{URL_SCHEME_WSS});
  } else {
    TxnDbg(dbg_ctl_http_trans_websocket_upgrade_pre_remap, "Invalid scheme for websocket upgrade");
    build_error_response(s, HTTPStatus::BAD_REQUEST, "Invalid Upgrade Request", "request#syntax_error");
    TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
  }

  TRANSACT_RETURN(StateMachineAction_t::API_PRE_REMAP, HttpTransact::PerformRemap);
}

void
HttpTransact::handle_websocket_upgrade_post_remap(State *s)
{
  TxnDbg(dbg_ctl_http_trans_websocket_upgrade_post_remap, "Remap is complete, start websocket upgrade");

  TRANSACT_RETURN(StateMachineAction_t::API_POST_REMAP, HttpTransact::handle_websocket_connection);
}

void
HttpTransact::handle_websocket_connection(State *s)
{
  TxnDbg(dbg_ctl_http_trans_websocket, "START handle_websocket_connection");

  HandleRequest(s);
}

static bool
mimefield_value_equal(MIMEField *field, const char *value, const int value_len)
{
  auto field_value{field->value_get()};

  if (field_value.data() != nullptr && static_cast<int>(field_value.length()) == value_len) {
    return !strncasecmp(field_value.data(), value, value_len);
  }

  return false;
}

void
HttpTransact::ModifyRequest(State *s)
{
  int              scheme;
  HTTPHdr         &request      = s->hdr_info.client_request;
  static const int PORT_PADDING = 8;

  TxnDbg(dbg_ctl_http_trans, "START HttpTransact::ModifyRequest");

  // Initialize the state vars necessary to sending error responses
  bootstrap_state_variables_from_request(s, &request);

  ////////////////////////////////////////////////
  // If there is no scheme, default to http      //
  ////////////////////////////////////////////////
  URL *url = request.url_get();

  s->orig_scheme = (scheme = url->scheme_get_wksidx());

  s->method = request.method_get_wksidx();
  if (scheme < 0 && s->method != HTTP_WKSIDX_CONNECT) {
    if (s->client_info.port_attribute == HttpProxyPort::TRANSPORT_SSL) {
      url->scheme_set(std::string_view{URL_SCHEME_HTTPS});
      s->orig_scheme = URL_WKSIDX_HTTPS;
    } else {
      url->scheme_set(std::string_view{URL_SCHEME_HTTP});
      s->orig_scheme = URL_WKSIDX_HTTP;
    }
  }

  if (s->method == HTTP_WKSIDX_CONNECT && !request.is_port_in_header()) {
    url->port_set(80);
  }

  // Ugly - this must come after the call to url->scheme_set or
  // it can't get the scheme properly and the wrong data is cached.
  // The solution should be to move the scheme detecting logic in to
  // the header class, rather than doing it in a random bit of
  // external code.
  auto buf{request.host_get()};
  auto hostname_len{static_cast<int>(buf.length())};
  if (!request.is_target_in_url()) {
    s->hdr_info.client_req_is_server_style = true;
  }
  // Copy out buf to a hostname just in case its heap header memory is freed during coalescing
  // due to later HdrHeap operations
  char *hostname = static_cast<char *>(alloca(hostname_len + PORT_PADDING));
  memcpy(hostname, buf.data(), hostname_len);

  // Make clang analyzer happy. hostname is non-null iff request.is_target_in_url().
  ink_assert(hostname || s->hdr_info.client_req_is_server_style);

  // If the incoming request is proxy-style make sure the Host: header
  // matches the incoming request URL. The exception is if we have
  // Max-Forwards set to 0 in the request
  int max_forwards = -1; // -1 is a valid value meaning that it didn't find the header
  if (request.presence(MIME_PRESENCE_MAX_FORWARDS)) {
    max_forwards = request.get_max_forwards();
  }

  if ((max_forwards != 0) && !s->hdr_info.client_req_is_server_style && s->method != HTTP_WKSIDX_CONNECT) {
    MIMEField *host_field = request.field_find(static_cast<std::string_view>(MIME_FIELD_HOST));
    in_port_t  port       = url->port_get_raw();

    // Form the host:port string if not a default port (e.g. 80)
    // We allocated extra space for the port above
    if (port > 0) {
      hostname_len += snprintf(hostname + hostname_len, PORT_PADDING, ":%u", port);
    }

    // No host_field means not equal to host and will need to be set, so create it now.
    if (!host_field) {
      host_field = request.field_create(static_cast<std::string_view>(MIME_FIELD_HOST));
      request.field_attach(host_field);
    }

    if (mimefield_value_equal(host_field, hostname, hostname_len) == false) {
      request.field_value_set(host_field, std::string_view{hostname, static_cast<std::string_view::size_type>(hostname_len)});
      request.mark_target_dirty();
    }
  }

  TxnDbg(dbg_ctl_http_trans, "END HttpTransact::ModifyRequest");

  TRANSACT_RETURN(StateMachineAction_t::API_READ_REQUEST_HDR, HttpTransact::StartRemapRequest);
}

// This function is supposed to figure out if this transaction is
// susceptible to a redirection as specified by remap.config
bool
HttpTransact::handleIfRedirect(State *s)
{
  mapping_type answer;
  URL          redirect_url;

  answer = request_url_remap_redirect(&s->hdr_info.client_request, &redirect_url, s->state_machine->m_remap);
  if ((answer == mapping_type::PERMANENT_REDIRECT) || (answer == mapping_type::TEMPORARY_REDIRECT)) {
    s->remap_redirect = redirect_url.string_get_ref(nullptr);
    if (answer == mapping_type::TEMPORARY_REDIRECT) {
      if ((s->client_info).http_version == HTTP_1_1) {
        build_error_response(s, HTTPStatus::TEMPORARY_REDIRECT, "Redirect", "redirect#moved_temporarily");
      } else {
        build_error_response(s, HTTPStatus::MOVED_TEMPORARILY, "Redirect", "redirect#moved_temporarily");
      }
    } else {
      build_error_response(s, HTTPStatus::MOVED_PERMANENTLY, "Redirect", "redirect#moved_permanently");
    }
    s->remap_redirect = nullptr;
    redirect_url.destroy();
    return true;
  }

  return false;
}

void
HttpTransact::HandleRequest(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "START HttpTransact::HandleRequest");

  if (!s->state_machine->is_waiting_for_full_body && !s->state_machine->is_buffering_request_body) {
    ink_assert(!s->hdr_info.server_request.valid());

    Metrics::Counter::increment(http_rsb.incoming_requests);

    if (s->client_info.port_attribute == HttpProxyPort::TRANSPORT_SSL) {
      Metrics::Counter::increment(http_rsb.https_incoming_requests);
    }

    ///////////////////////////////////////////////
    // if request is bad, return error response  //
    ///////////////////////////////////////////////

    if (!(is_request_valid(s, &s->hdr_info.client_request))) {
      Metrics::Counter::increment(http_rsb.invalid_client_requests);
      TxnDbg(dbg_ctl_http_seq, "request invalid.");
      s->next_action = StateMachineAction_t::SEND_ERROR_CACHE_NOOP;
      //  s->next_action = HttpTransact::PROXY_INTERNAL_CACHE_NOOP;
      return;
    }
    TxnDbg(dbg_ctl_http_seq, "request valid.");

    if (dbg_ctl_http_chdr_describe.on()) {
      obj_describe(s->hdr_info.client_request.m_http, true);
    }
    // at this point we are guaranteed that the request is good and acceptable.
    // initialize some state variables from the request (client version,
    // client keep-alive, cache action, etc.
    initialize_state_variables_from_request(s, &s->hdr_info.client_request);
    // The following chunk of code will limit the maximum number of websocket connections (TS-3659)
    if (s->is_upgrade_request && s->is_websocket && s->http_config_param->max_websocket_connections >= 0) {
      if (Metrics::Gauge::load(http_rsb.websocket_current_active_client_connections) >=
          s->http_config_param->max_websocket_connections) {
        s->is_websocket = false; // unset to avoid screwing up stats.
        TxnDbg(dbg_ctl_http_trans, "Rejecting websocket connection because the limit has been exceeded");
        bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
        build_error_response(s, HTTPStatus::SERVICE_UNAVAILABLE, "WebSocket Connection Limit Exceeded", nullptr);
        TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
      }
    }

    // The following code is configurable to allow a user to control the max post size (TS-3631)
    if (s->http_config_param->max_post_size > 0 && s->hdr_info.request_content_length > 0 &&
        s->hdr_info.request_content_length > s->http_config_param->max_post_size) {
      TxnDbg(dbg_ctl_http_trans, "Max post size %" PRId64 " Client tried to post a body that was too large.",
             s->http_config_param->max_post_size);
      Metrics::Counter::increment(http_rsb.post_body_too_large);
      bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
      build_error_response(s, HTTPStatus::REQUEST_ENTITY_TOO_LARGE, "Request Entity Too Large", "request#entity_too_large");
      s->squid_codes.log_code = SquidLogCode::ERR_POST_ENTITY_TOO_LARGE;
      TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
    }

    // The following chunk of code allows you to disallow post w/ expect 100-continue (TS-3459)
    if (s->hdr_info.request_content_length && s->http_config_param->disallow_post_100_continue) {
      MIMEField *expect = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_EXPECT));

      if (expect != nullptr) {
        auto expect_hdr_val{expect->value_get()};
        if (strcasecmp(expect_hdr_val, static_cast<std::string_view>(HTTP_VALUE_100_CONTINUE)) == 0) {
          // Let's error out this request.
          TxnDbg(dbg_ctl_http_trans, "Client sent a post expect: 100-continue, sending 405.");
          Metrics::Counter::increment(http_rsb.disallowed_post_100_continue);
          build_error_response(s, HTTPStatus::METHOD_NOT_ALLOWED, "Method Not Allowed", "request#method_unsupported");
          TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
        }
      }
    }
    if (s->txn_conf->request_buffer_enabled && s->http_config_param->post_copy_size > 0 &&
        s->state_machine->get_ua_txn()->has_request_body(s->hdr_info.request_content_length,
                                                         s->client_info.transfer_encoding == TransferEncoding_t::CHUNKED)) {
      TRANSACT_RETURN(StateMachineAction_t::WAIT_FOR_FULL_BODY, nullptr);
    }
  }

  // Cache lookup or not will be decided later at DecideCacheLookup().
  // Before it's decided to do a cache lookup,
  // assume no cache lookup and using proxy (not tunneling)
  s->cache_info.action = CacheAction_t::NO_ACTION;
  s->current.mode      = ProxyMode_t::GENERIC;

  // initialize the cache_control structure read from cache.config
  update_cache_control_information_from_config(s);

  // We still need to decide whether or not to do a cache lookup since
  // the scheduled update code depends on this info.
  if (is_request_cache_lookupable(s)) {
    s->cache_info.action = CacheAction_t::LOOKUP;
  }

  if (s->state_machine->plugin_tunnel_type == HttpPluginTunnel_t::AS_INTERCEPT) {
    setup_plugin_request_intercept(s);
    return;
  }

  // if ip in url or cop test page, not do srv lookup.
  if (s->txn_conf->srv_enabled) {
    s->my_txn_conf().srv_enabled = !s->server_info.name_addr.is_valid();
  }

  // if the request is a trace or options request, decrement the
  // max-forwards value. if the incoming max-forwards value was 0,
  // then we have to return a response to the client with the
  // appropriate action for trace/option. in this case this routine
  // is responsible for building the response.
  if (handle_trace_and_options_requests(s, &s->hdr_info.client_request)) {
    TRANSACT_RETURN(StateMachineAction_t::INTERNAL_CACHE_NOOP, nullptr);
  }

  if (s->txn_conf->no_dns_forward_to_parent && s->scheme != URL_WKSIDX_HTTPS && strcmp(s->server_info.name, "127.0.0.1") != 0) {
    // for HTTPS requests, we must go directly to the
    // origin server. Ignore the no_dns_just_forward_to_parent setting.
    // we need to see if the hostname is an
    //   ip address since the parent selection code result
    //   could change as a result of this ip address
    if (s->server_info.name_addr.is_valid()) {
      s->server_info.name_addr.copy_to(&s->request_data.dest_ip.sa);
    }

    if (parentExists(s)) {
      // If the proxy is behind and firewall and there is no
      //  DNS service available, we just want to forward the request
      //  the parent proxy.  In this case, we never find out the
      //  origin server's ip.  So just skip past OSDNS
      ats_ip_invalidate(&s->server_info.dst_addr);
      StartAccessControl(s);
      return;
    } else if (s->http_config_param->no_origin_server_dns) {
      build_error_response(s, HTTPStatus::BAD_GATEWAY, "Next Hop Connection Failed", "connect#failed_connect");

      TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
    }
  }

  // Added to skip the dns if the document is in the cache.
  // DNS is requested before cache lookup only if there are rules in cache.config , parent.config or
  // if the newly added variable doc_in_cache_skip_dns is not enabled
  if (s->server_info.name_addr.is_valid() && (!s->state_machine->enable_redirection || !s->redirect_info.redirect_in_process) &&
      s->parent_params->parent_table->hostMatch) {
    s->force_dns = true;
  }
  /* A redirect means we need to check some things again.
     If the cache is enabled then we need to check the new (redirected) request against the cache.
     If not, then we need to at least do DNS again to guarantee we are using the correct IP address
     (if the host changed). Note DNS comes after cache lookup so in both cases we do the DNS.
  */
  if (s->redirect_info.redirect_in_process && s->state_machine->enable_redirection) {
    if (s->txn_conf->cache_http) {
      TRANSACT_RETURN(StateMachineAction_t::CACHE_LOOKUP, nullptr);
    } else {
      return CallOSDNSLookup(s);
    }
  }

  if (s->force_dns) {
    return CallOSDNSLookup(s);
  } else {
    // After the requested is properly handled No need of requesting the DNS directly check the ACLs
    // if the request is authorized
    StartAccessControl(s);
  }
}

void
HttpTransact::HandleRequestBufferDone(State *s)
{
  TRANSACT_RETURN(StateMachineAction_t::REQUEST_BUFFER_READ_COMPLETE, HttpTransact::HandleRequest);
}

void
HttpTransact::setup_plugin_request_intercept(State *s)
{
  ink_assert(s->state_machine->plugin_tunnel != nullptr);

  // Plugin is intercepting the request which means
  //  that we don't do dns, cache read or cache write
  //
  // We just want to write the request straight to the plugin
  if (s->cache_info.action != HttpTransact::CacheAction_t::NO_ACTION) {
    s->cache_info.action = HttpTransact::CacheAction_t::NO_ACTION;
    s->current.mode      = ProxyMode_t::TUNNELLING;
    Metrics::Counter::increment(http_rsb.tunnels);
  }
  // Regardless of the protocol we're gatewaying to
  //   we see the scheme as http
  s->scheme = s->next_hop_scheme = URL_WKSIDX_HTTP;

  // Set up a "fake" server entry
  update_current_info(&s->current, &s->server_info, ResolveInfo::ORIGIN_SERVER, true);

  // Also "fake" the info we'd normally get from
  //   hostDB
  s->server_info.http_version = HTTP_1_0;
  s->server_info.keep_alive   = HTTPKeepAlive::NO_KEEPALIVE;
  s->server_info.http_version = HTTP_1_0;
  s->server_info.dst_addr.setToAnyAddr(AF_INET); // must set an address or we can't set the port.
  s->server_info.dst_addr.network_order_port() = htons(s->hdr_info.client_request.port_get()); // this is the info that matters.

  // Build the request to the server
  build_request(s, &s->hdr_info.client_request, &s->hdr_info.server_request, s->client_info.http_version);

  // We don't do keep alive over these impersonated
  //  NetVCs so nuke the connection header
  s->hdr_info.server_request.field_delete(static_cast<std::string_view>(MIME_FIELD_CONNECTION));

  TRANSACT_RETURN(StateMachineAction_t::ORIGIN_SERVER_OPEN, nullptr);
}

////////////////////////////////////////////////////////////////////////
// void HttpTransact::HandleApiErrorJump(State* s)
//
//   Called after an API function indicates it wished to send an
//     error to the user agent
////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleApiErrorJump(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "Entering HttpTransact::HandleApiErrorJump");

  // since the READ_REQUEST_HDR_HOOK is processed before
  //   we examine the request, returning TS_EVENT_ERROR will cause
  //   the protocol in the via string to be "?"  Set it here
  //   since we know it has to be http
  // For CONNECT method, next_hop_scheme is NULL
  if (s->next_hop_scheme < 0) {
    s->next_hop_scheme = URL_WKSIDX_HTTP;
  }
  // The client response may not be empty in the
  // case the txn was reenabled in error by a plugin from hook SEND_RESPONSE_HDR.
  // build_response doesn't clean the header. So clean it up before.
  // Do fields_clear() instead of clear() to prevent memory leak
  if (s->hdr_info.client_response.valid()) {
    s->hdr_info.client_response.fields_clear();
  }

  // Set the source to internal so chunking is handled correctly
  s->source = Source_t::INTERNAL;

  /**
    The API indicated an error. Lets use a >=400 error from the state (if one's set) or fallback to a
    generic HTTP/1.X 500 INKApi Error
  **/
  if (s->http_return_code != HTTPStatus::NONE && s->http_return_code >= HTTPStatus::BAD_REQUEST) {
    const char *reason = http_hdr_reason_lookup(s->http_return_code);
    build_response(s, &s->hdr_info.client_response, s->client_info.http_version, s->http_return_code, reason ? reason : "Error");
  } else {
    build_response(s, &s->hdr_info.client_response, s->client_info.http_version, HTTPStatus::INTERNAL_SERVER_ERROR, "INKApi Error");
  }

  TRANSACT_RETURN(StateMachineAction_t::INTERNAL_CACHE_NOOP, nullptr);
  return;
}

// PPDNSLookupAPICall does an API callout if a plugin set the response_action,
// then calls PPDNSLookup.
// This is to preserve plugin hook calling behavior pre-9, which didn't call
// the TS_HTTP_OS_DNS_HOOK on PPDNSLookup.
// Since response_action is new in 9, only new plugins intentionally setting
// it will have the new behavior of TS_HTTP_OS_DNS_HOOK firing on PPDNSLookup.
void
HttpTransact::PPDNSLookupAPICall(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "response_action.handled %d", s->response_action.handled);
  if (!s->response_action.handled) {
    TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, PPDNSLookup);
  } else {
    TRANSACT_RETURN(StateMachineAction_t::API_OS_DNS, PPDNSLookup);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : PPDNSLookup
// Description: called after DNS lookup of parent proxy name
//
// Details    :
//
// the configuration information gave us the name of the parent proxy
// to send the request to. this function is called after the dns lookup
// for that name. it may fail, in which case we look for the next parent
// proxy to try and if none exist, then go to the origin server.
// if the lookup succeeds, we open a connection to the parent proxy.
//
//
// Possible Next States From Here:

// - HttpTransact::StateMachineAction_t::DNS_LOOKUP;
// - HttpTransact::ORIGIN_SERVER_RAW_OPEN;
// - HttpTransact::ORIGIN_SERVER_OPEN;
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::PPDNSLookup(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "Entering HttpTransact::PPDNSLookup");

  ink_assert(s->dns_info.looking_up == ResolveInfo::PARENT_PROXY);
  if (!s->dns_info.resolved_p) {
    // Mark parent as down due to resolving failure
    markParentDown(s);
    // DNS lookup of parent failed, find next parent or o.s.
    if (find_server_and_update_current_info(s) == ResolveInfo::HOST_NONE) {
      if (is_cache_hit(s->cache_lookup_result) && is_stale_cache_response_returnable(s)) {
        s->source = Source_t::CACHE;
        TxnDbg(dbg_ctl_http_trans, "All parents are down, serving stale doc to client");
        build_response_from_cache(s, HTTPWarningCode::REVALIDATION_FAILED);
        return;
      }
      ink_assert(s->current.request_to == ResolveInfo::HOST_NONE);
      handle_parent_down(s);
      return;
    }

    if (!s->current.server->dst_addr.isValid()) {
      if (s->current.request_to == ResolveInfo::PARENT_PROXY) {
        TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, PPDNSLookupAPICall);
      } else if (s->parent_result.result == ParentResultType::DIRECT && s->txn_conf->no_dns_forward_to_parent != 1) {
        // We ran out of parents but parent configuration allows us to go to Origin Server directly
        CallOSDNSLookup(s);
        return;
      } else {
        // We could be out of parents here if all the parents failed DNS lookup
        ink_assert(s->current.request_to == ResolveInfo::HOST_NONE);
        handle_parent_down(s);
      }
      return;
    }
  } else {
    // lookup succeeded, open connection to p.p.
    ats_ip_copy(&s->parent_info.dst_addr, s->dns_info.addr);
    s->parent_info.dst_addr.network_order_port() = htons(s->parent_result.port);
    get_ka_info_from_host_db(s, &s->parent_info, &s->client_info, s->dns_info.active);

    ip_port_text_buffer addrbuf;
    TxnDbg(dbg_ctl_http_trans, "DNS lookup for successful IP: %s",
           ats_ip_nptop(&s->parent_info.dst_addr.sa, addrbuf, sizeof(addrbuf)));
  }

  // Since this function can be called several times while retrying
  //  parents, check to see if we've already built our request
  if (!s->hdr_info.server_request.valid()) {
    build_request(s, &s->hdr_info.client_request, &s->hdr_info.server_request, s->current.server->http_version);
    // Take care of deferred (issue revalidate) work in building
    //   the request
    if (s->pending_work != nullptr) {
      ink_assert(s->pending_work == issue_revalidate);
      (*s->pending_work)(s);
      s->pending_work = nullptr;
    }
  }
  // what kind of a connection (raw, simple)
  s->next_action = how_to_open_connection(s);
}

///////////////////////////////////////////////////////////////////////////////
// Name       : OSDNSLookup
// Description: called after the DNS lookup of origin server name
//
// Details    :
//
// normally called after Start. may be called more than once, however,
// if the dns lookup fails. this may be because
// it was not possible to resolve the name after several attempts.
//
// the next action depends. since this function is normally called after
// a request has come in, which is valid and does not require an immediate
// response, the next action may just be to open a connection to the
// origin server, or a parent proxy, or the next action may be to do a
// cache lookup, or in the event of an error, the next action may be to
// send a response back to the client.
//
//
// Possible Next States From Here:
// - HttpTransact::PROXY_INTERNAL_CACHE_NOOP;
// - HttpTransact::CACHE_LOOKUP;
// - HttpTransact::StateMachineAction_t::DNS_LOOKUP;
// - HttpTransact::ORIGIN_SERVER_RAW_OPEN;
// - HttpTransact::ORIGIN_SERVER_OPEN;
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::OSDNSLookup(State *s)
{
  ink_assert(s->dns_info.looking_up == ResolveInfo::UpstreamResolveStyle::ORIGIN_SERVER);

  TxnDbg(dbg_ctl_http_trans, "Entering HttpTransact::OSDNSLookup");

  if (!s->dns_info.resolved_p) {
    if (ResolveInfo::OS_Addr::TRY_HOSTDB == s->dns_info.os_addr_style) {
      /* Transparent case: We tried to connect to client target address, failed and tried to use a different addr
       * but that failed to resolve therefore keep on with the CTA.
       */
      s->dns_info.addr.assign(s->state_machine->get_ua_txn()->get_netvc()->get_local_addr()); // fetch CTA
      s->dns_info.resolved_p    = true;
      s->dns_info.os_addr_style = ResolveInfo::OS_Addr::USE_CLIENT;
      TxnDbg(dbg_ctl_http_seq, "DNS lookup unsuccessful, using client target address");
    } else {
      TxnDbg(dbg_ctl_http_seq, "DNS Lookup unsuccessful");
      char const *log_msg;

      // Even with unsuccessful DNS lookup, return stale object from cache if applicable
      if (is_cache_hit(s->cache_lookup_result) && is_stale_cache_response_returnable(s)) {
        s->source = Source_t::CACHE;
        TxnDbg(dbg_ctl_http_trans, "[hscno] serving stale doc to client");
        build_response_from_cache(s, HTTPWarningCode::REVALIDATION_FAILED);
        return;
      }
      // output the DNS failure error message
      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
      if (!s->dns_info.record || s->dns_info.record->is_failed()) {
        // Set to internal server error so later logging will pick up SquidLogCode::ERR_DNS_FAIL
        build_error_response(s, HTTPStatus::INTERNAL_SERVER_ERROR, "Cannot find server.", Dns_error_body);
        log_msg = "looking up";
      } else {
        build_error_response(s, HTTPStatus::INTERNAL_SERVER_ERROR, "No valid server.", "connect#all_down");
        log_msg = "no valid server";
      }
      char *url_str = s->hdr_info.client_request.url_string_get(&s->arena, nullptr);
      swoc::bwprint(error_bw_buffer, "DNS Error: {} {}", log_msg, swoc::bwf::FirstOf(url_str, "<none>"));
      Log::error("%s", error_bw_buffer.c_str());
      // s->cache_info.action = CacheAction_t::NO_ACTION;
      TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
    }
    return;
  }

  // The dns lookup succeeded
  ink_assert(s->dns_info.resolved_p);
  TxnDbg(dbg_ctl_http_seq, "DNS Lookup successful");

  // It's never valid to connect *to* INADDR_ANY, so let's reject the request now.
  if (ats_is_ip_any(s->dns_info.addr)) {
    TxnDbg(dbg_ctl_http_trans, "[OSDNSLookup] Invalid request IP: INADDR_ANY");
    build_error_response(s, HTTPStatus::BAD_REQUEST, "Bad Destination Address", "request#syntax_error");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
  }

  // For the transparent case, nail down the kind of address we are really using
  if (ResolveInfo::OS_Addr::TRY_HOSTDB == s->dns_info.os_addr_style) {
    // We've backed off from a client supplied address and found some
    // HostDB addresses. We use those if they're different from the CTA.
    // In all cases we now commit to client or HostDB for our source.
    if (s->dns_info.set_active(&s->current.server->dst_addr.sa) && s->dns_info.select_next_rr()) {
      s->dns_info.os_addr_style = ResolveInfo::OS_Addr::USE_HOSTDB;
    } else {
      // nothing else there, continue with CTA.
      s->dns_info.set_active(nullptr);
      s->dns_info.set_upstream_address(&s->current.server->dst_addr.sa);
      s->dns_info.os_addr_style = ResolveInfo::OS_Addr::USE_CLIENT;
    }
  }

  s->server_info.dst_addr.assign(s->dns_info.addr);
  // If the SRV response has a port number, we should honor it. Otherwise we do the port defined in remap
  if (s->dns_info.resolved_p && s->dns_info.srv_port) {
    s->server_info.dst_addr.network_order_port() = htons(s->dns_info.srv_port);
  } else if (s->dns_info.os_addr_style == ResolveInfo::OS_Addr::USE_API && 0 != ats_ip_port_cast(s->dns_info.addr)) {
    // Nothing - port set via API and already copied over.
  } else {
    s->server_info.dst_addr.network_order_port() = htons(s->hdr_info.client_request.port_get()); // now we can set the port.
  }
  ats_ip_copy(&s->request_data.dest_ip, &s->server_info.dst_addr);
  get_ka_info_from_host_db(s, &s->server_info, &s->client_info, s->dns_info.active);

  ip_port_text_buffer addrbuf;
  TxnDbg(dbg_ctl_http_trans, "DNS lookup for O.S. successful IP: %s",
         ats_ip_nptop(&s->server_info.dst_addr.sa, addrbuf, sizeof(addrbuf)));

  if (s->redirect_info.redirect_in_process) {
    // If dns lookup was not successful, the code below will handle the error.
    RedirectEnabled::Action action = RedirectEnabled::Action::INVALID;
    if (true == Machine::instance()->is_self(&s->dns_info.addr.sa)) {
      action = s->http_config_param->redirect_actions_self_action;
      TxnDbg(dbg_ctl_http_trans, "[OSDNSLookup] Self action - %d.", int(action));
    } else {
      ink_release_assert(s->http_config_param->redirect_actions_map != nullptr);
      auto &addrs = *(s->http_config_param->redirect_actions_map);
      auto  spot  = addrs.find(swoc::IPAddr(&s->dns_info.addr.sa));
      ink_release_assert(spot != addrs.end()); // Should always find an entry.
      action = std::get<1>(*spot);
      TxnDbg(dbg_ctl_http_trans, "[OSDNSLookup] Mapped action - %d for family %d.", int(action),
             int(s->dns_info.active->data.ip.family()));
    }

    if (action == RedirectEnabled::Action::FOLLOW) {
      TxnDbg(dbg_ctl_http_trans, "Invalid redirect address. Following");
    } else if (action == RedirectEnabled::Action::REJECT || s->hdr_info.server_response.valid() == false) {
      if (action == RedirectEnabled::Action::REJECT) {
        TxnDbg(dbg_ctl_http_trans, "Invalid redirect address. Rejecting.");
      } else {
        // Invalid server response, since we can't copy it we are going to reject
        TxnDbg(dbg_ctl_http_trans, "Invalid server response. Rejecting.");
        Error("Invalid server response. Rejecting. IP: %s", ats_ip_nptop(&s->server_info.dst_addr.sa, addrbuf, sizeof(addrbuf)));
      }
      build_error_response(s, HTTPStatus::FORBIDDEN, nullptr, "request#syntax_error");
      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
      TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
    } else {
      // Return this 3xx to the client as-is
      if (action == RedirectEnabled::Action::RETURN) {
        TxnDbg(dbg_ctl_http_trans, "Configured to return on invalid redirect address.");
      } else {
        TxnDbg(dbg_ctl_http_trans, "Invalid redirect address. Returning.");
      }
      build_response_copy(s, &s->hdr_info.server_response, &s->hdr_info.client_response, s->client_info.http_version);
      TRANSACT_RETURN(StateMachineAction_t::INTERNAL_CACHE_NOOP, nullptr);
    }
  }

  // everything succeeded with the DNS lookup so do an API callout
  //   that allows for filtering.  We'll do traffic_server internal
  //   filtering after API filtering

  // After StateMachineAction_t::DNS_LOOKUP, goto the saved action/state ORIGIN_SERVER_(RAW_)OPEN.
  // Should we skip the StartAccessControl()? why?

  if (ResolveInfo::OS_Addr::USE_CLIENT == s->dns_info.os_addr_style ||
      ResolveInfo::OS_Addr::USE_HOSTDB == s->dns_info.os_addr_style) {
    // we've come back after already trying the server to get a better address,
    // or we're locked on a plugin supplied address.
    // therefore no more backtracking - return to trying the server.
    TRANSACT_RETURN(how_to_open_connection(s), HttpTransact::HandleResponse);
  } else if (s->server_info.name_addr.is_valid() && s->parent_params->parent_table->hostMatch &&
             !s->txn_conf->no_dns_forward_to_parent) {
    // note, broken logic: ACC fudges the OR stmt to always be true,
    // 'AuthHttpAdapter' should do the rev-dns if needed, not here .
    TRANSACT_RETURN(StateMachineAction_t::DNS_REVERSE_LOOKUP, HttpTransact::StartAccessControl);
  } else {
    if (s->force_dns) {
      StartAccessControl(s); // If skip_dns is enabled and no ip based rules in cache.config and parent.config
      // Access Control is called after DNS response
    } else {
      if ((s->cache_info.action == CacheAction_t::NO_ACTION) &&
          (((s->hdr_info.client_request.presence(MIME_PRESENCE_RANGE) && !s->txn_conf->cache_range_write) ||
            s->range_setup == RangeSetup_t::NOT_SATISFIABLE || s->range_setup == RangeSetup_t::NOT_HANDLED))) {
        TRANSACT_RETURN(StateMachineAction_t::API_OS_DNS, HandleCacheOpenReadMiss);
      } else if (!s->txn_conf->cache_http || s->cache_lookup_result == HttpTransact::CacheLookupResult_t::SKIPPED) {
        TRANSACT_RETURN(StateMachineAction_t::API_OS_DNS, LookupSkipOpenServer);
        // DNS Lookup is done after LOOKUP Skipped  and after we get response
        // from the DNS we need to call LookupSkipOpenServer
      } else if (is_cache_hit(s->cache_lookup_result)) {
        // DNS lookup is done if the content is state need to call handle cache open read hit
        TRANSACT_RETURN(StateMachineAction_t::API_OS_DNS, HandleCacheOpenReadHit);
      } else if (s->cache_lookup_result == CacheLookupResult_t::MISS || s->cache_info.action == CacheAction_t::NO_ACTION) {
        TRANSACT_RETURN(StateMachineAction_t::API_OS_DNS, HandleCacheOpenReadMiss);
        // DNS lookup is done if the lookup failed and need to call Handle Cache Open Read Miss
      } else if (s->cache_info.action == CacheAction_t::PREPARE_TO_WRITE && s->txn_conf->cache_post_method == 1 &&
                 s->method == HTTP_WKSIDX_POST) {
        // By virtue of being here, we are intending to forward the request on
        // to the server. If we marked this as CacheAction_t::PREPARE_TO_WRITE and this
        // is a POST request whose response we intend to write, then we have to
        // proceed from here by calling the function that handles this as a
        // miss.
        TRANSACT_RETURN(StateMachineAction_t::API_OS_DNS, HandleCacheOpenReadMiss);
      } else {
        build_error_response(s, HTTPStatus::INTERNAL_SERVER_ERROR, "Invalid Cache Lookup result", "default");
        Log::error("HTTP: Invalid CACHE LOOKUP RESULT : %d", static_cast<int>(s->cache_lookup_result));
        TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
      }
    }
  }
}

void
HttpTransact::StartAccessControl(State *s)
{
  HandleRequestAuthorized(s);
}

void
HttpTransact::HandleRequestAuthorized(State *s)
{
  if (s->force_dns) {
    TRANSACT_RETURN(StateMachineAction_t::API_OS_DNS, HttpTransact::DecideCacheLookup);
  } else {
    HttpTransact::DecideCacheLookup(s);
  }
}

void
HttpTransact::DecideCacheLookup(State *s)
{
  // Check if a client request is lookupable.
  if (s->redirect_info.redirect_in_process) {
    // for redirect, we want to skip cache lookup and write into
    // the cache directly with the URL before the redirect
    s->cache_info.action = CacheAction_t::NO_ACTION;
    s->current.mode      = ProxyMode_t::GENERIC;
  } else {
    if (is_request_cache_lookupable(s) && !s->is_upgrade_request) {
      s->cache_info.action = CacheAction_t::LOOKUP;
      s->current.mode      = ProxyMode_t::GENERIC;
    } else {
      s->cache_info.action = CacheAction_t::NO_ACTION;
      s->current.mode      = ProxyMode_t::TUNNELLING;
      Metrics::Counter::increment(http_rsb.tunnels);
    }
  }

  // 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 == CacheAction_t::LOOKUP) {
    TxnDbg(dbg_ctl_http_trans, "Will do cache lookup.");
    TxnDbg(dbg_ctl_http_seq, "Will do cache lookup");
    ink_assert(s->current.mode != ProxyMode_t::TUNNELLING);

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

      if (s->txn_conf->maintain_pristine_host_hdr) {
        s->cache_info.lookup_url_storage.create(nullptr);
        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) {
        // So, the host header will have the original host header.
        if (auto [field, host, port_sv]{incoming_request->get_host_port_values()}; field != nullptr) {
          int port = 0;
          if (!port_sv.empty()) {
            s->cache_info.lookup_url->host_set(host);
            port = ink_atoi(port_sv.data(), static_cast<int>(port_sv.length()));
          } else {
            s->cache_info.lookup_url->host_set(host);
          }
          s->cache_info.lookup_url->port_set(port);
        }
      }
      ink_assert(s->cache_info.lookup_url->valid() == true);
    }

    TRANSACT_RETURN(StateMachineAction_t::CACHE_LOOKUP, nullptr);
  } else {
    ink_assert(s->cache_info.action != CacheAction_t::LOOKUP && s->cache_info.action != CacheAction_t::SERVE);

    TxnDbg(dbg_ctl_http_trans, "Will NOT do cache lookup.");
    TxnDbg(dbg_ctl_http_seq, "Will NOT do cache lookup");
    // If this is a push request, we need send an error because
    //   since what ever was sent is not cacheable
    if (s->method == HTTP_WKSIDX_PUSH) {
      HandlePushError(s, "Request Not Cacheable");
      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
      if (s->txn_conf->cache_http) {
        HttpTransact::set_cache_prepare_write_action_for_new_request(s);
      }
      LookupSkipOpenServer(s);
    } else {
      // calling out CACHE_LOOKUP_COMPLETE_HOOK even when the cache
      // lookup is skipped
      s->cache_lookup_result = HttpTransact::CacheLookupResult_t::SKIPPED;
      if (s->force_dns) {
        TRANSACT_RETURN(StateMachineAction_t::API_CACHE_LOOKUP_COMPLETE, LookupSkipOpenServer);
      } else {
        // Returning to dns lookup as cache lookup is skipped
        TRANSACT_RETURN(StateMachineAction_t::API_CACHE_LOOKUP_COMPLETE, CallOSDNSLookup);
      }
    }
  }

  return;
}

void
HttpTransact::LookupSkipOpenServer(State *s)
{
  // cache will not be looked up. open a connection
  // to a parent proxy or to the origin server.
  find_server_and_update_current_info(s);

  if (s->current.request_to == ResolveInfo::PARENT_PROXY) {
    TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, PPDNSLookupAPICall);
  } else if (s->parent_result.result == ParentResultType::FAIL) {
    handle_parent_down(s);
    return;
  }

  ink_assert(s->current.request_to == ResolveInfo::ORIGIN_SERVER);
  // ink_assert(s->current.server->ip != 0);

  build_request(s, &s->hdr_info.client_request, &s->hdr_info.server_request, s->current.server->http_version);

  StateMachineAction_t next = how_to_open_connection(s);
  s->next_action            = next;
  if (next == StateMachineAction_t::ORIGIN_SERVER_OPEN || next == StateMachineAction_t::ORIGIN_SERVER_RAW_OPEN) {
    TRANSACT_RETURN(next, HttpTransact::HandleResponse);
  }
}

//////////////////////////////////////////////////////////////////////////////
// Name       : HandleCacheOpenReadPush
// Description:
//
// Details    :
//
// Called on PUSH requests from HandleCacheOpenRead
//////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleCacheOpenReadPush(State *s, bool read_successful)
{
  if (read_successful) {
    s->cache_info.action = CacheAction_t::PREPARE_TO_UPDATE;
  } else {
    s->cache_info.action = CacheAction_t::PREPARE_TO_WRITE;
  }

  TRANSACT_RETURN(StateMachineAction_t::READ_PUSH_HDR, HandlePushResponseHdr);
}

//////////////////////////////////////////////////////////////////////////////
// Name       : HandlePushResponseHdr
// Description:
//
// Details    :
//
// Called after reading the response header on PUSH request
//////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandlePushResponseHdr(State *s)
{
  // Verify the pushed header wasn't longer than the content length
  int64_t body_bytes = s->hdr_info.request_content_length - s->state_machine->pushed_response_hdr_bytes;
  if (body_bytes < 0) {
    HandlePushError(s, "Bad Content Length");
    return;
  }
  // We need to create the request header storing in the cache
  s->hdr_info.server_request.create(HTTPType::REQUEST);
  s->hdr_info.server_request.copy(&s->hdr_info.client_request);
  s->hdr_info.server_request.method_set(static_cast<std::string_view>(HTTP_METHOD_GET));
  s->hdr_info.server_request.value_set("X-Inktomi-Source"sv, "http PUSH"sv);

  dump_header(dbg_ctl_http_hdrs, &s->hdr_info.server_response, s->state_machine_id(), "Pushed Response Header");

  dump_header(dbg_ctl_http_hdrs, &s->hdr_info.server_request, s->state_machine_id(), "Generated Request Header");

  s->response_received_time = s->request_sent_time = ink_local_time();

  if (is_response_cacheable(s, &s->hdr_info.server_request, &s->hdr_info.server_response)) {
    ink_assert(s->cache_info.action == CacheAction_t::PREPARE_TO_WRITE || s->cache_info.action == CacheAction_t::PREPARE_TO_UPDATE);

    TRANSACT_RETURN(StateMachineAction_t::CACHE_ISSUE_WRITE, HandlePushCacheWrite);
  } else {
    HandlePushError(s, "Response Not Cacheable");
  }
}

//////////////////////////////////////////////////////////////////////////////
// Name       : HandlePushCacheWrite
// Description:
//
// Details    :
//
// Called after performing the cache write on a push request
//////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandlePushCacheWrite(State *s)
{
  switch (s->cache_info.write_lock_state) {
  case CacheWriteLock_t::SUCCESS:
    // We were able to get the lock for the URL vector in the cache
    if (s->cache_info.action == CacheAction_t::PREPARE_TO_WRITE) {
      s->cache_info.action = CacheAction_t::WRITE;
    } else if (s->cache_info.action == CacheAction_t::PREPARE_TO_UPDATE) {
      s->cache_info.action = CacheAction_t::REPLACE;
    } else {
      ink_release_assert(0);
    }
    set_headers_for_cache_write(s, &s->cache_info.object_store, &s->hdr_info.server_request, &s->hdr_info.server_response);

    TRANSACT_RETURN(StateMachineAction_t::STORE_PUSH_BODY, nullptr);
    break;

  case CacheWriteLock_t::FAIL:
  case CacheWriteLock_t::READ_RETRY:
    // No write lock, can not complete request so bail
    HandlePushError(s, "Cache Write Failed");
    break;
  case CacheWriteLock_t::INIT:
  default:
    ink_release_assert(0);
  }
}

void
HttpTransact::HandlePushTunnelSuccess(State *s)
{
  ink_assert(s->cache_info.action == CacheAction_t::WRITE || s->cache_info.action == CacheAction_t::REPLACE);

  // FIX ME: check PUSH spec for status codes
  HTTPStatus resp_status = (s->cache_info.action == CacheAction_t::WRITE) ? HTTPStatus::CREATED : HTTPStatus::OK;

  build_response(s, &s->hdr_info.client_response, s->client_info.http_version, resp_status);

  TRANSACT_RETURN(StateMachineAction_t::INTERNAL_CACHE_NOOP, nullptr);
}

void
HttpTransact::HandlePushTunnelFailure(State *s)
{
  HandlePushError(s, "Cache Error");
}

void
HttpTransact::HandleBadPushRespHdr(State *s)
{
  HandlePushError(s, "Malformed Pushed Response Header");
}

void
HttpTransact::HandlePushError(State *s, const char *reason)
{
  s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;

  // Set half close flag to prevent TCP
  //   reset from the body still being transferred
  s->state_machine->set_ua_half_close_flag();

  build_error_response(s, HTTPStatus::BAD_REQUEST, reason, "default");
}

///////////////////////////////////////////////////////////////////////////////
// Name       : HandleCacheOpenRead
// Description: the cache lookup succeeded - may have been a hit or a miss
//
// Details    :
//
// the cache lookup succeeded. first check if the lookup resulted in
// a hit or a miss, if the lookup was for an http request.
// This function just funnels the result into the appropriate
// functions which handle these different cases.
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleCacheOpenRead(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "[HttpTransact::HandleCacheOpenRead]");

  SET_VIA_STRING(VIA_DETAIL_CACHE_TYPE, VIA_DETAIL_CACHE);

  bool read_successful = true;

  if (s->cache_info.object_read == nullptr) {
    read_successful = false;
    //
    // If somebody else was writing the document, proceed just like it was
    // a normal cache miss, except don't try to write to the cache
    //
    if (s->cache_lookup_result == CacheLookupResult_t::DOC_BUSY) {
      s->cache_lookup_result = CacheLookupResult_t::MISS;
      s->cache_info.action   = CacheAction_t::NO_ACTION;
    }
  } else {
    CacheHTTPInfo *obj = s->cache_info.object_read;
    if (obj->response_get()->type_get() == HTTPType::UNKNOWN) {
      read_successful = false;
    }
    if (obj->request_get()->type_get() == HTTPType::UNKNOWN) {
      read_successful = false;
    }
  }

  if (s->method == HTTP_WKSIDX_PUSH) {
    HandleCacheOpenReadPush(s, read_successful);
  } else if (read_successful == false) {
    // cache miss
    TxnDbg(dbg_ctl_http_trans, "CacheOpenRead -- miss");
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_NOT_CACHED);
    // Perform DNS for the origin when it is required.
    // 1. If parent configuration does not allow to go to origin there is no need of performing DNS
    // 2. If parent satisfies the request there is no need to go to origin to perform DNS
    HandleCacheOpenReadMiss(s);
  } else {
    // cache hit
    TxnDbg(dbg_ctl_http_trans, "CacheOpenRead -- hit");
    TRANSACT_RETURN(StateMachineAction_t::API_READ_CACHE_HDR, HandleCacheOpenReadHitFreshness);
  }

  return;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : issue_revalidate
// Description:   Sets cache action and does various bookkeeping
//
// Details    :
//
// The Cache Lookup was hit but the document was stale so after
//   calling build_request, we need setup up the cache action,
//   set the via code, and possibly conditionalize the request
// The paths that we take to get this code are:
//   Directly from HandleOpenReadHit if we are going to the origin server
//   After PPDNS if we are going to a parent proxy
//
//
// Possible Next States From Here:
// -
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::issue_revalidate(State *s)
{
  HTTPHdr *c_resp = find_appropriate_cached_resp(s);
  SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_STALE);
  ink_assert(GET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP) != ' ');

  if (s->www_auth_content == CacheAuth_t::FRESH) {
    s->hdr_info.server_request.method_set(static_cast<std::string_view>(HTTP_METHOD_HEAD));
    // The document is fresh in cache and we just want to see if the
    // the client has the right credentials
    // this cache action is just to get us into the hcoofsr function
    s->cache_info.action = CacheAction_t::UPDATE;
    dump_header(dbg_ctl_http_hdrs, &s->hdr_info.server_request, s->state_machine_id(), "Proxy's Request (Conditionalized)");
    return;
  }

  if (s->cache_info.write_lock_state == CacheWriteLock_t::INIT) {
    // We do a cache lookup for DELETE, PUT and POST requests as well.
    // We must, however, delete the cached copy after forwarding the
    // request to the server. is_cache_response_returnable will ensure
    // that we forward the request. We now specify what the cache
    // action should be when the response is received.
    if (does_method_require_cache_copy_deletion(s->txn_conf, s->method)) {
      s->cache_info.action = CacheAction_t::PREPARE_TO_DELETE;
      TxnDbg(dbg_ctl_http_seq, "cache action: DELETE");
    } else {
      s->cache_info.action = CacheAction_t::PREPARE_TO_UPDATE;
      TxnDbg(dbg_ctl_http_seq, "cache action: UPDATE");
    }
  } else {
    // We've looped back around due to missing the write lock
    //  for the cache.  At this point we want to forget about the cache
    ink_assert(s->cache_info.write_lock_state == CacheWriteLock_t::READ_RETRY);
    s->cache_info.action = CacheAction_t::NO_ACTION;
    return;
  }

  // if the document is cached, just send a conditional request to the server

  // So the request does not have preconditions. It can, however
  // be a simple GET request with a Pragma:no-cache. As on 8/28/98
  // we have fixed the whole Reload/Shift-Reload cached copy
  // corruption problem. This means that we can issue a conditional
  // request to the server only if the incoming request has a conditional
  // or the incoming request does NOT have a no-cache header.
  // In other words, if the incoming request is not conditional
  // but has a no-cache header we can not issue an IMS. check for
  // that case here.
  bool no_cache_in_request = false;

  if (s->hdr_info.client_request.is_pragma_no_cache_set() ||
      s->hdr_info.client_request.is_cache_control_set(HTTP_VALUE_NO_CACHE.c_str())) {
    TxnDbg(dbg_ctl_http_trans, "no-cache header directive in request, folks");
    no_cache_in_request = true;
  }

  if ((!(s->hdr_info.client_request.presence(MIME_PRESENCE_IF_MODIFIED_SINCE))) &&
      (!(s->hdr_info.client_request.presence(MIME_PRESENCE_IF_NONE_MATCH))) && (no_cache_in_request == true) &&
      (!s->txn_conf->cache_ims_on_client_no_cache) && (s->www_auth_content == CacheAuth_t::NONE)) {
    TxnDbg(dbg_ctl_http_trans, "Can not make this a conditional request. This is the force update of the cached copy case");
    // set cache action to update. response will be a 200 or error,
    // causing cached copy to be replaced (if 200).
    s->cache_info.action = CacheAction_t::PREPARE_TO_UPDATE;
    return;
  }
  // do not conditionalize if the cached response is not a 200
  switch (c_resp->status_get()) {
  case HTTPStatus::OK: // 200
    // don't conditionalize if we are configured to repeat the clients
    //   conditionals
    if (s->txn_conf->cache_when_to_revalidate == 4) {
      break;
    }
    // ok, request is either a conditional or does not have a no-cache.
    //   (or is method that we don't conditionalize but lookup the
    //    cache on like DELETE)
    if (c_resp->get_last_modified() > 0 &&
        (s->hdr_info.server_request.method_get_wksidx() == HTTP_WKSIDX_GET ||
         s->hdr_info.server_request.method_get_wksidx() == HTTP_WKSIDX_HEAD) &&
        s->range_setup == RangeSetup_t::NONE) {
      // make this a conditional request
      if (auto str{c_resp->value_get(static_cast<std::string_view>(MIME_FIELD_LAST_MODIFIED))}; !str.empty()) {
        s->hdr_info.server_request.value_set(static_cast<std::string_view>(MIME_FIELD_IF_MODIFIED_SINCE), str);
      }
      dump_header(dbg_ctl_http_hdrs, &s->hdr_info.server_request, s->state_machine_id(), "Proxy's Request (Conditionalized)");
    }
    // if Etag exists, also add if-non-match header
    if (c_resp->presence(MIME_PRESENCE_ETAG) && (s->hdr_info.server_request.method_get_wksidx() == HTTP_WKSIDX_GET ||
                                                 s->hdr_info.server_request.method_get_wksidx() == HTTP_WKSIDX_HEAD)) {
      auto etag{c_resp->value_get(static_cast<std::string_view>(MIME_FIELD_ETAG))};
      if (!etag.empty()) {
        if (etag.starts_with("W/"sv)) {
          etag.remove_prefix(2);
        }
        s->hdr_info.server_request.value_set(static_cast<std::string_view>(MIME_FIELD_IF_NONE_MATCH), etag);
      }
      dump_header(dbg_ctl_http_hdrs, &s->hdr_info.server_request, s->state_machine_id(), "Proxy's Request (Conditionalized)");
    }
    break;
  case HTTPStatus::NON_AUTHORITATIVE_INFORMATION: // 203
  /* fall through */
  case HTTPStatus::MULTIPLE_CHOICES: // 300
  /* fall through */
  case HTTPStatus::MOVED_PERMANENTLY: // 301
  /* fall through */
  case HTTPStatus::GONE: // 410
  /* fall through */
  default:
    TxnDbg(dbg_ctl_http_trans, "cached response is not a 200 response so no conditionalization.");
    s->cache_info.action = CacheAction_t::PREPARE_TO_UPDATE;
    break;
  case HTTPStatus::PARTIAL_CONTENT:
    ink_assert(!"unexpected status code");
    break;
  }
}

void
HttpTransact::HandleCacheOpenReadHitFreshness(State *s)
{
  CacheHTTPInfo *&obj = s->cache_info.object_read;

  ink_release_assert((s->request_sent_time == UNDEFINED_TIME) && (s->response_received_time == UNDEFINED_TIME));
  TxnDbg(dbg_ctl_http_seq, "Hit in cache");

  if (delete_all_document_alternates_and_return(s, true)) {
    TxnDbg(dbg_ctl_http_trans, "Delete and return");
    s->cache_info.action = CacheAction_t::DELETE;
    s->next_action       = HttpTransact::StateMachineAction_t::INTERNAL_CACHE_DELETE;
    return;
  }

  s->request_sent_time      = obj->request_sent_time_get();
  s->response_received_time = obj->response_received_time_get();

  // There may be clock skew if one of the machines
  // went down and we do not have the correct delta
  // for it. this is just to deal with the effects
  // of the skew by setting minimum and maximum times
  // so that ages are not negative, etc.
  s->request_sent_time      = std::min(s->client_request_time, s->request_sent_time);
  s->response_received_time = std::min(s->client_request_time, s->response_received_time);

  ink_assert(s->request_sent_time <= s->response_received_time);

  TxnDbg(dbg_ctl_http_trans, "request_sent_time      : %" PRId64, (int64_t)s->request_sent_time);
  TxnDbg(dbg_ctl_http_trans, "response_received_time : %" PRId64, (int64_t)s->response_received_time);
  // if the plugin has already decided the freshness, we don't need to
  // do it again
  if (s->cache_lookup_result == HttpTransact::CacheLookupResult_t::NONE) {
    // is the document still fresh enough to be served back to
    // the client without revalidation?
    Freshness_t freshness = what_is_document_freshness(s, &s->hdr_info.client_request, obj->response_get());
    switch (freshness) {
    case Freshness_t::FRESH:
      TxnDbg(dbg_ctl_http_seq, "Fresh copy");
      s->cache_lookup_result = HttpTransact::CacheLookupResult_t::HIT_FRESH;
      break;
    case Freshness_t::WARNING:
      TxnDbg(dbg_ctl_http_seq, "Heuristic-based Fresh copy");
      s->cache_lookup_result = HttpTransact::CacheLookupResult_t::HIT_WARNING;
      break;
    case Freshness_t::STALE:
      TxnDbg(dbg_ctl_http_seq, "Stale in cache");
      s->cache_lookup_result = HttpTransact::CacheLookupResult_t::HIT_STALE;
      break;
    default:
      ink_assert(!("what_is_document_freshness has returned unsupported code."));
      break;
    }
  }

  ink_assert(s->cache_lookup_result != HttpTransact::CacheLookupResult_t::MISS);
  if (s->cache_lookup_result == HttpTransact::CacheLookupResult_t::HIT_STALE) {
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_EXPIRED);
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_STALE);
  }

  TRANSACT_RETURN(StateMachineAction_t::API_CACHE_LOOKUP_COMPLETE, HttpTransact::HandleCacheOpenReadHit);
}

///////////////////////////////////////////////////////////////////////////////
// Name       : CallOSDNSLookup
// Description: Moves in StateMachineAction_t::DNS_LOOKUP state and sets the transact return to OSDNSLookup
//
// Details    :
/////////////////////////////////////////////////////////////////////////////
void
HttpTransact::CallOSDNSLookup(State *s)
{
  TxnDbg(dbg_ctl_http, "%s ", s->server_info.name);
  HostStatus  &pstatus = HostStatus::instance();
  HostStatRec *hst     = pstatus.getHostStatus(s->server_info.name);
  if (hst && hst->status == TSHostStatus::TS_HOST_STATUS_DOWN) {
    TxnDbg(dbg_ctl_http, "%d ", static_cast<int>(s->cache_lookup_result));
    s->current.state = OUTBOUND_CONGESTION;
    if (s->cache_lookup_result == CacheLookupResult_t::HIT_STALE || s->cache_lookup_result == CacheLookupResult_t::HIT_WARNING ||
        s->cache_lookup_result == CacheLookupResult_t::HIT_FRESH) {
      s->cache_info.action = CacheAction_t::SERVE;
    } else {
      s->cache_info.action = CacheAction_t::NO_ACTION;
    }
    handle_server_connection_not_open(s);
  } else {
    TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, OSDNSLookup);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : need_to_revalidate
// Description: Checks if a document which is in the cache needs to be revalidates
//
// Details    : Function calls AuthenticationNeeded and is_cache_response_returnable to determine
//              if the cached document can be served
/////////////////////////////////////////////////////////////////////////////
bool
HttpTransact::need_to_revalidate(State *s)
{
  bool           needs_revalidate, needs_authenticate = false;
  bool           needs_cache_auth = false;
  CacheHTTPInfo *obj;

  if (s->api_update_cached_object == HttpTransact::UpdateCachedObject_t::CONTINUE) {
    obj = &s->cache_info.object_store;
    ink_assert(obj->valid());
    if (!obj->valid()) {
      return true;
    }
  } else {
    obj = s->cache_info.object_read;
  }

  // do we have to authenticate with the server before
  // sending back the cached response to the client?
  Authentication_t authentication_needed = AuthenticationNeeded(s->txn_conf, &s->hdr_info.client_request, obj->response_get());

  switch (authentication_needed) {
  case Authentication_t::SUCCESS:
    TxnDbg(dbg_ctl_http_seq, "Authentication not needed");
    needs_authenticate = false;
    break;
  case Authentication_t::MUST_REVALIDATE:
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_METHOD);
    TxnDbg(dbg_ctl_http_seq, "Authentication needed");
    needs_authenticate = true;
    break;
  case Authentication_t::MUST_PROXY:
    TxnDbg(dbg_ctl_http_seq, "Authentication needed");
    needs_authenticate = true;
    break;
  case Authentication_t::CACHE_AUTH:
    TxnDbg(dbg_ctl_http_seq, "Authentication needed for cache_auth_content");
    needs_authenticate = false;
    needs_cache_auth   = true;
    break;
  default:
    ink_assert(!("AuthenticationNeeded has returned unsupported code."));
    return true;
    break;
  }

  ink_assert(is_cache_hit(s->cache_lookup_result));
  if (s->cache_lookup_result == CacheLookupResult_t::HIT_STALE &&
      s->api_update_cached_object != HttpTransact::UpdateCachedObject_t::CONTINUE) {
    needs_revalidate = true;
  } else {
    needs_revalidate = false;
  }

  bool send_revalidate = ((needs_authenticate == true) || (needs_revalidate == true) || (is_cache_response_returnable(s) == false));
  if (needs_cache_auth == true) {
    s->www_auth_content = send_revalidate ? CacheAuth_t::STALE : CacheAuth_t::FRESH;
    send_revalidate     = true;
  }
  return send_revalidate;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : HandleCacheOpenReadHit
// Description: handle result of a cache hit
//
// Details    :
//
// Cache lookup succeeded and resulted in a cache hit. This means
// that the Accept* and Etags fields also matched. The cache lookup
// may have resulted in a vector of alternates (since lookup may
// be based on a url). A different function (SelectFromAlternates)
// goes through the alternates and finds the best match. That is
// then returned to this function. The result may not be sent back
// to the client, still, if the document is not fresh enough, or
// does not have enough authorization, or if the client wants a
// reload, etc. that decision will be made in this routine.
//
//
// Possible Next States From Here:
// - HttpTransact::PROXY_INTERNAL_CACHE_DELETE;
// - HttpTransact::StateMachineAction_t::DNS_LOOKUP;
// - HttpTransact::ORIGIN_SERVER_OPEN;
// - HttpTransact::PROXY_INTERNAL_CACHE_NOOP;
// - HttpTransact::SERVE_FROM_CACHE;
// - result of how_to_open_connection()
//
//
// For Range requests, we will decide to do simple tunneling if one of the
// following conditions hold:
// - document stale
// - cached response doesn't have Accept-Ranges and Content-Length
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleCacheOpenReadHit(State *s)
{
  bool           needs_revalidate   = false;
  bool           needs_authenticate = false;
  bool           needs_cache_auth   = false;
  bool           server_up          = true;
  CacheHTTPInfo *obj;

  if (s->api_update_cached_object == HttpTransact::UpdateCachedObject_t::CONTINUE) {
    obj = &s->cache_info.object_store;
    ink_assert(obj->valid());
  } else {
    obj = s->cache_info.object_read;
  }

  if (obj == nullptr || !obj->valid()) {
    HandleCacheOpenReadMiss(s);
    return;
  }

  // do we have to authenticate with the server before
  // sending back the cached response to the client?
  Authentication_t authentication_needed = AuthenticationNeeded(s->txn_conf, &s->hdr_info.client_request, obj->response_get());

  switch (authentication_needed) {
  case Authentication_t::SUCCESS:
    TxnDbg(dbg_ctl_http_seq, "Authentication not needed");
    needs_authenticate = false;
    break;
  case Authentication_t::MUST_REVALIDATE:
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_METHOD);
    TxnDbg(dbg_ctl_http_seq, "Authentication needed");
    needs_authenticate = true;
    break;
  case Authentication_t::MUST_PROXY:
    TxnDbg(dbg_ctl_http_seq, "Authentication needed");
    HandleCacheOpenReadMiss(s);
    return;
  case Authentication_t::CACHE_AUTH:
    TxnDbg(dbg_ctl_http_seq, "Authentication needed for cache_auth_content");
    needs_authenticate = false;
    needs_cache_auth   = true;
    break;
  default:
    ink_assert(!("AuthenticationNeeded has returned unsupported code."));
    break;
  }

  ink_assert(is_cache_hit(s->cache_lookup_result));

  // We'll request a revalidation under one of these conditions:
  //
  // 1. Cache lookup is a hit, but the response is stale
  // 2. The cached object has a "Cache-Control: no-cache" header
  //       *and*
  //    proxy.config.http.cache.ignore_server_no_cache is set to 0 (i.e don't ignore no cache -- the default setting)
  //
  // But, we only do this if we're not in an API updating the cached object (see TSHttpTxnUpdateCachedObject)
  if ((((s->cache_lookup_result == CacheLookupResult_t::HIT_STALE) ||
        ((obj->response_get()->get_cooked_cc_mask() & MIME_COOKED_MASK_CC_NO_CACHE) && !s->cache_control.ignore_server_no_cache)) &&
       (s->api_update_cached_object != HttpTransact::UpdateCachedObject_t::CONTINUE))) {
    needs_revalidate = true;
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_EXPIRED);
  }

  // the response may not be directly returnable to the client. there
  // are several reasons for this: config may force revalidation or
  // client may have forced a refresh by sending a Pragma:no-cache
  // or a Cache-Control:no-cache, or the client may have sent a
  // non-GET/HEAD request for a document that is cached. an example
  // of a situation for this is when a client sends a DELETE, PUT
  // or POST request for a url that is cached. except for DELETE,
  // we may actually want to update the cached copy with the contents
  // of the PUT/POST, but the easiest, safest and most robust solution
  // is to simply delete the cached copy (in order to maintain cache
  // consistency). this is particularly true if the server does not
  // accept or conditionally accepts the PUT/POST requests.
  // anyhow, this is an overloaded function and will return false
  // if the origin server still has to be looked up.
  bool response_returnable = is_cache_response_returnable(s);

  // do we need to revalidate. in other words if the response
  // has to be authorized, is stale or can not be returned, do
  // a revalidate.
  bool send_revalidate = (needs_authenticate || needs_revalidate || !response_returnable);

  if (needs_cache_auth == true) {
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_EXPIRED);
    s->www_auth_content = send_revalidate ? CacheAuth_t::STALE : CacheAuth_t::FRESH;
    send_revalidate     = true;
  }

  TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- needs_auth          = %d", needs_authenticate);
  TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- needs_revalidate    = %d", needs_revalidate);
  TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- response_returnable = %d", response_returnable);
  TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- needs_cache_auth    = %d", needs_cache_auth);
  TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- send_revalidate     = %d", send_revalidate);

  if (send_revalidate) {
    TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- HIT-STALE");

    TxnDbg(dbg_ctl_http_seq, "Revalidate document with server");

    find_server_and_update_current_info(s);

    // We do not want to try to revalidate documents if we think
    //  the server is down due to the something report problem
    //
    // Note: we only want to skip origin servers because 1)
    //  parent proxies have their own negative caching
    //  scheme & 2) If we skip down parents, every page
    //  we serve is potentially stale
    //
    if (s->current.request_to == ResolveInfo::ORIGIN_SERVER && is_server_negative_cached(s) && response_returnable == true &&
        is_stale_cache_response_returnable(s) == true) {
      server_up = false;
      update_current_info(&s->current, nullptr, ResolveInfo::UNDEFINED_LOOKUP, true);
      TxnDbg(dbg_ctl_http_trans, "CacheOpenReadHit - server_down, returning stale document");
    }
    // a parent lookup could come back as ParentResultType::FAIL if in parent.config, go_direct == false and
    // there are no available parents (all down).
    else if (s->current.request_to == ResolveInfo::HOST_NONE && s->parent_result.result == ParentResultType::FAIL) {
      if (response_returnable == true && is_stale_cache_response_returnable(s) == true) {
        server_up = false;
        update_current_info(&s->current, nullptr, ResolveInfo::UNDEFINED_LOOKUP, true);
        TxnDbg(dbg_ctl_http_trans, "CacheOpenReadHit - server_down, returning stale document");
      } else {
        handle_parent_down(s);
        return;
      }
    }

    if (server_up) {
      // set a default version for the outgoing request
      HTTPVersion http_version;

      if (s->current.server != nullptr) {
        bool check_hostdb = get_ka_info_from_config(s, s->current.server);
        TxnDbg(dbg_ctl_http_trans, "CacheOpenReadHit - check_hostdb %d", check_hostdb);
        if (check_hostdb || !s->current.server->dst_addr.isValid()) {
          // We must be going a PARENT PROXY since so did
          //  origin server DNS lookup right after state Start
          //
          // If we end up here in the release case just fall
          //  through.  The request will fail because of the
          //  missing ip but we won't take down the system
          //
          if (s->current.request_to == ResolveInfo::PARENT_PROXY) {
            // Set ourselves up to handle pending revalidate issues
            //  after the PP DNS lookup
            ink_assert(s->pending_work == nullptr);
            s->pending_work = issue_revalidate;

            TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, PPDNSLookupAPICall);
          } else if (s->current.request_to == ResolveInfo::ORIGIN_SERVER) {
            return CallOSDNSLookup(s);
          } else {
            handle_parent_down(s);
            return;
          }
        }
        // override the default version with what the server has
        http_version = s->current.server->http_version;
      }

      TxnDbg(dbg_ctl_http_trans, "CacheOpenReadHit - version %d.%d", http_version.get_major(), http_version.get_minor());
      build_request(s, &s->hdr_info.client_request, &s->hdr_info.server_request, http_version);

      issue_revalidate(s);

      // this can not be anything but a simple origin server connection.
      // in other words, we would not have looked up the cache for a
      // connect request, so the next action can not be origin_server_raw_open.
      s->next_action = how_to_open_connection(s);

      ink_release_assert(s->next_action != StateMachineAction_t::ORIGIN_SERVER_RAW_OPEN);
      return;
    } else { // server is down but stale response is returnable
      SET_VIA_STRING(VIA_DETAIL_CACHE_TYPE, VIA_DETAIL_CACHE);
    }
  }
  // cache hit, document is fresh, does not authorization,
  // is valid, etc. etc. send it back to the client.
  //
  // the important thing to keep in mind is that if we are
  // here then we found a match in the cache and the document
  // is fresh and we have enough authorization for it to send
  // it back to the client without revalidating first with the
  // origin server. we are, therefore, allowed to behave as the
  // origin server. we can, therefore, make the claim that the
  // document has not been modified since or has not been unmodified
  // since the time requested by the client. this may not be
  // the case in reality, but since the document is fresh in
  // the cache, we can make the claim that this is the truth.
  //
  // so, any decision we make at this point can be made with authority.
  // realistically, if we can not make this claim, then there
  // is no reason to cache anything.
  //
  ink_assert((send_revalidate == true && server_up == false) || (send_revalidate == false && server_up == true));

  TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- HIT-FRESH");
  TxnDbg(dbg_ctl_http_seq, "[HttpTransact::HandleCacheOpenReadHit] Serve from cache");

  // ToDo: Should support other levels of cache hits here, but the cache does not support it (yet)
  if (SQUID_HIT_RAM == s->cache_info.hit_miss_code) {
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_RAM_CACHE_FRESH);
  } else {
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_FRESH);
  }

  HttpCacheSM &cache_sm = s->state_machine->get_cache_sm();
  TxnDbg(dbg_ctl_http_trans, "CacheOpenRead --- HIT-FRESH read while write %d", cache_sm.is_readwhilewrite_inprogress());
  if (cache_sm.is_readwhilewrite_inprogress())
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_RWW_HIT);

  if (s->cache_lookup_result == CacheLookupResult_t::HIT_WARNING) {
    build_response_from_cache(s, HTTPWarningCode::HERUISTIC_EXPIRATION);
  } else if (s->cache_lookup_result == CacheLookupResult_t::HIT_STALE) {
    ink_assert(server_up == false);
    build_response_from_cache(s, HTTPWarningCode::REVALIDATION_FAILED);
  } else {
    build_response_from_cache(s, HTTPWarningCode::NONE);
  }

  if (s->api_update_cached_object == HttpTransact::UpdateCachedObject_t::CONTINUE) {
    s->saved_update_next_action  = s->next_action;
    s->saved_update_cache_action = s->cache_info.action;
    s->next_action               = StateMachineAction_t::CACHE_PREPARE_UPDATE;
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : build_response_from_cache()
// Description: build a client response from cached response and client request
//
// Input      : State, warning code to be inserted into the response header
// Output     :
//
// Details    : This function is called if we decided to serve a client request
//              using a cached response.
//              It is called by handle_server_connection_not_open()
//              and HandleCacheOpenReadHit().
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::build_response_from_cache(State *s, HTTPWarningCode warning_code)
{
  HTTPHdr       *client_request  = &s->hdr_info.client_request;
  HTTPHdr       *cached_response = nullptr;
  HTTPHdr       *to_warn         = &s->hdr_info.client_response;
  CacheHTTPInfo *obj;

  if (s->api_update_cached_object == HttpTransact::UpdateCachedObject_t::CONTINUE) {
    obj = &s->cache_info.object_store;
    ink_assert(obj->valid());
  } else {
    obj = s->cache_info.object_read;
  }
  cached_response = obj->response_get();

  // If the client request is conditional, and the cached copy meets
  // the conditions, do not need to send back the full document,
  // just a NOT_MODIFIED response.
  // If the request is not conditional,
  // the function match_response_to_request_conditionals() returns
  // the code of the cached response, which means that we should send
  // back the full document.
  HTTPStatus client_response_code =
    HttpTransactCache::match_response_to_request_conditionals(client_request, cached_response, s->response_received_time);

  switch (client_response_code) {
  case HTTPStatus::NOT_MODIFIED:
    // A IMS or INM GET client request with conditions being met
    // by the cached response.  Send back a NOT MODIFIED response.
    TxnDbg(dbg_ctl_http_trans, "Not modified");
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_HIT_CONDITIONAL);

    build_response(s, cached_response, &s->hdr_info.client_response, s->client_info.http_version, client_response_code);
    s->cache_info.action = CacheAction_t::NO_ACTION;
    s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
    break;

  case HTTPStatus::PRECONDITION_FAILED:
    // A conditional request with conditions not being met by the cached
    // response.  Send back a PRECONDITION FAILED response.
    TxnDbg(dbg_ctl_http_trans, "Precondition Failed");
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_CONDITIONAL);

    build_response(s, &s->hdr_info.client_response, s->client_info.http_version, client_response_code);
    s->cache_info.action = CacheAction_t::NO_ACTION;
    s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
    break;

  // Check if cached response supports Range. If it does, append
  // Range transformation plugin
  // A little misnomer. HTTPStatus::RANGE_NOT_SATISFIABLE
  // actually means If-Range match fails here.
  // fall through
  default:
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_HIT_SERVED);
    if (s->method == HTTP_WKSIDX_GET || (s->txn_conf->cache_post_method == 1 && s->method == HTTP_WKSIDX_POST) ||
        s->api_resp_cacheable == true) {
      // send back the full document to the client.
      TxnDbg(dbg_ctl_http_trans, "Match! Serving full document.");
      s->cache_info.action = CacheAction_t::SERVE;

      // Check if cached response supports Range. If it does, append
      // Range transformation plugin
      // only if the cached response is a 200 OK
      if (client_response_code == HTTPStatus::OK && client_request->presence(MIME_PRESENCE_RANGE) &&
          HttpTransactCache::validate_ifrange_header_if_any(client_request, cached_response)) {
        s->state_machine->do_range_setup_if_necessary();
        if (s->range_setup == RangeSetup_t::NOT_SATISFIABLE) {
          build_error_response(s, HTTPStatus::RANGE_NOT_SATISFIABLE, "Requested Range Not Satisfiable", "default");
          s->cache_info.action = CacheAction_t::NO_ACTION;
          s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
          break;
        } else if ((s->range_setup == RangeSetup_t::NOT_HANDLED) || !s->range_in_cache) {
          // we switch to tunneling for Range requests if it is out of order.
          // or if the range can't be satisfied from the cache
          // In that case we fetch the entire source so it's OK to switch
          // this late.
          TxnDbg(dbg_ctl_http_seq, "Out-of-order Range request - tunneling");
          s->cache_info.action = CacheAction_t::NO_ACTION;
          if (s->force_dns || s->dns_info.resolved_p) {
            HandleCacheOpenReadMiss(s); // DNS is already completed no need of doing DNS
          } else {
            CallOSDNSLookup(s);
          }
          return;
        }
      }

      if (s->state_machine->do_transform_open()) {
        set_header_for_transform(s, cached_response);
        to_warn = &s->hdr_info.transform_response;
      } else {
        build_response(s, cached_response, &s->hdr_info.client_response, s->client_info.http_version);
      }
      s->next_action = StateMachineAction_t::SERVE_FROM_CACHE;
    }
    // If the client request is a HEAD, then serve the header from cache.
    else if (s->method == HTTP_WKSIDX_HEAD) {
      TxnDbg(dbg_ctl_http_trans, "Match! Serving header only.");

      build_response(s, cached_response, &s->hdr_info.client_response, s->client_info.http_version);
      s->cache_info.action = CacheAction_t::NO_ACTION;
      s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
    } else {
      // We handled the request but it's not GET or HEAD (eg. DELETE),
      // and server is not reachable: 502
      //
      TxnDbg(dbg_ctl_http_trans, "No match! Connection failed.");
      build_error_response(s, HTTPStatus::BAD_GATEWAY, "Connection Failed", "connect#failed_connect");
      s->cache_info.action = CacheAction_t::NO_ACTION;
      s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
      warning_code         = HTTPWarningCode::NONE;
    }
    break;
  }

  // After building the client response, add the given warning if provided.
  if (warning_code != HTTPWarningCode::NONE) {
    delete_warning_value(to_warn, warning_code);
    HttpTransactHeaders::insert_warning_header(s->http_config_param, to_warn, warning_code);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_cache_write_lock
// Description:
//
// Details    :
//
//
//
// Possible Next States From Here:
// - result of how_to_open_connection
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_cache_write_lock(State *s)
{
  bool remove_ims = false;

  ink_assert(s->cache_info.action == CacheAction_t::PREPARE_TO_DELETE || s->cache_info.action == CacheAction_t::PREPARE_TO_UPDATE ||
             s->cache_info.action == CacheAction_t::PREPARE_TO_WRITE);

  switch (s->cache_info.write_lock_state) {
  case CacheWriteLock_t::SUCCESS:
    // We were able to get the lock for the URL vector in the cache
    SET_UNPREPARE_CACHE_ACTION(s->cache_info);
    break;
  case CacheWriteLock_t::FAIL:
    // No write lock, ignore the cache and proxy only;
    // FIX: Should just serve from cache if this is a revalidate
    Metrics::Counter::increment(http_rsb.cache_open_write_fail_count);
    s->cache_info.action = CacheAction_t::NO_ACTION;
    switch (static_cast<CacheOpenWriteFailAction_t>(s->cache_open_write_fail_action)) {
    case CacheOpenWriteFailAction_t::ERROR_ON_MISS:
    case CacheOpenWriteFailAction_t::ERROR_ON_MISS_STALE_ON_REVALIDATE:
    case CacheOpenWriteFailAction_t::ERROR_ON_MISS_OR_REVALIDATE:
      TxnDbg(dbg_ctl_http_error, "cache_open_write_fail_action %d, cache miss, return error", s->cache_open_write_fail_action);
      s->cache_info.write_status = CacheWriteStatus_t::ERROR;
      build_error_response(s, HTTPStatus::BAD_GATEWAY, "Connection Failed", "connect#failed_connect");
      MIMEField *ats_field;
      HTTPHdr   *header;
      header = &(s->hdr_info.client_response);
      if ((ats_field = header->field_find(static_cast<std::string_view>(MIME_FIELD_ATS_INTERNAL))) == nullptr) {
        if (likely((ats_field = header->field_create(static_cast<std::string_view>(MIME_FIELD_ATS_INTERNAL))) != nullptr)) {
          header->field_attach(ats_field);
        }
      }
      if (likely(ats_field)) {
        int value = (s->cache_info.object_read) ? 1 : 0;
        TxnDbg(dbg_ctl_http_error, "Adding Ats-Internal-Messages: %d", value);
        header->field_value_set_int(ats_field, value);
      } else {
        TxnDbg(dbg_ctl_http_error, "failed to add Ats-Internal-Messages");
      }

      TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
    default:
      s->cache_info.write_status = CacheWriteStatus_t::LOCK_MISS;
      remove_ims                 = true;
      break;
    }
    break;
  case CacheWriteLock_t::READ_RETRY:
    s->request_sent_time      = UNDEFINED_TIME;
    s->response_received_time = UNDEFINED_TIME;
    s->cache_info.action      = CacheAction_t::LOOKUP;
    if (!s->cache_info.object_read) {
      //  Write failed and read retry triggered
      //  Clean up server_request and re-initiate
      //  Cache Lookup
      ink_assert(s->cache_open_write_fail_action == static_cast<MgmtByte>(CacheOpenWriteFailAction_t::READ_RETRY));
      s->cache_info.write_status = CacheWriteStatus_t::LOCK_MISS;
      StateMachineAction_t next;
      next           = StateMachineAction_t::CACHE_LOOKUP;
      s->next_action = next;
      s->hdr_info.server_request.destroy();
      TRANSACT_RETURN(next, nullptr);
    }
    //  Write failed but retried and got a vector to read
    //  We need to clean up our state so that transact does
    //  not assert later on.  Then handle the open read hit
    remove_ims = true;
    SET_VIA_STRING(VIA_DETAIL_CACHE_TYPE, VIA_DETAIL_CACHE);
    break;
  case CacheWriteLock_t::INIT:
  default:
    ink_release_assert(0);
    break;
  }

  // Since we've already built the server request and we can't get the write
  //  lock we need to remove the ims field from the request since we're
  //  ignoring the cache.  If their is a client ims field, copy that since
  //  we're tunneling response anyway
  if (remove_ims) {
    s->hdr_info.server_request.field_delete(static_cast<std::string_view>(MIME_FIELD_IF_MODIFIED_SINCE));
    s->hdr_info.server_request.field_delete(static_cast<std::string_view>(MIME_FIELD_IF_NONE_MATCH));
    MIMEField *c_ims = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_IF_MODIFIED_SINCE));
    MIMEField *c_inm = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_IF_NONE_MATCH));

    if (c_ims) {
      auto value{c_ims->value_get()};
      s->hdr_info.server_request.value_set(static_cast<std::string_view>(MIME_FIELD_IF_MODIFIED_SINCE), value);
    }
    if (c_inm) {
      auto value{c_inm->value_get()};
      s->hdr_info.server_request.value_set(static_cast<std::string_view>(MIME_FIELD_IF_NONE_MATCH), value);
    }
  }

  if (s->cache_info.write_lock_state == CacheWriteLock_t::READ_RETRY) {
    TxnDbg(dbg_ctl_http_error, "calling hdr_info.server_request.destroy");
    s->hdr_info.server_request.destroy();
    HandleCacheOpenReadHitFreshness(s);
  } else {
    StateMachineAction_t next;
    next = how_to_open_connection(s);
    if (next == StateMachineAction_t::ORIGIN_SERVER_OPEN || next == StateMachineAction_t::ORIGIN_SERVER_RAW_OPEN) {
      s->next_action = next;
      TRANSACT_RETURN(next, nullptr);
    } else {
      // hehe!
      s->next_action = next;
      ink_assert(s->next_action == StateMachineAction_t::DNS_LOOKUP);
      return;
    }
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : HandleCacheOpenReadMiss
// Description: cache looked up, miss or hit, but needs authorization
//
// Details    :
//
//
//
// Possible Next States From Here:
// - HttpTransact::StateMachineAction_t::DNS_LOOKUP;
// - HttpTransact::ORIGIN_SERVER_OPEN;
// - HttpTransact::PROXY_INTERNAL_CACHE_NOOP;
// - result of how_to_open_connection()
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleCacheOpenReadMiss(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "--- MISS");
  TxnDbg(dbg_ctl_http_seq, "Miss in cache");

  if (delete_all_document_alternates_and_return(s, false)) {
    TxnDbg(dbg_ctl_http_trans, "Delete and return");
    s->cache_info.action = CacheAction_t::NO_ACTION;
    s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
    return;
  }
  // reinitialize some variables to reflect cache miss state.
  s->cache_info.object_read = nullptr;
  s->request_sent_time      = UNDEFINED_TIME;
  s->response_received_time = UNDEFINED_TIME;
  SET_VIA_STRING(VIA_CACHE_RESULT, VIA_CACHE_MISS);
  if (GET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP) == ' ') {
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_NOT_CACHED);
  }
  // We do a cache lookup for some non-GET requests as well.
  // We must, however, not cache the responses to these requests.
  if (does_method_require_cache_copy_deletion(s->txn_conf, s->method) && s->api_req_cacheable == false) {
    s->cache_info.action = CacheAction_t::NO_ACTION;
  } else if ((s->hdr_info.client_request.presence(MIME_PRESENCE_RANGE) && !s->txn_conf->cache_range_write) ||
             does_method_effect_cache(s->method) == false || s->range_setup == RangeSetup_t::NOT_SATISFIABLE ||
             s->range_setup == RangeSetup_t::NOT_HANDLED) {
    s->cache_info.action = CacheAction_t::NO_ACTION;
  } else if (s->api_server_response_no_store) { // plugin may have decided not to cache the response
    s->cache_info.action = CacheAction_t::NO_ACTION;
  } else {
    HttpTransact::set_cache_prepare_write_action_for_new_request(s);
  }

  ///////////////////////////////////////////////////////////////
  // a normal miss would try to fetch the document from the    //
  // origin server, unless the origin server isn't resolvable, //
  // but if "CacheControl: only-if-cached" is set, then we are //
  // supposed to send a 504 (GATEWAY TIMEOUT) response.        //
  ///////////////////////////////////////////////////////////////

  HTTPHdr *h = &s->hdr_info.client_request;

  if (!h->is_cache_control_set(HTTP_VALUE_ONLY_IF_CACHED.c_str())) {
    // Initialize the server_info structure if we haven't been through DNS
    // Otherwise, the http_version will not be initialized
    if (!s->current.server || !s->current.server->dst_addr.isValid()) {
      // Short term hack.  get_ka_info_from_config assumes if http_version is > 0,9 it has already been
      // set and skips the rest of the function.  The default functor sets it to 1,0
      s->server_info.http_version = HTTP_0_9;
      get_ka_info_from_config(s, &s->server_info);
    }
    find_server_and_update_current_info(s);
    // a parent lookup could come back as ParentResultType::FAIL if in parent.config go_direct == false and
    // there are no available parents (all down).
    if (s->parent_result.result == ParentResultType::FAIL) {
      handle_parent_down(s);
      return;
    }
    if (!s->current.server->dst_addr.isValid()) {
      ink_release_assert(s->parent_result.result == ParentResultType::DIRECT ||
                         s->current.request_to == ResolveInfo::PARENT_PROXY || s->txn_conf->no_dns_forward_to_parent != 0);
      if (s->parent_result.result == ParentResultType::DIRECT && s->txn_conf->no_dns_forward_to_parent != 1) {
        return CallOSDNSLookup(s);
      }
      if (s->current.request_to == ResolveInfo::PARENT_PROXY) {
        TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, HttpTransact::PPDNSLookupAPICall);
      } else {
        handle_parent_down(s);
        return;
      }
    }
    build_request(s, &s->hdr_info.client_request, &s->hdr_info.server_request, s->current.server->http_version);
    s->current.retry_attempts.clear();
    s->next_action = how_to_open_connection(s);
    if (s->current.server == &s->server_info && s->next_hop_scheme == URL_WKSIDX_HTTP) {
      HttpTransactHeaders::remove_host_name_from_url(&s->hdr_info.server_request);
    }
  } else { // miss, but only-if-cached is set
    build_error_response(s, HTTPStatus::GATEWAY_TIMEOUT, "Not Cached", "cache#not_in_cache");
    s->next_action = StateMachineAction_t::SEND_ERROR_CACHE_NOOP;
  }

  return;
}

void
HttpTransact::set_cache_prepare_write_action_for_new_request(State *s)
{
  // This method must be called no more than one time per request. It should
  // not be called for non-cacheable requests.
  if (s->cache_info.write_lock_state == CacheWriteLock_t::SUCCESS) {
    // If and only if this is a redirected request, we may have already
    // prepared a cache write (during the handling of the previous request
    // which got the 3xx response) and can safely re-use it. Otherwise, we
    // risk storing the response under the wrong cache key. This is a release
    // assert because the correct behavior would be to prepare a new write,
    // but we can't do that because we failed to release the lock. To recover
    // we would have to tell the state machine to abort its write, and we
    // don't have a state for that.
    ink_release_assert(s->redirect_info.redirect_in_process);
    s->cache_info.action = CacheAction_t::WRITE;
  } else {
    s->cache_info.action           = CacheAction_t::PREPARE_TO_WRITE;
    s->cache_info.write_lock_state = HttpTransact::CacheWriteLock_t::INIT;
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : OriginServerRawOpen
// Description: called for ssl tunneling
//
// Details    :
//
// when the method is CONNECT, we open a raw connection to the origin
// server. if the open succeeds, then do ssl tunneling from the client
// to the host.
//
//
// Possible Next States From Here:
// - HttpTransact::PROXY_INTERNAL_CACHE_NOOP;
// - HttpTransact::SSL_TUNNEL;
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::OriginServerRawOpen(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "Entering HttpTransact::OriginServerRawOpen");

  switch (s->current.state) {
  case STATE_UNDEFINED:
  /* fall through */
  case OPEN_RAW_ERROR:
  /* fall through */
  case CONNECTION_ERROR:
  /* fall through */
  case CONNECTION_CLOSED:
    /* fall through */
  case OUTBOUND_CONGESTION:
    /* fall through */
    handle_server_down(s);

    ink_assert(s->cache_info.action == CacheAction_t::NO_ACTION);
    s->next_action = StateMachineAction_t::INTERNAL_CACHE_NOOP;
    break;
  case CONNECTION_ALIVE:
    build_response(s, &s->hdr_info.client_response, s->client_info.http_version, HTTPStatus::OK);

    TxnDbg(dbg_ctl_http_trans, "connection alive. next action is ssl_tunnel");
    s->next_action = StateMachineAction_t::SSL_TUNNEL;
    break;
  default:
    ink_assert(!("s->current.state is set to something unsupported"));
    break;
  }

  return;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : HandleResponse
// Description: called from the state machine when a response is received
//
// Details    :
//
//   This is the entry into a coin-sorting machine. There are many different
//   bins that the response can fall into. First, the response can be invalid
//   if for example it is not a response, or not complete, or the connection
//   was closed, etc. Then, the response can be from  parent proxy or from
//   the origin server. The next action to take differs for all three of these
//   cases. Finally, good responses can either require a cache action,
//   be it deletion, update, or writing or may just need to be tunnelled
//   to the client. This latter case should be handled with as little processing
//   as possible, since it should represent a fast path.
//
//
// Possible Next States From Here:
//
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleResponse(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "Entering HttpTransact::HandleResponse");
  TxnDbg(dbg_ctl_http_seq, "Response received");

  s->source                 = Source_t::HTTP_ORIGIN_SERVER;
  s->response_received_time = ink_local_time();
  ink_assert(s->response_received_time >= s->request_sent_time);
  s->current.now = s->response_received_time;

  TxnDbg(dbg_ctl_http_trans, "response_received_time: %" PRId64, (int64_t)s->response_received_time);
  dump_header(dbg_ctl_http_hdrs, &s->hdr_info.server_response, s->state_machine_id(), "Incoming O.S. Response");

  Metrics::Counter::increment(http_rsb.incoming_responses);

  ink_release_assert(s->current.request_to != ResolveInfo::UNDEFINED_LOOKUP);
  if (s->cache_info.action != CacheAction_t::WRITE) {
    ink_release_assert(s->cache_info.action != CacheAction_t::LOOKUP);
    ink_release_assert(s->cache_info.action != CacheAction_t::SERVE);
    ink_release_assert(s->cache_info.action != CacheAction_t::PREPARE_TO_DELETE);
    ink_release_assert(s->cache_info.action != CacheAction_t::PREPARE_TO_UPDATE);
    ink_release_assert(s->cache_info.action != CacheAction_t::PREPARE_TO_WRITE);
  }

  if (!HttpTransact::is_response_valid(s, &s->hdr_info.server_response)) {
    TxnDbg(dbg_ctl_http_seq, "Response not valid");
  } else {
    TxnDbg(dbg_ctl_http_seq, "Response valid");
    initialize_state_variables_from_response(s, &s->hdr_info.server_response);
  }

  switch (s->current.request_to) {
  case ResolveInfo::PARENT_PROXY:
    handle_response_from_parent(s);
    break;
  case ResolveInfo::ORIGIN_SERVER:
    handle_response_from_server(s);
    break;
  default:
    ink_assert(!("s->current.request_to is not P.P. or O.S. - hmmm."));
    break;
  }

  return;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : HandleUpdateCachedObject
// Description: called from the state machine when we are going to modify
//              headers without any server contact.
//
// Details    : this function does very little. mainly to satisfy
//              the call_transact_and_set_next format and not affect
//              the performance of the non-invalidate operations, which
//              are the majority
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleUpdateCachedObject(State *s)
{
  if (s->cache_info.write_lock_state == HttpTransact::CacheWriteLock_t::SUCCESS) {
    ink_assert(s->cache_info.object_store.valid());
    ink_assert(s->cache_info.object_store.response_get() != nullptr);
    ink_assert(s->cache_info.object_read != nullptr);
    ink_assert(s->cache_info.object_read->valid());

    if (!s->cache_info.object_store.request_get()) {
      s->cache_info.object_store.request_set(s->cache_info.object_read->request_get());
    }
    s->request_sent_time      = s->cache_info.object_read->request_sent_time_get();
    s->response_received_time = s->cache_info.object_read->response_received_time_get();
    if (s->api_update_cached_object == UpdateCachedObject_t::CONTINUE) {
      TRANSACT_RETURN(StateMachineAction_t::CACHE_ISSUE_UPDATE, HttpTransact::HandleUpdateCachedObjectContinue);
    } else {
      TRANSACT_RETURN(StateMachineAction_t::CACHE_ISSUE_UPDATE, HttpTransact::HandleApiErrorJump);
    }
  } else if (s->api_update_cached_object == UpdateCachedObject_t::CONTINUE) {
    // even failed to update, continue to serve from cache
    HandleUpdateCachedObjectContinue(s);
  } else {
    s->api_update_cached_object = UpdateCachedObject_t::FAIL;
    HandleApiErrorJump(s);
  }
}

void
HttpTransact::HandleUpdateCachedObjectContinue(State *s)
{
  ink_assert(s->api_update_cached_object == UpdateCachedObject_t::CONTINUE);
  s->cache_info.action = s->saved_update_cache_action;
  s->next_action       = s->saved_update_next_action;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_response_from_parent
// Description: response came from a parent proxy
//
// Details    :
//
//   The configuration file can be used to specify more than one parent
//   proxy. If a connection to one fails, another can be looked up. This
//   function handles responses from parent proxies. If the response is
//   bad the next parent proxy (if any) is looked up. If there are no more
//   parent proxies that can be looked up, the response is sent to the
//   origin server. If the response is good handle_forward_server_connection_open
//   is called.
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_response_from_parent(State *s)
{
  auto next_lookup = ResolveInfo::UNDEFINED_LOOKUP;
  TxnDbg(dbg_ctl_http_trans, "(hrfp)");
  HTTP_RELEASE_ASSERT(s->current.server == &s->parent_info);

  // if this parent was retried from a markdown, then
  // notify that the retry has completed.
  if (s->parent_result.retry) {
    markParentUp(s);
  }

  simple_or_unavailable_server_retry(s);

  s->parent_info.state = s->current.state;
  switch (s->current.state) {
  case CONNECTION_ALIVE:
    TxnDbg(dbg_ctl_http_trans, "[hrfp] connection alive");
    s->current.server->connect_result = 0;
    SET_VIA_STRING(VIA_DETAIL_PP_CONNECT, VIA_DETAIL_PP_SUCCESS);
    if (s->parent_result.retry) {
      markParentUp(s);
    }
    // the next hop strategy is configured not
    // to cache a response from a next hop peer.
    if (s->response_action.handled) {
      if (s->response_action.action.no_cache) {
        TxnDbg(dbg_ctl_http_trans, "plugin set response_action.no_cache, do not cache.");
        s->cache_info.action = CacheAction_t::NO_ACTION;
      }
    } else {
      if (s->parent_result.do_not_cache_response) {
        TxnDbg(dbg_ctl_http_trans, "response is from a next hop peer, do not cache.");
        s->cache_info.action = CacheAction_t::NO_ACTION;
      }
    }
    handle_forward_server_connection_open(s);
    break;
  case PARENT_RETRY:
    if (s->current.retry_type == ParentRetry_t::SIMPLE) {
      s->current.simple_retry_attempts++;
    } else {
      markParentDown(s);
      s->current.unavailable_server_retry_attempts++;
    }
    next_lookup           = find_server_and_update_current_info(s);
    s->current.retry_type = ParentRetry_t::NONE;
    break;
  default:
    TxnDbg(dbg_ctl_http_trans, "[hrfp] connection not alive");
    SET_VIA_STRING(VIA_DETAIL_PP_CONNECT, VIA_DETAIL_PP_FAILURE);

    ink_assert(s->hdr_info.server_request.valid());

    s->current.server->connect_result = ENOTCONN;
    // only mark the parent down in hostdb if the configuration allows it and the parent,
    // is not congested, see proxy.config.http.parent_proxy.mark_down_hostdb in records.yaml.
    if (s->txn_conf->parent_failures_update_hostdb && s->current.state != OUTBOUND_CONGESTION) {
      s->state_machine->do_hostdb_update_if_necessary();
    }

    ip_port_text_buffer addrbuf;
    TxnDbg(dbg_ctl_http_trans, "[%d] failed to connect to parent %s", s->current.retry_attempts.get(),
           ats_ip_nptop(&s->current.server->dst_addr.sa, addrbuf, sizeof(addrbuf)));

    // If the request is not retryable, just give up!
    if (!is_request_retryable(s)) {
      if (s->current.state != OUTBOUND_CONGESTION) {
        markParentDown(s);
      }
      s->parent_result.result = ParentResultType::FAIL;
      handle_parent_down(s);
      return;
    }

    if (s->current.retry_attempts.get() < (s->txn_conf->parent_connect_attempts - 1)) {
      Metrics::Counter::increment(http_rsb.total_parent_retries);
      s->current.retry_attempts.increment();

      // Are we done with this particular parent?
      if (s->current.retry_attempts.get() % s->txn_conf->per_parent_connect_attempts != 0) {
        // No we are not done with this parent so retry
        Metrics::Counter::increment(http_rsb.total_parent_switches);
        s->next_action = how_to_open_connection(s);
        TxnDbg(dbg_ctl_http_trans, "%s Retrying parent for attempt %d, max %" PRId64, "[handle_response_from_parent]",
               s->current.retry_attempts.get(), s->txn_conf->per_parent_connect_attempts);
        return;
      } else {
        TxnDbg(dbg_ctl_http_trans, "%s %d per parent attempts exhausted", "[handle_response_from_parent]",
               s->current.retry_attempts.get());
        Metrics::Counter::increment(http_rsb.total_parent_retries_exhausted);

        // Only mark the parent down if we failed to connect
        //  to the parent otherwise slow origin servers cause
        //  us to mark the parent down
        if (s->current.state == CONNECTION_ERROR || s->current.state == INACTIVE_TIMEOUT) {
          markParentDown(s);
        }
        // We are done so look for another parent if any
        next_lookup = find_server_and_update_current_info(s);
      }
    } else {
      // Done trying parents... fail over to origin server if that is
      //   appropriate
      Metrics::Counter::increment(http_rsb.total_parent_retries_exhausted);
      TxnDbg(dbg_ctl_http_trans, "Error. No more retries.");
      if (s->current.state == CONNECTION_ERROR || s->current.state == INACTIVE_TIMEOUT) {
        markParentDown(s);
      }
      s->parent_result.result = ParentResultType::FAIL;
      next_lookup             = ResolveInfo::HOST_NONE;
    }
    break;
  }

  // We have either tried to find a new parent or failed over to the
  //   origin server
  switch (next_lookup) {
  case ResolveInfo::PARENT_PROXY:
    ink_assert(s->current.request_to == ResolveInfo::PARENT_PROXY);
    TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, PPDNSLookupAPICall);
    break;
  case ResolveInfo::ORIGIN_SERVER:
    // Next lookup is Origin Server, try DNS for Origin Server
    return CallOSDNSLookup(s);
    break;
  case ResolveInfo::HOST_NONE:
    // Check if content can be served from cache
    s->current.request_to = ResolveInfo::PARENT_PROXY;
    handle_server_connection_not_open(s);
    break;
  default:
    // This handles:
    // UNDEFINED_LOOKUP
    // INCOMING_ROUTER
    break;
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_response_from_server
// Description: response is from the origin server
//
// Details    :
//
//   response from the origin server. one of three things can happen now.
//   if the response is bad, then we can either retry (by first downgrading
//   the request, maybe making it non-keepalive, etc.), or we can give up.
//   the latter case is handled by handle_server_connection_not_open and
//   sends an error response back to the client. if the response is good
//   handle_forward_server_connection_open is called.
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_response_from_server(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "(hrfs)");
  HTTP_RELEASE_ASSERT(s->current.server == &s->server_info);
  unsigned max_connect_retries = 0;

  // plugin call
  s->server_info.state = s->current.state;
  if (s->os_response_plugin_inst) {
    s->os_response_plugin_inst->osResponse(reinterpret_cast<TSHttpTxn>(s->state_machine), s->current.state);
  }

  switch (s->current.state) {
  case CONNECTION_ALIVE:
    TxnDbg(dbg_ctl_http_trans, "[hrfs] connection alive");
    SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_SUCCESS);
    s->current.server->clear_connect_fail();
    handle_forward_server_connection_open(s);
    break;
  case OUTBOUND_CONGESTION:
    TxnDbg(dbg_ctl_http_trans, "Error. congestion control -- congested.");
    SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
    s->set_connect_fail(EUSERS); // too many users
    handle_server_connection_not_open(s);
    break;
  case OPEN_RAW_ERROR:
  case CONNECTION_ERROR:
  case STATE_UNDEFINED:
  case INACTIVE_TIMEOUT:
  case PARSE_ERROR:
  case CONNECTION_CLOSED:
  case BAD_INCOMING_RESPONSE:

    // Ensure cause_of_death_errno is set for all error states if not already set.
    // This prevents the assertion failure in retry_server_connection_not_open.
    if (s->cause_of_death_errno == -UNKNOWN_INTERNAL_ERROR) {
      if (s->current.state == PARSE_ERROR || s->current.state == BAD_INCOMING_RESPONSE) {
        s->set_connect_fail(EBADMSG);
      } else if (s->current.state == CONNECTION_CLOSED) {
        s->set_connect_fail(EPIPE);
      } else {
        // Generic fallback for OPEN_RAW_ERROR, CONNECTION_ERROR,
        // STATE_UNDEFINED, and any other unexpected error states.
        s->set_connect_fail(EIO);
      }
    }

    if (is_server_negative_cached(s)) {
      max_connect_retries = s->txn_conf->connect_attempts_max_retries_down_server - 1;
    } else {
      // server not yet negative cached - use default number of retries
      max_connect_retries = s->txn_conf->connect_attempts_max_retries;
    }

    TxnDbg(dbg_ctl_http_trans, "max_connect_retries: %d s->current.retry_attempts: %d", max_connect_retries,
           s->current.retry_attempts.get());

    if (is_request_retryable(s) && s->current.retry_attempts.get() < max_connect_retries &&
        !HttpTransact::is_response_valid(s, &s->hdr_info.server_response)) {
      // If this is a round robin DNS entry & we're tried configured
      //    number of times, we should try another node
      if (ResolveInfo::OS_Addr::TRY_CLIENT == s->dns_info.os_addr_style) {
        // attempt was based on client supplied server address. Try again using HostDB.
        // Allow DNS attempt
        s->dns_info.resolved_p = false;
        // See if we can get data from HostDB for this.
        s->dns_info.os_addr_style = ResolveInfo::OS_Addr::TRY_HOSTDB;
        // Force host resolution to have the same family as the client.
        // Because this is a transparent connection, we can't switch address
        // families - that is locked in by the client source address.
        ats_force_order_by_family(s->current.server->dst_addr.family(), s->my_txn_conf().host_res_data.order);
        return CallOSDNSLookup(s);
      } else if (ResolveInfo::OS_Addr::USE_API == s->dns_info.os_addr_style && !s->api_server_addr_set_retried) {
        // Plugin set the server address via TSHttpTxnServerAddrSet(). Clear resolution
        // state to allow the OS_DNS hook to be called again, giving the plugin a chance
        // to set a different server address for retry (issue #12611).
        // Only retry once to avoid infinite loops if the plugin keeps setting failing addresses.
        s->api_server_addr_set_retried = true;
        s->dns_info.resolved_p         = false;
        s->dns_info.os_addr_style      = ResolveInfo::OS_Addr::TRY_DEFAULT;
        // Clear the server request so it can be rebuilt for the new destination
        s->hdr_info.server_request.destroy();
        TxnDbg(dbg_ctl_http_trans, "Retrying with plugin-set address, returning to OS_DNS hook");
        return CallOSDNSLookup(s);
      } else {
        if ((s->txn_conf->connect_attempts_rr_retries > 0) &&
            ((s->current.retry_attempts.get() + 1) % s->txn_conf->connect_attempts_rr_retries == 0)) {
          s->dns_info.select_next_rr();
        }
        retry_server_connection_not_open(s, s->current.state, max_connect_retries);
        TxnDbg(dbg_ctl_http_trans, "Error. Retrying...");
        s->next_action = how_to_open_connection(s);
      }
    } else {
      error_log_connection_failure(s, s->current.state);
      TxnDbg(dbg_ctl_http_trans, "Error. No more retries.");
      SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
      handle_server_connection_not_open(s);
    }
    break;
  case ACTIVE_TIMEOUT:
    TxnDbg(dbg_ctl_http_trans, "[hrfs] connection not alive");
    SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
    s->set_connect_fail(ETIMEDOUT);
    handle_server_connection_not_open(s);
    break;
  default:
    ink_assert(!("s->current.state is set to something unsupported"));
    break;
  }

  return;
}

void
HttpTransact::error_log_connection_failure(State *s, ServerState_t conn_state)
{
  ip_port_text_buffer addrbuf;
  TxnDbg(dbg_ctl_http_trans, "[%d] failed to connect [%d] to %s", s->current.retry_attempts.get(), conn_state,
         ats_ip_nptop(&s->current.server->dst_addr.sa, addrbuf, sizeof(addrbuf)));

  if (s->current.server->had_connect_fail()) {
    char            *url_str = s->hdr_info.client_request.url_string_get(&s->arena);
    std::string_view host_name{};
    if (s->unmapped_url.valid()) {
      host_name = s->unmapped_url.host_get();
    }
    swoc::bwprint(error_bw_buffer,
                  "CONNECT: attempt fail [{}] to {} for host='{}' "
                  "connection_result={::s} error={::s} retry_attempts={} url='{}'",
                  HttpDebugNames::get_server_state_name(conn_state), s->current.server->dst_addr, host_name,
                  swoc::bwf::Errno(s->current.server->connect_result), swoc::bwf::Errno(s->cause_of_death_errno),
                  s->current.retry_attempts.get(), swoc::bwf::FirstOf(url_str, "<none>"));
    Log::error("%s", error_bw_buffer.c_str());

    s->arena.str_free(url_str);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : retry_server_connection_not_open
// Description:
//
// Details    :
//
//   connection to server failed. retry.
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::retry_server_connection_not_open(State *s, ServerState_t conn_state, unsigned max_retries)
{
  ink_assert(s->current.state != CONNECTION_ALIVE);
  ink_assert(s->current.state != ACTIVE_TIMEOUT);
  ink_assert(s->current.retry_attempts.get() < max_retries);
  ink_assert(s->cause_of_death_errno != -UNKNOWN_INTERNAL_ERROR);

  error_log_connection_failure(s, conn_state);

  //////////////////////////////////////////////
  // disable keep-alive for request and retry //
  //////////////////////////////////////////////
  s->current.server->keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  s->current.retry_attempts.increment();

  TxnDbg(dbg_ctl_http_trans, "retry attempts now: %d, max: %d", s->current.retry_attempts.get(), max_retries);

  return;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_server_connection_not_open
// Description:
//
// Details    :
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_server_connection_not_open(State *s)
{
  bool serve_from_cache = false;

  TxnDbg(dbg_ctl_http_trans, "(hscno)");
  TxnDbg(dbg_ctl_http_seq, "Entering HttpTransact::handle_server_connection_not_open");
  ink_assert(s->current.state != CONNECTION_ALIVE);

  SET_VIA_STRING(VIA_SERVER_RESULT, VIA_SERVER_ERROR);
  Metrics::Counter::increment(http_rsb.broken_server_connections);

  // Fire off a hostdb update to mark the server as down
  s->state_machine->do_hostdb_update_if_necessary();

  switch (s->cache_info.action) {
  case CacheAction_t::UPDATE:
  case CacheAction_t::SERVE:
    serve_from_cache = is_stale_cache_response_returnable(s);
    break;

  case CacheAction_t::PREPARE_TO_DELETE:
  /* fall through */
  case CacheAction_t::PREPARE_TO_UPDATE:
  /* fall through */
  case CacheAction_t::PREPARE_TO_WRITE:
    ink_release_assert(!"Why still preparing for cache action - "
                        "we skipped a step somehow.");
    break;

  case CacheAction_t::LOOKUP:
    ink_assert(!("Why server response? Should have been a cache operation"));
    break;

  case CacheAction_t::DELETE:
  // decisions, decisions. what should we do here?
  // we could theoretically still delete the cached
  // copy or serve it back with a warning, or easier
  // just punt and biff the user. i say: biff the user.
  /* fall through */
  case CacheAction_t::UNDEFINED:
  /* fall through */
  case CacheAction_t::NO_ACTION:
  /* fall through */
  case CacheAction_t::WRITE:
  /* fall through */
  default:
    serve_from_cache = false;
    break;
  }

  if (serve_from_cache) {
    ink_assert(s->cache_info.object_read != nullptr);
    ink_assert(s->cache_info.action == CacheAction_t::UPDATE || s->cache_info.action == CacheAction_t::SERVE);
    ink_assert(s->internal_msg_buffer == nullptr);
    s->source = Source_t::CACHE;
    TxnDbg(dbg_ctl_http_trans, "[hscno] serving stale doc to client");
    build_response_from_cache(s, HTTPWarningCode::REVALIDATION_FAILED);
  } else {
    switch (s->current.request_to) {
    case ResolveInfo::PARENT_PROXY:
      handle_parent_down(s);
      break;
    case ResolveInfo::ORIGIN_SERVER:
      handle_server_down(s);
      break;
    default:
      ink_assert(!("s->current.request_to is not P.P. or O.S. - hmmm."));
      break;
    }
    s->next_action = StateMachineAction_t::SEND_ERROR_CACHE_NOOP;
  }

  return;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_forward_server_connection_open
// Description: connection to a forward server is open and good
//
// Details    :
//
//   "Forward server" includes the parent proxy
//   or the origin server. This function first determines if the forward
//   server uses HTTP 0.9, in which case it simply tunnels the response
//   to the client. Else, it updates
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_forward_server_connection_open(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "(hfsco)");
  TxnDbg(dbg_ctl_http_seq, "Entering HttpTransact::handle_server_connection_open");
  ink_release_assert(s->current.state == CONNECTION_ALIVE);

  HTTPVersion real_version = s->state_machine->get_server_version(s->hdr_info.server_response);
  if (real_version != s->dns_info.http_version) {
    // Need to update the hostdb
    s->updated_server_version = real_version;
    TxnDbg(dbg_ctl_http_trans, "Update hostdb history of server HTTP version 0x%x", s->updated_server_version.get_flat_version());
  }

  s->state_machine->do_hostdb_update_if_necessary();

  if (s->hdr_info.server_response.status_get() == HTTPStatus::CONTINUE ||
      s->hdr_info.server_response.status_get() == HTTPStatus::EARLY_HINTS) {
    handle_100_continue_response(s);
    return;
  }

  if (s->www_auth_content == CacheAuth_t::FRESH) {
    // no update is needed - either to serve from cache if authorized,
    // or tunnnel the server response
    if (s->hdr_info.server_response.status_get() == HTTPStatus::OK) {
      // borrow a state variable used by the API function
      // this enable us to serve from cache without doing any updating
      s->api_server_response_ignore = true;
    }
    // s->cache_info.action = CACHE_PREPARE_TO_SERVE;
    // xing in the tunneling case, need to check when the cache_read_vc is closed, make sure the cache_read_vc is closed
    // right away
  }

  CacheVConnection *cw_vc = s->state_machine->get_cache_sm().cache_write_vc;

  if (s->redirect_info.redirect_in_process && s->state_machine->enable_redirection) {
    if (s->cache_info.action == CacheAction_t::NO_ACTION) {
      switch (s->hdr_info.server_response.status_get()) {
      case HTTPStatus::MULTIPLE_CHOICES:   // 300
      case HTTPStatus::MOVED_PERMANENTLY:  // 301
      case HTTPStatus::MOVED_TEMPORARILY:  // 302
      case HTTPStatus::SEE_OTHER:          // 303
      case HTTPStatus::USE_PROXY:          // 305
      case HTTPStatus::TEMPORARY_REDIRECT: // 307
      case HTTPStatus::PERMANENT_REDIRECT: // 308
        break;
      default:
        TxnDbg(dbg_ctl_http_trans, "[hfsco] redirect in progress, non-3xx response, setting cache_do_write");
        if (cw_vc && s->txn_conf->cache_http) {
          s->cache_info.action = CacheAction_t::WRITE;
        }
        break;
      }
    }
  }

  switch (s->cache_info.action) {
  case CacheAction_t::WRITE:
  /* fall through */
  case CacheAction_t::UPDATE:
  /* fall through */
  case CacheAction_t::DELETE:
    TxnDbg(dbg_ctl_http_trans, "[hfsco] cache action: %s", HttpDebugNames::get_cache_action_name(s->cache_info.action));
    handle_cache_operation_on_forward_server_response(s);
    break;
  case CacheAction_t::PREPARE_TO_DELETE:
  /* fall through */
  case CacheAction_t::PREPARE_TO_UPDATE:
  /* fall through */
  case CacheAction_t::PREPARE_TO_WRITE:
    ink_release_assert(!"Why still preparing for cache action - we skipped a step somehow.");
    break;
  case CacheAction_t::LOOKUP:
  /* fall through */
  case CacheAction_t::SERVE:
    ink_assert(!("Why server response? Should have been a cache operation"));
    break;
  case CacheAction_t::UNDEFINED:
  /* fall through */
  case CacheAction_t::NO_ACTION:
  /* fall through */
  default:
    // Just tunnel?
    TxnDbg(dbg_ctl_http_trans, "[hfsco] cache action: %s", HttpDebugNames::get_cache_action_name(s->cache_info.action));
    handle_no_cache_operation_on_forward_server_response(s);
    break;
  }

  return;
}

// void HttpTransact::handle_100_continue_response(State* s)
//
//   We've received a 100 continue response.  Determine if
//     we should just swallow the response 100 or forward it
//     the client.  http-1.1-spec-rev-06 section 8.2.3
//
void
HttpTransact::handle_100_continue_response(State *s)
{
  bool forward_100 = false;

  HTTPVersion ver = s->hdr_info.client_request.version_get();
  if (ver == HTTP_1_1) {
    forward_100 = true;
  } else if (ver == HTTP_1_0) {
    if (s->hdr_info.client_request.value_get_int(static_cast<std::string_view>(MIME_FIELD_EXPECT)) == 100) {
      forward_100 = true;
    }
  }

  if (forward_100) {
    // We just want to copy the server's response.  All
    //   the other build response functions insist on
    //   adding stuff
    build_response_copy(s, &s->hdr_info.server_response, &s->hdr_info.client_response, s->client_info.http_version);
    TRANSACT_RETURN(StateMachineAction_t::INTERNAL_100_RESPONSE, HandleResponse);
  } else {
    TRANSACT_RETURN(StateMachineAction_t::SERVER_PARSE_NEXT_HDR, HandleResponse);
  }
}

// void HttpTransact::build_response_copy
//
//   Build a response with minimal changes from the base response
//
void
HttpTransact::build_response_copy(State *s, HTTPHdr *base_response, HTTPHdr *outgoing_response, HTTPVersion outgoing_version)
{
  HttpTransactHeaders::copy_header_fields(base_response, outgoing_response, s->txn_conf->fwd_proxy_auth_to_parent, s->current.now);
  HttpTransactHeaders::convert_response(outgoing_version, outgoing_response); // http version conversion
  HttpTransactHeaders::add_server_header_to_response(s->txn_conf, outgoing_response);

  dump_header(dbg_ctl_http_hdrs, outgoing_response, s->state_machine_id(), "Proxy's Response");
}

//////////////////////////////////////////////////////////////////////////
//   IMS handling table                                                 //
//       OS = Origin Server                                             //
//       IMS = A GET request w/ an If-Modified-Since header             //
//       LMs = Last modified state returned by server                   //
//       D, D' are Last modified dates returned by the origin server    //
//          and are later used for IMS                                  //
//       D < D'                                                         //
//                                                                      //
//  +----------+-----------+----------+-----------+--------------+      //
//  | Client's | Cached    | Proxy's  |   Response to client     |      //
//  | Request  | State     | Request  +-----------+--------------+      //
//  |          |           |          | OS 200    |  OS 304      |      //
//  +==========+===========+==========+===========+==============+      //
//  |  GET     | Fresh     | N/A      |  N/A      |  N/A         |      //
//  +----------+-----------+----------+-----------+--------------+      //
//  |  GET     | Stale, D' | IMS  D'  | 200, new  | 200, cached  |      //
//  +----------+-----------+----------+-----------+--------------+      //
//  |  GET     | Stale, E  | INM  E   | 200, new  | 200, cached  |      //
//  +----------+-----------+----------+-----------+--------------+      //
//  |  INM E   | Stale, E  | INM  E   | 304       | 304          |      //
//  +----------+-----------+----------+-----------+--------------+      //
//  |  INM E + | Stale,    | INM E    | 200, new *| 304          |      //
//  |  IMS D'  | E + D'    | IMS D'   |           |              |      //
//  +----------+-----------+----------+-----------+--------------+      //
//  |  IMS D   | None      | GET      | 200, new *|  N/A         |      //
//  +----------+-----------+----------+-----------+--------------+      //
//  |  INM E   | None      | GET      | 200, new *|  N/A         |      //
//  +----------+-----------+----------+-----------+--------------+      //
//  |  IMS D   | Stale, D' | IMS D'   | 200, new  | Compare      |      //
//  |---------------------------------------------| LMs & D'     |      //
//  |  IMS D'  | Stale, D' | IMS D'   | 200, new  | If match, 304|      //
//  |---------------------------------------------| If no match, |      //
//  |  IMS D'  | Stale D   | IMS D    | 200, new *|  200, cached |      //
//  +------------------------------------------------------------+      //
//                                                                      //
//  Note: * indicates a case that could be optimized to return          //
//     304 to the client but currently is not                           //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_cache_operation_on_forward_server_response
// Description:
//
// Details    :
//
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_cache_operation_on_forward_server_response(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "(hcoofsr)");
  TxnDbg(dbg_ctl_http_seq, "Entering handle_cache_operation_on_forward_server_response");

  HTTPHdr    *base_response        = nullptr;
  HTTPStatus  server_response_code = HTTPStatus::NONE;
  HTTPStatus  client_response_code = HTTPStatus::NONE;
  const char *warn_text            = nullptr;
  bool        cacheable            = false;

  cacheable = is_response_cacheable(s, &s->hdr_info.client_request, &s->hdr_info.server_response);
  TxnDbg(dbg_ctl_http_trans, "[hcoofsr] response %s cacheable", cacheable ? "is" : "is not");

  // set the correct next action, cache action, response code, and base response

  server_response_code = s->hdr_info.server_response.status_get();
  switch (server_response_code) {
  case HTTPStatus::NOT_MODIFIED: // 304
    SET_VIA_STRING(VIA_SERVER_RESULT, VIA_SERVER_NOT_MODIFIED);

    // determine the correct cache action, next state, and response
    // precondition: s->cache_info.action should be one of the following
    // CacheAction_t::DELETE, or CacheAction_t::UPDATE; otherwise, it's an error.
    if (s->api_server_response_ignore && s->cache_info.action == CacheAction_t::UPDATE) {
      s->api_server_response_ignore = false;
      ink_assert(s->cache_info.object_read);
      base_response        = s->cache_info.object_read->response_get();
      s->cache_info.action = CacheAction_t::SERVE;
      TxnDbg(dbg_ctl_http_trans, "[hcoofsr] not merging, cache action changed to: %s",
             HttpDebugNames::get_cache_action_name(s->cache_info.action));
      s->next_action       = StateMachineAction_t::SERVE_FROM_CACHE;
      client_response_code = base_response->status_get();
    } else if ((s->cache_info.action == CacheAction_t::DELETE) || ((s->cache_info.action == CacheAction_t::UPDATE) && !cacheable)) {
      if (is_request_conditional(&s->hdr_info.client_request)) {
        client_response_code = HttpTransactCache::match_response_to_request_conditionals(
          &s->hdr_info.client_request, s->cache_info.object_read->response_get(), s->response_received_time);
      } else {
        client_response_code = HTTPStatus::OK;
      }

      if (client_response_code != HTTPStatus::OK) {
        // we can just forward the not modified response
        // from the server and delete the cached copy
        base_response        = &s->hdr_info.server_response;
        client_response_code = base_response->status_get();
        s->cache_info.action = CacheAction_t::DELETE;
        s->next_action       = StateMachineAction_t::INTERNAL_CACHE_DELETE;
      } else {
        // We got screwed. The client did not send a conditional request,
        // but we had a cached copy which we revalidated. The server has
        // now told us to delete the cached copy and sent back a 304.
        // We need to send the cached copy to the client, then delete it.
        if (s->method == HTTP_WKSIDX_HEAD) {
          s->cache_info.action = CacheAction_t::DELETE;
          s->next_action       = StateMachineAction_t::SERVER_READ;
        } else {
          // No need to worry about If-Range headers because the request isn't conditional
          if (s->hdr_info.client_request.presence(MIME_PRESENCE_RANGE)) {
            s->state_machine->do_range_setup_if_necessary();
            // Check client request range header if we cached a stealed content with cacheable=false
          }
          s->cache_info.action = CacheAction_t::SERVE_AND_DELETE;
          s->next_action       = StateMachineAction_t::SERVE_FROM_CACHE;
        }
        base_response        = s->cache_info.object_read->response_get();
        client_response_code = base_response->status_get();
      }

    } else if (s->cache_info.action == CacheAction_t::UPDATE && is_request_conditional(&s->hdr_info.server_request)) {
      // CacheAction_t::UPDATE and server response is cacheable
      if (is_request_conditional(&s->hdr_info.client_request)) {
        if (s->txn_conf->cache_when_to_revalidate != 4) {
          client_response_code = HttpTransactCache::match_response_to_request_conditionals(
            &s->hdr_info.client_request, s->cache_info.object_read->response_get(), s->response_received_time);
        } else {
          client_response_code = server_response_code;
        }
      } else {
        client_response_code = HTTPStatus::OK;
      }

      if (client_response_code != HTTPStatus::OK) {
        // delete the cached copy unless configured to always verify IMS
        if (s->txn_conf->cache_when_to_revalidate != 4) {
          s->cache_info.action = CacheAction_t::UPDATE;
          s->next_action       = StateMachineAction_t::INTERNAL_CACHE_UPDATE_HEADERS;
          /* base_response will be set after updating headers below */
        } else {
          s->cache_info.action = CacheAction_t::NO_ACTION;
          s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
          base_response        = &s->hdr_info.server_response;
        }
      } else {
        if (s->method == HTTP_WKSIDX_HEAD) {
          s->cache_info.action = CacheAction_t::UPDATE;
          s->next_action       = StateMachineAction_t::SERVER_READ;
        } else {
          auto *client_request  = &s->hdr_info.client_request;
          auto *cached_response = s->cache_info.object_read->response_get();
          if (client_request->presence(MIME_PRESENCE_RANGE) &&
              HttpTransactCache::validate_ifrange_header_if_any(client_request, cached_response)) {
            s->state_machine->do_range_setup_if_necessary();
            // Note that even if the Range request is not satisfiable, we
            // update and serve this cache. This will give a 200 response to
            // a bad client, but allows us to avoid pegging the origin (e.g. abuse).
          }
          s->cache_info.action = CacheAction_t::SERVE_AND_UPDATE;
          s->next_action       = StateMachineAction_t::SERVE_FROM_CACHE;
        }
        /* base_response will be set after updating headers below */
      }

    } else { // cache action != CacheAction_t::DELETE and != CacheAction_t::UPDATE

      // bogus response from server. deal by tunnelling to client.
      // server should not have sent back a 304 because our request
      // should not have been an conditional.
      TxnDbg(dbg_ctl_http_trans, "[hcoofsr] 304 for non-conditional request");
      s->cache_info.action = CacheAction_t::NO_ACTION;
      s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
      client_response_code = s->hdr_info.server_response.status_get();
      base_response        = &s->hdr_info.server_response;

      // since this is bad, insert warning header into client response
      // The only exception case is conditional client request,
      // cache miss, and client request being unlikely cacheable.
      // In this case, the server request is given the same
      // conditional headers as client request (see build_request()).
      // So an unexpected 304 might be received.
      // FIXME: check this case
      if (is_request_likely_cacheable(s, &s->hdr_info.client_request)) {
        warn_text = "Proxy received unexpected 304 response; "
                    "content may be stale";
      }
    }

    break;

  case HTTPStatus::HTTPVER_NOT_SUPPORTED: // 505
  {
    bool keep_alive = (s->current.server->keep_alive == HTTPKeepAlive::KEEPALIVE);

    s->next_action = how_to_open_connection(s);

    /* Downgrade the request level and retry */
    if (!HttpTransactHeaders::downgrade_request(&keep_alive, &s->hdr_info.server_request)) {
      build_error_response(s, HTTPStatus::HTTPVER_NOT_SUPPORTED, "HTTP Version Not Supported", "response#bad_version");
      s->next_action        = StateMachineAction_t::SEND_ERROR_CACHE_NOOP;
      s->already_downgraded = true;
    } else {
      if (!keep_alive) {
        /* START Hack */
        (s->hdr_info.server_request).field_delete(static_cast<std::string_view>(MIME_FIELD_PROXY_CONNECTION));
        /* END   Hack */
      }
      s->already_downgraded = true;
      s->next_action        = how_to_open_connection(s);
    }
  }
    return;

  default:
    TxnDbg(dbg_ctl_http_trans, "[hcoofsr] response code: %d", static_cast<int>(server_response_code));
    SET_VIA_STRING(VIA_SERVER_RESULT, VIA_SERVER_SERVED);
    SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_SERVED);

    /* By default, if we receive a 500, 502, 503 or 504 while revalidating
       a document, treat the response as a 304 and in effect revalidate the document for
       negative_revalidating_lifetime. (negative revalidating)
     */
    if (s->txn_conf->negative_revalidating_enabled &&
        s->txn_conf->negative_revalidating_list.contains(static_cast<int>(server_response_code)) &&
        s->cache_info.action == CacheAction_t::UPDATE && is_stale_cache_response_returnable(s)) {
      HTTPStatus cached_response_code = s->cache_info.object_read->response_get()->status_get();
      if (!(cached_response_code == HTTPStatus::INTERNAL_SERVER_ERROR || cached_response_code == HTTPStatus::GATEWAY_TIMEOUT ||
            cached_response_code == HTTPStatus::BAD_GATEWAY || cached_response_code == HTTPStatus::SERVICE_UNAVAILABLE)) {
        TxnDbg(dbg_ctl_http_trans, "[hcoofsr] negative revalidating: revalidate stale object and serve from cache");

        s->cache_info.object_store.create();
        s->cache_info.object_store.request_set(&s->hdr_info.client_request);
        s->cache_info.object_store.response_set(s->cache_info.object_read->response_get());
        base_response   = s->cache_info.object_store.response_get();
        time_t exp_time = s->txn_conf->negative_revalidating_lifetime + ink_local_time();
        base_response->set_expires(exp_time);

        SET_VIA_STRING(VIA_CACHE_FILL_ACTION, VIA_CACHE_UPDATED);
        Metrics::Counter::increment(http_rsb.cache_updates);

        // unset Cache-control: "need-revalidate-once" (if it's set)
        // This directive is used internally by T.S. to invalidate
        // documents so that an invalidated document needs to be
        // revalidated again.
        base_response->unset_cooked_cc_need_revalidate_once();

        if (is_request_conditional(&s->hdr_info.client_request) &&
            HttpTransactCache::match_response_to_request_conditionals(&s->hdr_info.client_request,
                                                                      s->cache_info.object_read->response_get(),
                                                                      s->response_received_time) == HTTPStatus::NOT_MODIFIED) {
          s->next_action       = StateMachineAction_t::INTERNAL_CACHE_UPDATE_HEADERS;
          client_response_code = HTTPStatus::NOT_MODIFIED;
        } else {
          if (s->method == HTTP_WKSIDX_HEAD) {
            s->cache_info.action = CacheAction_t::UPDATE;
            s->next_action       = StateMachineAction_t::INTERNAL_CACHE_NOOP;
          } else {
            s->cache_info.action = CacheAction_t::SERVE_AND_UPDATE;
            s->next_action       = StateMachineAction_t::SERVE_FROM_CACHE;
          }

          client_response_code = s->cache_info.object_read->response_get()->status_get();
        }

        ink_assert(base_response->valid());

        if (client_response_code == HTTPStatus::NOT_MODIFIED) {
          ink_assert(GET_VIA_STRING(VIA_CLIENT_REQUEST) != VIA_CLIENT_SIMPLE);
          SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_IMS);
          SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_NOT_MODIFIED);
        } else {
          SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_SERVED);
        }

        ink_assert(client_response_code != HTTPStatus::NONE);

        if (s->next_action == StateMachineAction_t::SERVE_FROM_CACHE && s->state_machine->do_transform_open()) {
          set_header_for_transform(s, base_response);
        } else {
          build_response(s, base_response, &s->hdr_info.client_response, s->client_info.http_version, client_response_code);
        }

        return;
      }
    }

    s->next_action       = StateMachineAction_t::SERVER_READ;
    client_response_code = server_response_code;
    base_response        = &s->hdr_info.server_response;

    s->is_cacheable_due_to_negative_caching_configuration = cacheable && is_negative_caching_appropriate(s);

    // determine the correct cache action given the original cache action,
    // cacheability of server response, and request method
    // precondition: s->cache_info.action is one of the following
    // CacheAction_t::UPDATE, CacheAction_t::WRITE, or CacheAction_t::DELETE
    int const server_request_method = s->hdr_info.server_request.method_get_wksidx();
    if (s->api_server_response_no_store) {
      s->cache_info.action = CacheAction_t::NO_ACTION;
    } else if (s->api_server_response_ignore && server_response_code == HTTPStatus::OK &&
               server_request_method == HTTP_WKSIDX_HEAD) {
      s->api_server_response_ignore = false;
      ink_assert(s->cache_info.object_read);
      base_response        = s->cache_info.object_read->response_get();
      s->cache_info.action = CacheAction_t::SERVE;
      TxnDbg(dbg_ctl_http_trans,
             "[hcoofsr] ignoring server response, "
             "cache action changed to: %s",
             HttpDebugNames::get_cache_action_name(s->cache_info.action));
      s->next_action       = StateMachineAction_t::SERVE_FROM_CACHE;
      client_response_code = base_response->status_get();
    } else if (s->cache_info.action == CacheAction_t::UPDATE) {
      if (s->www_auth_content == CacheAuth_t::FRESH || s->api_server_response_ignore) {
        s->cache_info.action = CacheAction_t::NO_ACTION;
      } else if (s->www_auth_content == CacheAuth_t::STALE && server_response_code == HTTPStatus::UNAUTHORIZED) {
        s->cache_info.action = CacheAction_t::NO_ACTION;
      } else if (!cacheable) {
        if (HttpTransactHeaders::is_status_an_error_response(server_response_code) &&
            !HttpTransactHeaders::is_method_safe(server_request_method)) {
          // Only delete the cache entry if the response is successful. For
          // unsuccessful responses, the transaction doesn't invalidate our
          // entry. This behavior complies with RFC 7234, section 4.4 which
          // stipulates that the entry only need be invalidated for non-error
          // responses:
          //
          //    A cache MUST invalidate the effective request URI (Section 5.5 of
          //    [RFC7230]) when it receives a non-error response to a request
          //    with a method whose safety is unknown.
          s->cache_info.action = CacheAction_t::NO_ACTION;
        } else {
          s->cache_info.action = CacheAction_t::DELETE;
        }
      } else if (s->method == HTTP_WKSIDX_HEAD) {
        s->cache_info.action = CacheAction_t::DELETE;
      } else {
        ink_assert(s->cache_info.object_read != nullptr);
        s->cache_info.action = CacheAction_t::REPLACE;

        auto *client_request = &s->hdr_info.client_request;
        if (client_request->presence(MIME_PRESENCE_RANGE) &&
            HttpTransactCache::validate_ifrange_header_if_any(client_request, base_response)) {
          s->state_machine->do_range_setup_if_necessary();
        }
      }

    } else if (s->cache_info.action == CacheAction_t::WRITE) {
      if (!cacheable) {
        s->cache_info.action = CacheAction_t::NO_ACTION;
      } else if (s->method == HTTP_WKSIDX_HEAD) {
        s->cache_info.action = CacheAction_t::NO_ACTION;
      } else {
        s->cache_info.action = CacheAction_t::WRITE;
        auto *client_request = &s->hdr_info.client_request;
        if (client_request->presence(MIME_PRESENCE_RANGE) &&
            HttpTransactCache::validate_ifrange_header_if_any(client_request, base_response)) {
          s->state_machine->do_range_setup_if_necessary();
        }
      }

    } else if (s->cache_info.action == CacheAction_t::DELETE) {
      if (!cacheable && HttpTransactHeaders::is_status_an_error_response(server_response_code) &&
          !HttpTransactHeaders::is_method_safe(server_request_method)) {
        // Only delete the cache entry if the response is successful. For
        // unsuccessful responses, the transaction doesn't invalidate our
        // entry. This behavior complies with RFC 7234, section 4.4 which
        // stipulates that the entry only need be invalidated for non-error
        // responses:
        //
        //    A cache MUST invalidate the effective request URI (Section 5.5 of
        //    [RFC7230]) when it receives a non-error response to a request
        //    with a method whose safety is unknown.
        s->cache_info.action = CacheAction_t::NO_ACTION;
      }

    } else {
      ink_assert(!("cache action inconsistent with current state"));
    }
    // postcondition: s->cache_info.action is one of the following
    // CacheAction_t::REPLACE, CacheAction_t::WRITE, CacheAction_t::DELETE, or
    // CacheAction_t::NO_ACTION

    // Check see if we ought to serve the client a 304 based on
    //   it's IMS date.  We may gotten a 200 back from the origin
    //   server if our (the proxies's) cached copy was out of date
    //   but the client's wasn't.  However, if the response is
    //   not cacheable we ought not issue a 304 to the client so
    //   make sure we are writing the document to the cache if
    //   before issuing a 304
    if (s->cache_info.action == CacheAction_t::WRITE || s->cache_info.action == CacheAction_t::NO_ACTION ||
        s->cache_info.action == CacheAction_t::REPLACE) {
      if (s->is_cacheable_due_to_negative_caching_configuration) {
        HTTPHdr *resp;
        s->cache_info.object_store.create();
        s->cache_info.object_store.request_set(&s->hdr_info.client_request);
        s->cache_info.object_store.response_set(&s->hdr_info.server_response);
        resp = s->cache_info.object_store.response_get();
        if (!resp->presence(MIME_PRESENCE_EXPIRES)) {
          time_t exp_time = s->txn_conf->negative_caching_lifetime + ink_local_time();

          resp->set_expires(exp_time);
        }
      } else if (is_request_conditional(&s->hdr_info.client_request) && server_response_code == HTTPStatus::OK) {
        client_response_code = HttpTransactCache::match_response_to_request_conditionals(
          &s->hdr_info.client_request, &s->hdr_info.server_response, s->response_received_time);

        TxnDbg(dbg_ctl_http_trans,
               "[hcoofsr] conditional request, 200 "
               "response, send back 304 if possible [crc=%d]",
               static_cast<int>(client_response_code));
        if ((client_response_code == HTTPStatus::NOT_MODIFIED) || (client_response_code == HTTPStatus::PRECONDITION_FAILED)) {
          switch (s->cache_info.action) {
          case CacheAction_t::WRITE:
          case CacheAction_t::REPLACE:
            s->next_action = StateMachineAction_t::INTERNAL_CACHE_WRITE;
            break;
          case CacheAction_t::DELETE:
            s->next_action = StateMachineAction_t::INTERNAL_CACHE_DELETE;
            break;
          default:
            s->next_action = StateMachineAction_t::INTERNAL_CACHE_NOOP;
            break;
          }
        } else {
          SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_SERVER_REVALIDATED);
        }
      }
    } else if (s->is_cacheable_due_to_negative_caching_configuration) {
      s->is_cacheable_due_to_negative_caching_configuration = false;
    }

    break;
  }

  // update stat, set via string, etc

  switch (s->cache_info.action) {
  case CacheAction_t::SERVE_AND_DELETE:
  // fall through
  case CacheAction_t::DELETE:
    TxnDbg(dbg_ctl_http_trans, "[hcoofsr] delete cached copy");
    SET_VIA_STRING(VIA_CACHE_FILL_ACTION, VIA_CACHE_DELETED);
    Metrics::Counter::increment(http_rsb.cache_deletes);
    break;
  case CacheAction_t::WRITE:
    TxnDbg(dbg_ctl_http_trans, "[hcoofsr] cache write");
    SET_VIA_STRING(VIA_CACHE_FILL_ACTION, VIA_CACHE_WRITTEN);
    Metrics::Counter::increment(http_rsb.cache_writes);
    break;
  case CacheAction_t::SERVE_AND_UPDATE:
  // fall through
  case CacheAction_t::UPDATE:
  // fall through
  case CacheAction_t::REPLACE:
    TxnDbg(dbg_ctl_http_trans, "[hcoofsr] cache update/replace");
    SET_VIA_STRING(VIA_CACHE_FILL_ACTION, VIA_CACHE_UPDATED);
    Metrics::Counter::increment(http_rsb.cache_updates);
    break;
  default:
    break;
  }

  if ((client_response_code == HTTPStatus::NOT_MODIFIED) && (s->cache_info.action != CacheAction_t::NO_ACTION)) {
    /* ink_assert(GET_VIA_STRING(VIA_CLIENT_REQUEST)
       != VIA_CLIENT_SIMPLE); */
    TxnDbg(dbg_ctl_http_trans, "[hcoofsr] Client request was conditional");
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_IMS);
    SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_NOT_MODIFIED);
  } else {
    SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_SERVED);
  }

  ink_assert(client_response_code != HTTPStatus::NONE);

  // The correct cache action, next action, and response code are set.
  // Do the real work below.

  // first update the cached object
  if ((s->cache_info.action == CacheAction_t::UPDATE) || (s->cache_info.action == CacheAction_t::SERVE_AND_UPDATE)) {
    TxnDbg(dbg_ctl_http_trans, "[hcoofsr] merge and update cached copy");
    merge_and_update_headers_for_cache_update(s);
    base_response = s->cache_info.object_store.response_get();
    // unset Cache-control: "need-revalidate-once" (if it's set)
    // This directive is used internally by T.S. to invalidate documents
    // so that an invalidated document needs to be revalidated again.
    base_response->unset_cooked_cc_need_revalidate_once();
    // unset warning revalidation failed header if it set
    // (potentially added by negative revalidating)
    delete_warning_value(base_response, HTTPWarningCode::REVALIDATION_FAILED);
  }
  ink_assert(base_response->valid());

  if ((s->cache_info.action == CacheAction_t::WRITE) || (s->cache_info.action == CacheAction_t::REPLACE)) {
    set_headers_for_cache_write(s, &s->cache_info.object_store, &s->hdr_info.server_request, &s->hdr_info.server_response);
  }
  // 304, 412, and 416 responses are handled here
  if ((client_response_code == HTTPStatus::NOT_MODIFIED) || (client_response_code == HTTPStatus::PRECONDITION_FAILED)) {
    // Because we are decoupling User-Agent validation from
    //  Traffic Server validation just build a regular 304
    //  if the exception of adding prepending the VIA
    //  header to show the revalidation path
    build_response(s, base_response, &s->hdr_info.client_response, s->client_info.http_version, client_response_code);

    // Copy over the response via field (if any) preserving
    //  the order of the fields
    MIMEField *resp_via = s->hdr_info.server_response.field_find(static_cast<std::string_view>(MIME_FIELD_VIA));
    if (resp_via) {
      swoc::LocalBufferWriter<HTTP_OUR_VIA_MAX_LENGTH> saved_via_w;
      MIMEField                                       *our_via;
      our_via = s->hdr_info.client_response.field_find(static_cast<std::string_view>(MIME_FIELD_VIA));
      if (our_via == nullptr) {
        our_via = s->hdr_info.client_response.field_create(static_cast<std::string_view>(MIME_FIELD_VIA));
        s->hdr_info.client_response.field_attach(our_via);
      } else {
        auto src{our_via->value_get()};
        saved_via_w.write(src.data(), src.length());
        s->hdr_info.client_response.field_value_set(our_via, ""sv, true);
      }
      // HDR FIX ME - Multiple appends are VERY slow
      while (resp_via) {
        auto cfield{resp_via->value_get()};
        s->hdr_info.client_response.field_value_append(our_via, cfield, true);
        resp_via = resp_via->m_next_dup;
      }
      if (saved_via_w.size()) {
        s->hdr_info.client_response.field_value_append(our_via, saved_via_w, true);
      }
    }
    // a warning text is added only in the case of a NOT MODIFIED response
    if (warn_text) {
      HttpTransactHeaders::insert_warning_header(s->http_config_param, &s->hdr_info.client_response, HTTPWarningCode::MISC_WARNING,
                                                 warn_text, strlen(warn_text));
    }

    dump_header(dbg_ctl_http_hdrs, &s->hdr_info.client_response, s->state_machine_id(), "Proxy's Response (Client Conditionals)");
    return;
  }
  // all other responses (not 304, 412, 416) are handled here
  else {
    if (((s->next_action == StateMachineAction_t::SERVE_FROM_CACHE) || (s->next_action == StateMachineAction_t::SERVER_READ)) &&
        s->state_machine->do_transform_open()) {
      set_header_for_transform(s, base_response);
    } else {
      build_response(s, base_response, &s->hdr_info.client_response, s->client_info.http_version, client_response_code);
    }
  }

  return;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_no_cache_operation_on_forward_server_response
// Description:
//
// Details    :
//
//
//
// Possible Next States From Here:
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_no_cache_operation_on_forward_server_response(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "(hncoofsr)");
  TxnDbg(dbg_ctl_http_seq, "Entering handle_no_cache_operation_on_forward_server_response");

  bool        keep_alive = s->current.server->keep_alive == HTTPKeepAlive::KEEPALIVE;
  const char *warn_text  = nullptr;

  switch (s->hdr_info.server_response.status_get()) {
  case HTTPStatus::OK:
    TxnDbg(dbg_ctl_http_trans, "[hncoofsr] server sent back 200");
    SET_VIA_STRING(VIA_SERVER_RESULT, VIA_SERVER_SERVED);
    SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_SERVED);
    if (s->method == HTTP_WKSIDX_CONNECT) {
      TxnDbg(dbg_ctl_http_trans, "[hncoofsr] next action is SSL_TUNNEL");
      s->next_action = StateMachineAction_t::SSL_TUNNEL;
    } else {
      TxnDbg(dbg_ctl_http_trans, "[hncoofsr] next action will be OS_READ_CACHE_NOOP");

      ink_assert(s->cache_info.action == CacheAction_t::NO_ACTION);
      s->next_action = StateMachineAction_t::SERVER_READ;
    }
    if (s->state_machine->redirect_url == nullptr) {
      s->state_machine->enable_redirection = false;
    }
    break;
  case HTTPStatus::NOT_MODIFIED:
    TxnDbg(dbg_ctl_http_trans, "[hncoofsr] server sent back 304. IMS from client?");
    SET_VIA_STRING(VIA_SERVER_RESULT, VIA_SERVER_NOT_MODIFIED);
    SET_VIA_STRING(VIA_PROXY_RESULT, VIA_PROXY_NOT_MODIFIED);

    if (!is_request_conditional(&s->hdr_info.client_request)) {
      // bogus server response. not a conditional request
      // from the client and probably not a conditional
      // request from the proxy.

      // since this is bad, insert warning header into client response
      warn_text = "Proxy received unexpected 304 response; content may be stale";
    }

    ink_assert(s->cache_info.action == CacheAction_t::NO_ACTION);
    s->next_action = StateMachineAction_t::INTERNAL_CACHE_NOOP;
    break;
  case HTTPStatus::HTTPVER_NOT_SUPPORTED:
    s->next_action = how_to_open_connection(s);

    /* Downgrade the request level and retry */
    if (!HttpTransactHeaders::downgrade_request(&keep_alive, &s->hdr_info.server_request)) {
      s->already_downgraded = true;
      build_error_response(s, HTTPStatus::HTTPVER_NOT_SUPPORTED, "HTTP Version Not Supported", "response#bad_version");
      s->next_action = StateMachineAction_t::SEND_ERROR_CACHE_NOOP;
    } else {
      s->already_downgraded = true;
      s->next_action        = how_to_open_connection(s);
    }
    return;
  case HTTPStatus::PARTIAL_CONTENT:
    // If we get this back we should be just passing it through.
    ink_assert(s->cache_info.action == CacheAction_t::NO_ACTION);
    s->next_action = StateMachineAction_t::SERVER_READ;
    break;
  default:
    TxnDbg(dbg_ctl_http_trans, "[hncoofsr] server sent back something other than 100,304,200");
    /* Default behavior is to pass-through response to the client */

    ink_assert(s->cache_info.action == CacheAction_t::NO_ACTION);
    s->next_action = StateMachineAction_t::SERVER_READ;
    break;
  }

  HTTPHdr *to_warn;
  if (s->next_action == StateMachineAction_t::SERVER_READ && s->state_machine->do_transform_open()) {
    set_header_for_transform(s, &s->hdr_info.server_response);
    to_warn = &s->hdr_info.transform_response;
  } else {
    build_response(s, &s->hdr_info.server_response, &s->hdr_info.client_response, s->client_info.http_version);
    to_warn = &s->hdr_info.server_response;
  }

  if (warn_text) {
    HttpTransactHeaders::insert_warning_header(s->http_config_param, to_warn, HTTPWarningCode::MISC_WARNING, warn_text,
                                               strlen(warn_text));
  }

  return;
}

void
HttpTransact::merge_and_update_headers_for_cache_update(State *s)
{
  URL     *s_url      = nullptr;
  HTTPHdr *cached_hdr = nullptr;

  if (!s->cache_info.object_store.valid()) {
    s->cache_info.object_store.create();
  }

  s->cache_info.object_store.request_set(&s->hdr_info.server_request);
  cached_hdr = s->cache_info.object_store.response_get();

  if (s->redirect_info.redirect_in_process) {
    s_url = &s->redirect_info.original_url;
  } else {
    s_url = &s->cache_info.original_url;
  }
  ink_assert(s_url != nullptr);

  s->cache_info.object_store.request_get()->url_set(s_url->valid() ? s_url : s->hdr_info.client_request.url_get());

  if (s->cache_info.object_store.request_get()->method_get_wksidx() == HTTP_WKSIDX_HEAD) {
    s->cache_info.object_store.request_get()->method_set(static_cast<std::string_view>(HTTP_METHOD_GET));
  }

  if (s->api_modifiable_cached_resp) {
    ink_assert(cached_hdr != nullptr && cached_hdr->valid());
    s->api_modifiable_cached_resp = false;
  } else {
    s->cache_info.object_store.response_set(s->cache_info.object_read->response_get());
  }

  // Delete caching headers from the cached response. If these are
  // still being served by the origin we will copy new versions in
  // from the server response. RFC 2616 says that a 304 response may
  // omit some headers if they were sent in a 200 response (see section
  // 10.3.5), but RFC 7232) is clear that the 304 and 200 responses
  // must be identical (see section 4.1). This code attempts to strike
  // a balance between the two.
  cached_hdr->field_delete(static_cast<std::string_view>(MIME_FIELD_AGE));
  cached_hdr->field_delete(static_cast<std::string_view>(MIME_FIELD_ETAG));
  cached_hdr->field_delete(static_cast<std::string_view>(MIME_FIELD_EXPIRES));

  merge_response_header_with_cached_header(cached_hdr, &s->hdr_info.server_response);

  // Some special processing for 304
  if (s->hdr_info.server_response.status_get() == HTTPStatus::NOT_MODIFIED) {
    // Hack fix. If the server sends back
    // a 304 without a Date Header, use the current time
    // as the new Date value in the header to be cached.
    time_t date_value = s->hdr_info.server_response.get_date();

    if (date_value <= 0) {
      cached_hdr->set_date(s->request_sent_time);
      date_value = s->request_sent_time;
    }

    // If the cached response has an Age: we should update it
    // We could use calculate_document_age but my guess is it's overkill
    // Just use 'now' - 304's Date: + Age: (response's Age: if there)
    date_value = std::max(s->current.now - date_value, static_cast<ink_time_t>(0));
    if (s->hdr_info.server_response.presence(MIME_PRESENCE_AGE)) {
      time_t new_age = s->hdr_info.server_response.get_age();

      if (new_age >= 0) {
        cached_hdr->set_age(date_value + new_age);
      } else {
        cached_hdr->set_age(-1); // Overflow
      }
    }

    delete_warning_value(cached_hdr, HTTPWarningCode::REVALIDATION_FAILED);
  }

  s->cache_info.object_store.request_get()->field_delete(static_cast<std::string_view>(MIME_FIELD_VIA));
}

void
HttpTransact::handle_transform_cache_write(State *s)
{
  ink_assert(s->cache_info.transform_action == CacheAction_t::PREPARE_TO_WRITE);

  switch (s->cache_info.write_lock_state) {
  case CacheWriteLock_t::SUCCESS:
    // We were able to get the lock for the URL vector in the cache
    s->cache_info.transform_action = CacheAction_t::WRITE;
    break;
  case CacheWriteLock_t::FAIL:
    // No write lock, ignore the cache
    s->cache_info.transform_action       = CacheAction_t::NO_ACTION;
    s->cache_info.transform_write_status = CacheWriteStatus_t::LOCK_MISS;
    break;
  default:
    ink_release_assert(0);
  }

  TRANSACT_RETURN(StateMachineAction_t::TRANSFORM_READ, nullptr);
}

void
HttpTransact::handle_transform_ready(State *s)
{
  ink_assert(s->hdr_info.transform_response.valid() == true);

  s->pre_transform_source = s->source;
  s->source               = Source_t::TRANSFORM;

  dump_header(dbg_ctl_http_hdrs, &s->hdr_info.transform_response, s->state_machine_id(), "Header From Transform");

  build_response(s, &s->hdr_info.transform_response, &s->hdr_info.client_response, s->client_info.http_version);

  if (s->cache_info.action != CacheAction_t::NO_ACTION && s->cache_info.action != CacheAction_t::DELETE &&
      s->api_info.cache_transformed && s->range_setup == HttpTransact::RangeSetup_t::NONE) {
    HTTPHdr *transform_store_request = nullptr;
    switch (s->pre_transform_source) {
    case Source_t::CACHE:
      // If we are transforming from the cache, treat
      //  the transform as if it were virtual server
      //  use in the incoming request
      transform_store_request = &s->hdr_info.client_request;
      break;
    case Source_t::HTTP_ORIGIN_SERVER:
      transform_store_request = &s->hdr_info.server_request;
      break;
    default:
      ink_release_assert(0);
    }
    ink_assert(transform_store_request->valid() == true);
    set_headers_for_cache_write(s, &s->cache_info.transform_store, transform_store_request, &s->hdr_info.transform_response);

    // For debugging
    if (is_action_tag_set("http_nullt")) {
      s->cache_info.transform_store.request_get()->value_set("InkXform"sv, "nullt"sv);
      s->cache_info.transform_store.response_get()->value_set("InkXform"sv, "nullt"sv);
    }

    s->cache_info.transform_action = CacheAction_t::PREPARE_TO_WRITE;
    TRANSACT_RETURN(StateMachineAction_t::CACHE_ISSUE_WRITE_TRANSFORM, handle_transform_cache_write);
  } else {
    s->cache_info.transform_action = CacheAction_t::NO_ACTION;
    TRANSACT_RETURN(StateMachineAction_t::TRANSFORM_READ, nullptr);
  }
}

void
HttpTransact::set_header_for_transform(State *s, HTTPHdr *base_header)
{
  s->hdr_info.transform_response.create(HTTPType::RESPONSE);
  s->hdr_info.transform_response.copy(base_header);

  // Nuke the content length since 1) the transform will probably
  //   change it.  2) it would only be valid for the first transform
  //   in the chain
  s->hdr_info.transform_response.field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_LENGTH));

  dump_header(dbg_ctl_http_hdrs, &s->hdr_info.transform_response, s->state_machine_id(), "Header To Transform");
}

void
HttpTransact::set_headers_for_cache_write(State *s, HTTPInfo *cache_info, HTTPHdr *request, HTTPHdr *response)
{
  URL *temp_url;
  ink_assert(request->type_get() == HTTPType::REQUEST);
  ink_assert(response->type_get() == HTTPType::RESPONSE);

  if (!cache_info->valid()) {
    cache_info->create();
  }

  /* Store the requested URI */
  //  Nasty hack. The set calls for
  //  marshalled types current do handle something being
  //  set to itself.  Make the check here for that case.
  //  Why the request url is set before a copy made is
  //  quite beyond me.  Seems like a unsafe practice so
  //  FIX ME!

  // Logic added to restore the original URL for multiple cache lookup
  // and automatic redirection
  if (s->redirect_info.redirect_in_process) {
    temp_url = &s->redirect_info.original_url;
    ink_assert(temp_url->valid());
    request->url_set(temp_url);
  } else if ((temp_url = &(s->cache_info.original_url))->valid()) {
    request->url_set(temp_url);
  } else if (request != &s->hdr_info.client_request) {
    request->url_set(s->hdr_info.client_request.url_get());
  }
  cache_info->request_set(request);
  /* Why do we check the negative caching case? No one knows. This used to assert if the cache_info
     response wasn't already valid, which broke negative caching when a transform is active. Why it
     wasn't OK to pull in the @a response explicitly passed in isn't clear and looking at the call
     sites yields no insight. So the assert is removed and we keep the behavior that if the response
     in @a cache_info is already set, we don't override it.
  */
  if (!s->is_cacheable_due_to_negative_caching_configuration || !cache_info->response_get()->valid()) {
    cache_info->response_set(response);
  }

  if (s->api_server_request_body_set) {
    cache_info->request_get()->method_set(static_cast<std::string_view>(HTTP_METHOD_GET));
  }

  // Set-Cookie should not be put in the cache to prevent
  //  sending person A's cookie to person B
  cache_info->response_get()->field_delete(static_cast<std::string_view>(MIME_FIELD_SET_COOKIE));
  cache_info->request_get()->field_delete(static_cast<std::string_view>(MIME_FIELD_VIA));
  // server 200 Ok for Range request
  cache_info->request_get()->field_delete(static_cast<std::string_view>(MIME_FIELD_RANGE));

  // If we're ignoring auth, then we don't want to cache WWW-Auth headers
  if (s->txn_conf->cache_ignore_auth) {
    cache_info->response_get()->field_delete(static_cast<std::string_view>(MIME_FIELD_WWW_AUTHENTICATE));
  }

  dump_header(dbg_ctl_http_hdrs, cache_info->request_get(), s->state_machine_id(), "Cached Request Hdr");
}

void
HttpTransact::merge_response_header_with_cached_header(HTTPHdr *cached_header, HTTPHdr *response_header)
{
  MIMEField *new_field;
  bool       dups_seen = false;

  for (auto spot = response_header->begin(), limit = response_header->end(); spot != limit; ++spot) {
    MIMEField &field{*spot};
    auto       name{field.name_get()};

    ///////////////////////////
    // is hop-by-hop header? //
    ///////////////////////////
    if (HttpTransactHeaders::is_this_a_hop_by_hop_header(name.data())) {
      continue;
    }
    /////////////////////////////////////
    // dont cache content-length field  and transfer encoding //
    /////////////////////////////////////
    if (name.data() == MIME_FIELD_CONTENT_LENGTH.c_str() || name.data() == MIME_FIELD_TRANSFER_ENCODING.c_str()) {
      continue;
    }
    /////////////////////////////////////
    // dont cache Set-Cookie headers   //
    /////////////////////////////////////
    if (name.data() == MIME_FIELD_SET_COOKIE.c_str()) {
      continue;
    }
    /////////////////////////////////////////
    // dont overwrite the cached content   //
    //   type as this wreaks havoc with    //
    //   transformed content               //
    /////////////////////////////////////////
    if (name.data() == MIME_FIELD_CONTENT_TYPE.c_str()) {
      continue;
    }
    /////////////////////////////////////
    // dont delete warning.  a separate//
    //  functions merges the two in a  //
    //  complex manner                 //
    /////////////////////////////////////
    if (name.data() == MIME_FIELD_WARNING.c_str()) {
      continue;
    }
    // Copy all remaining headers with replacement

    // Duplicate header fields cause a bug problem
    //   since we need to duplicate with replacement.
    //   Without dups, we can just nuke what is already
    //   there in the cached header.  With dups, we
    //   can't do this because what is already there
    //   may be a dup we've already copied in.  If
    //   dups show up we look through the remaining
    //   header fields in the new response, nuke
    //   them in the cached response and then add in
    //   the remaining fields one by one from the
    //   response header
    //
    if (field.m_next_dup) {
      if (dups_seen == false) {
        // use a second iterator to delete the
        // remaining response headers in the cached response,
        // so that they will be added in the next iterations.
        for (auto spot2 = spot; spot2 != limit; ++spot2) {
          MIMEField &field2{*spot2};
          auto       name2{field2.name_get()};

          // It is specified above that content type should not
          // be altered here however when a duplicate header
          // is present, all headers following are delete and
          // re-added back. This includes content type if it follows
          // any duplicate header. This leads to the loss of
          // content type in the client response.
          // This ensures that it is not altered when duplicate
          // headers are present.
          if (name2.data() == MIME_FIELD_CONTENT_TYPE.c_str()) {
            continue;
          }
          cached_header->field_delete(name2);
        }
        dups_seen = true;
      }
    }

    auto value{field.value_get()};

    if (dups_seen == false) {
      cached_header->value_set(name, value);
    } else {
      new_field = cached_header->field_create(name);
      cached_header->field_attach(new_field);
      cached_header->field_value_set(new_field, value);
    }
  }

  merge_warning_header(cached_header, response_header);

  Dbg(dbg_ctl_http_hdr_space, "Merged response header with %d dead bytes", cached_header->m_heap->m_lost_string_space);
}

void
HttpTransact::merge_warning_header(HTTPHdr *cached_header, HTTPHdr *response_header)
{
  //  The plan:
  //
  //    1) The cached header has it's warning codes untouched
  //         since merge_response_header_with_cached_header()
  //         doesn't deal with warning headers.
  //    2) If there are 1xx warning codes in the cached
  //         header, they need to be removed.  Removal
  //         is difficult since the hdrs don't comma
  //         separate values, so build up a new header
  //         piecemeal.  Very slow but shouldn't happen
  //         very often
  //    3) Since we keep the all the warning codes from
  //         the response header, append if to
  //         the cached header
  //
  MIMEField  *c_warn    = cached_header->field_find(static_cast<std::string_view>(MIME_FIELD_WARNING));
  MIMEField  *r_warn    = response_header->field_find(static_cast<std::string_view>(MIME_FIELD_WARNING));
  MIMEField  *new_cwarn = nullptr;
  int         move_warn_len;
  const char *move_warn;

  // Loop over the cached warning header and transfer all non 1xx
  //   warning values to a new header
  if (c_warn) {
    HdrCsvIter csv;

    move_warn = csv.get_first(c_warn, &move_warn_len);
    while (move_warn) {
      int code = ink_atoi(move_warn, move_warn_len);
      if (code < 100 || code > 199) {
        bool first_move;
        if (!new_cwarn) {
          new_cwarn  = cached_header->field_create();
          first_move = true;
        } else {
          first_move = false;
        }
        cached_header->field_value_append(
          new_cwarn, std::string_view{move_warn, static_cast<std::string_view::size_type>(move_warn_len)}, !first_move);
      }

      move_warn = csv.get_next(&move_warn_len);
    }

    // At this point we can nuke the old warning headers
    cached_header->field_delete(static_cast<std::string_view>(MIME_FIELD_WARNING));

    // Add in the new header if it has anything in it
    if (new_cwarn) {
      new_cwarn->name_set(cached_header->m_heap, cached_header->m_mime, static_cast<std::string_view>(MIME_FIELD_WARNING));
      cached_header->field_attach(new_cwarn);
    }
  }
  // Loop over all the dups in the response warning header and append
  //  them one by one on to the cached warning header
  while (r_warn) {
    auto move_warn_sv{r_warn->value_get()};

    if (new_cwarn) {
      cached_header->field_value_append(new_cwarn, move_warn_sv, true);
    } else {
      new_cwarn = cached_header->field_create(static_cast<std::string_view>(MIME_FIELD_WARNING));
      cached_header->field_attach(new_cwarn);
      cached_header->field_value_set(new_cwarn, move_warn_sv);
    }

    r_warn = r_warn->m_next_dup;
  }
}

////////////////////////////////////////////////////////
// Set the keep-alive and version flags for later use //
// in request construction                            //
// this is also used when opening a connection to     //
// the origin server, and search_keepalive_to().      //
////////////////////////////////////////////////////////
bool
HttpTransact::get_ka_info_from_config(State *s, ConnectionAttributes *server_info)
{
  bool check_hostdb = false;

  if (server_info->http_version > HTTP_0_9) {
    TxnDbg(dbg_ctl_http_trans, "version already set server_info->http_version %d.%d", server_info->http_version.get_major(),
           server_info->http_version.get_minor());
    return false;
  }
  switch (static_cast<HttpConfigParams::SendHttp11>(s->txn_conf->send_http11_requests)) {
  case HttpConfigParams::SendHttp11::NEVER:
    server_info->http_version = HTTP_1_0;
    break;
  case HttpConfigParams::SendHttp11::UPGRADE_HOSTDB:
    server_info->http_version = HTTP_1_0;
    check_hostdb              = true;
    break;
  case HttpConfigParams::SendHttp11::IF_REQUEST_11_AND_HOSTDB:
    server_info->http_version = HTTP_1_0;
    if (s->hdr_info.client_request.version_get() == HTTP_1_1) {
      // check hostdb only if client req is http/1.1
      check_hostdb = true;
    }
    break;
  default:
    // The default is the "1" config, SendHttp11::ALWAYS, but assert in debug builds since we shouldn't be here
    ink_assert(0);
  // fallthrough
  case HttpConfigParams::SendHttp11::ALWAYS:
    server_info->http_version = HTTP_1_1;
    break;
  }
  TxnDbg(dbg_ctl_http_trans, "server_info->http_version %d.%d, check_hostdb %d", server_info->http_version.get_major(),
         server_info->http_version.get_minor(), check_hostdb);

  // Set keep_alive info based on the records.yaml setting
  server_info->keep_alive = s->txn_conf->keep_alive_enabled_out ? HTTPKeepAlive::KEEPALIVE : HTTPKeepAlive::NO_KEEPALIVE;

  return check_hostdb;
}

////////////////////////////////////////////////////////
// Set the keep-alive and version flags for later use //
// in request construction                            //
// this is also used when opening a connection to     //
// the origin server, and search_keepalive_to().      //
////////////////////////////////////////////////////////
void
HttpTransact::get_ka_info_from_host_db(State *s, ConnectionAttributes                                  *server_info,
                                       ConnectionAttributes * /* client_info ATS_UNUSED */, HostDBInfo *host_db_info)
{
  bool force_http11     = false;
  bool http11_if_hostdb = false;

  switch (static_cast<HttpConfigParams::SendHttp11>(s->txn_conf->send_http11_requests)) {
  case HttpConfigParams::SendHttp11::NEVER:
    // No need to do anything since above vars
    //   are defaulted false
    break;
  case HttpConfigParams::SendHttp11::UPGRADE_HOSTDB:
    http11_if_hostdb = true;
    break;
  case HttpConfigParams::SendHttp11::IF_REQUEST_11_AND_HOSTDB:
    if (s->hdr_info.client_request.version_get() == HTTP_1_1) {
      http11_if_hostdb = true;
    }
    break;
  default:
    // The default is the "1" config, SendHttp11::ALWAYS, but assert in debug builds since we shouldn't be here
    ink_assert(0);
  // fallthrough
  case HttpConfigParams::SendHttp11::ALWAYS:
    force_http11 = true;
    break;
  }

  if (force_http11 == true || (http11_if_hostdb == true && host_db_info->http_version == HTTP_1_1)) {
    server_info->http_version = HTTP_1_1;
    server_info->keep_alive   = HTTPKeepAlive::KEEPALIVE;
  } else if (host_db_info->http_version == HTTP_1_0) {
    server_info->http_version = HTTP_1_0;
    server_info->keep_alive   = HTTPKeepAlive::KEEPALIVE;
  } else if (host_db_info->http_version == HTTP_0_9) {
    server_info->http_version = HTTP_0_9;
    server_info->keep_alive   = HTTPKeepAlive::NO_KEEPALIVE;
  } else {
    //////////////////////////////////////////////
    // not set yet for this host. set defaults. //
    //////////////////////////////////////////////
    server_info->http_version  = HTTP_1_0;
    server_info->keep_alive    = HTTPKeepAlive::KEEPALIVE;
    host_db_info->http_version = HTTP_1_0;
  }

  /////////////////////////////
  // origin server keep_alive //
  /////////////////////////////
  if (!s->txn_conf->keep_alive_enabled_out) {
    server_info->keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  }

  return;
}

void
HttpTransact::add_client_ip_to_outgoing_request(State *s, HTTPHdr *request)
{
  char   ip_string[INET6_ADDRSTRLEN + 1] = {'\0'};
  size_t ip_string_size                  = 0;

  if (!ats_is_ip(&s->client_info.src_addr.sa)) {
    return;
  }

  // Always prepare the IP string.
  if (ats_ip_ntop(&s->client_info.src_addr.sa, ip_string, sizeof(ip_string)) != nullptr) {
    ip_string_size += strlen(ip_string);
  } else {
    // Failure, omg
    ip_string_size = 0;
    ip_string[0]   = 0;
  }

  // Check to see if the ip_string has been set
  if (ip_string_size == 0) {
    return;
  }

  // if we want client-ip headers, and there isn't one, add one
  if (!s->txn_conf->anonymize_remove_client_ip) {
    switch (s->txn_conf->anonymize_insert_client_ip) {
    case 1: { // Insert the client-ip, but only if the UA did not send one
      bool client_ip_set = request->presence(MIME_PRESENCE_CLIENT_IP);
      TxnDbg(dbg_ctl_http_trans, "client_ip_set = %d", client_ip_set);

      if (client_ip_set == true) {
        break;
      }
    }

    // FALL-THROUGH
    case 2: // Always insert the client-ip
      request->value_set(static_cast<std::string_view>(MIME_FIELD_CLIENT_IP),
                         std::string_view{ip_string, static_cast<std::string_view::size_type>(ip_string_size)});
      TxnDbg(dbg_ctl_http_trans, "inserted request header 'Client-ip: %s'", ip_string);
      break;

    default: // don't insert client-ip
      break;
    }
  }

  // Add or append to the X-Forwarded-For header
  if (s->txn_conf->insert_squid_x_forwarded_for) {
    request->value_append_or_set(static_cast<std::string_view>(MIME_FIELD_X_FORWARDED_FOR),
                                 std::string_view{ip_string, ip_string_size});
    TxnDbg(dbg_ctl_http_trans, "Appended connecting client's (%s) to the X-Forwards header", ip_string);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : check_request_validity()
// Description: checks to see if incoming request has necessary fields
//
// Input      : State, header (can we do this without the state?)
// Output     : enum RequestError_t of the error type, if any
//
// Details    :
//
//
///////////////////////////////////////////////////////////////////////////////
HttpTransact::RequestError_t
HttpTransact::check_request_validity(State *s, HTTPHdr *incoming_hdr)
{
  // Called also on receiving request.  Not sure if we need to call this again in case
  // the transfer-encoding and content-length headers changed
  set_client_request_state(s, incoming_hdr);
  if (incoming_hdr == nullptr) {
    return RequestError_t::NON_EXISTANT_REQUEST_HEADER;
  }

  if (!(HttpTransactHeaders::is_request_proxy_authorized(incoming_hdr))) {
    return RequestError_t::FAILED_PROXY_AUTHORIZATION;
  }

  URL *incoming_url = incoming_hdr->url_get();
  auto hostname{incoming_hdr->host_get()};
  auto hostname_len{static_cast<int>(hostname.length())};

  if (hostname.empty()) {
    return RequestError_t::MISSING_HOST_FIELD;
  }

  if (hostname_len >= MAXDNAME || hostname_len <= 0 || memchr(hostname.data(), '\0', hostname_len)) {
    return RequestError_t::BAD_HTTP_HEADER_SYNTAX;
  }

  int scheme = incoming_url->scheme_get_wksidx();
  int method = incoming_hdr->method_get_wksidx();

  if (!((scheme == URL_WKSIDX_HTTP) && (method == HTTP_WKSIDX_GET))) {
    if (scheme != URL_WKSIDX_HTTP && scheme != URL_WKSIDX_HTTPS && method != HTTP_WKSIDX_CONNECT &&
        !((scheme == URL_WKSIDX_WS || scheme == URL_WKSIDX_WSS) && s->is_websocket)) {
      if (scheme < 0) {
        return RequestError_t::NO_REQUEST_SCHEME;
      } else {
        return RequestError_t::SCHEME_NOT_SUPPORTED;
      }
    }

    if (!HttpTransactHeaders::is_this_method_supported(scheme, method)) {
      return RequestError_t::METHOD_NOT_SUPPORTED;
    }
    if ((method == HTTP_WKSIDX_CONNECT) && !s->transparent_passthrough &&
        (!is_port_in_range(incoming_hdr->url_get()->port_get(), s->http_config_param->connect_ports))) {
      TxnDbg(dbg_ctl_http_trans, "Rejected a CONNECT to port %d not in connect_ports", incoming_hdr->url_get()->port_get());
      return RequestError_t::BAD_CONNECT_PORT;
    }

    if (s->client_info.transfer_encoding == TransferEncoding_t::CHUNKED && incoming_hdr->version_get() < HTTP_1_1) {
      // Per spec, Transfer-Encoding is only supported in HTTP/1.1. For earlier
      // versions, we must reject Transfer-Encoding rather than interpret it
      // since downstream proxies may ignore the chunk header and rely upon the
      // Content-Length, or interpret the body some other way. These
      // differences in interpretation may open up the door to compatibility
      // issues. To protect against this, we reply with a 4xx if the client
      // uses Transfer-Encoding with HTTP versions that do not support it.
      return RequestError_t::UNACCEPTABLE_TE_REQUIRED;
    }

    // Require Content-Length/Transfer-Encoding for POST/PUSH/PUT
    if ((scheme == URL_WKSIDX_HTTP || scheme == URL_WKSIDX_HTTPS) &&
        (method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUSH || method == HTTP_WKSIDX_PUT) &&
        s->client_info.transfer_encoding != TransferEncoding_t::CHUNKED) {
      // In normal operation there will always be a get_ua_txn() at this point, but in one of the -R1  regression tests a request is
      // createdindependent of a transaction and this method is called, so we must null check
      if (!s->state_machine->get_ua_txn() || s->state_machine->get_ua_txn()->is_chunked_encoding_supported()) {
        // See if we need to insert a chunked header
        if (!incoming_hdr->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
          if (s->txn_conf->post_check_content_length_enabled) {
            return RequestError_t::NO_POST_CONTENT_LENGTH;
          } else {
            // Stuff in a TE setting so we treat this as chunked, sort of.
            s->client_info.transfer_encoding = HttpTransact::TransferEncoding_t::CHUNKED;
            incoming_hdr->value_append(static_cast<std::string_view>(MIME_FIELD_TRANSFER_ENCODING),
                                       static_cast<std::string_view>(HTTP_VALUE_CHUNKED), true);
          }
        }
        if (HTTP_UNDEFINED_CL == s->hdr_info.request_content_length) {
          return RequestError_t::INVALID_POST_CONTENT_LENGTH;
        }
      }
    }
  }
  // Check whether a Host header field is missing in the request.
  if (!incoming_hdr->presence(MIME_PRESENCE_HOST) && incoming_hdr->version_get() != HTTP_0_9) {
    // Update the number of incoming 1.0 or 1.1 requests that do
    // not contain Host header fields.
    Metrics::Counter::increment(http_rsb.missing_host_hdr);
  }
  // Did the client send a "TE: identity;q=0"? We have to respond
  // with an error message because we only support identity
  // Transfer Encoding.

  if (incoming_hdr->presence(MIME_PRESENCE_TE)) {
    MIMEField *te_field = incoming_hdr->field_find(static_cast<std::string_view>(MIME_FIELD_TE));
    HTTPValTE *te_val;

    if (te_field) {
      HdrCsvIter  csv_iter;
      int         te_raw_len;
      const char *te_raw = csv_iter.get_first(te_field, &te_raw_len);

      while (te_raw) {
        te_val = http_parse_te(te_raw, te_raw_len, &s->arena);
        if (te_val->encoding == HTTP_VALUE_IDENTITY.c_str()) {
          if (te_val->qvalue <= 0.0) {
            s->arena.free(te_val, sizeof(HTTPValTE));
            return RequestError_t::UNACCEPTABLE_TE_REQUIRED;
          }
        }
        s->arena.free(te_val, sizeof(HTTPValTE));
        te_raw = csv_iter.get_next(&te_raw_len);
      }
    }
  }

  return RequestError_t::NO_REQUEST_HEADER_ERROR;
}

void
HttpTransact::set_client_request_state(State *s, HTTPHdr *incoming_hdr)
{
  if (incoming_hdr == nullptr) {
    return;
  }

  // Set transfer_encoding value
  if (incoming_hdr->presence(MIME_PRESENCE_TRANSFER_ENCODING)) {
    MIMEField *field = incoming_hdr->field_find(static_cast<std::string_view>(MIME_FIELD_TRANSFER_ENCODING));
    if (field) {
      HdrCsvIter  enc_val_iter;
      int         enc_val_len;
      const char *enc_value = enc_val_iter.get_first(field, &enc_val_len);

      while (enc_value) {
        const char *wks_value = hdrtoken_string_to_wks(enc_value, enc_val_len);
        if (wks_value == HTTP_VALUE_CHUNKED.c_str()) {
          s->client_info.transfer_encoding = TransferEncoding_t::CHUNKED;
          break;
        }
        enc_value = enc_val_iter.get_next(&enc_val_len);
      }
    }
  }

  /////////////////////////////////////////////////////
  // get request content length                      //
  // To avoid parsing content-length twice, we set   //
  // s->hdr_info.request_content_length here rather  //
  // than in initialize_state_variables_from_request //
  /////////////////////////////////////////////////////
  if (incoming_hdr->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
    s->hdr_info.request_content_length = incoming_hdr->get_content_length();
  } else {
    s->hdr_info.request_content_length = HTTP_UNDEFINED_CL; // content length less than zero is invalid
  }

  TxnDbg(dbg_ctl_http_trans, "set req cont length to %" PRId64, s->hdr_info.request_content_length);
}

HttpTransact::ResponseError_t
HttpTransact::check_response_validity(State *s, HTTPHdr *incoming_hdr)
{
  ink_assert(s->next_hop_scheme == URL_WKSIDX_HTTP || s->next_hop_scheme == URL_WKSIDX_HTTPS ||
             s->next_hop_scheme == URL_WKSIDX_TUNNEL);

  if (incoming_hdr == nullptr) {
    return ResponseError_t::NON_EXISTANT_RESPONSE_HEADER;
  }

  if (incoming_hdr->type_get() != HTTPType::RESPONSE) {
    return ResponseError_t::NOT_A_RESPONSE_HEADER;
  }

  HTTPStatus incoming_status = incoming_hdr->status_get();
  if (incoming_status == HTTPStatus::NONE) {
    return ResponseError_t::MISSING_STATUS_CODE;
  }

  if (incoming_status == HTTPStatus::INTERNAL_SERVER_ERROR) {
    return ResponseError_t::STATUS_CODE_SERVER_ERROR;
  }

  if (!incoming_hdr->presence(MIME_PRESENCE_DATE)) {
    incoming_hdr->set_date(s->current.now);
  }

#ifdef REALLY_NEED_TO_CHECK_DATE_VALIDITY

  if (incoming_hdr->presence(MIME_PRESENCE_DATE)) {
    time_t date_value = incoming_hdr->get_date();
    if (date_value <= 0) {
      TxnDbg(dbg_ctl_http_trans, "Bogus date in response");
      return ResponseError_t::BOGUS_OR_NO_DATE_IN_RESPONSE;
    }
  } else {
    TxnDbg(dbg_ctl_http_trans, "No date in response");
    return ResponseError_t::BOGUS_OR_NO_DATE_IN_RESPONSE;
  }
#endif

  return ResponseError_t::NO_RESPONSE_HEADER_ERROR;
}

bool
HttpTransact::handle_trace_and_options_requests(State *s, HTTPHdr *incoming_hdr)
{
  ink_assert(incoming_hdr->type_get() == HTTPType::REQUEST);

  // This only applies to TRACE and OPTIONS
  if ((s->method != HTTP_WKSIDX_TRACE) && (s->method != HTTP_WKSIDX_OPTIONS)) {
    return false;
  }

  // If there is no Max-Forwards request header, just return false.
  if (!incoming_hdr->presence(MIME_PRESENCE_MAX_FORWARDS)) {
    // Trace and Options requests should not be looked up in cache.
    // s->cache_info.action = CacheAction_t::NO_ACTION;
    s->current.mode = ProxyMode_t::TUNNELLING;
    Metrics::Counter::increment(http_rsb.tunnels);
    return false;
  }

  int max_forwards = incoming_hdr->get_max_forwards();
  if (max_forwards <= 0) {
    //////////////////////////////////////////////
    // if max-forward is 0 the request must not //
    // be forwarded to the origin server.       //
    //////////////////////////////////////////////
    TxnDbg(dbg_ctl_http_trans, "[handle_trace] max-forwards: 0, building response...");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_response(s, &s->hdr_info.client_response, s->client_info.http_version, HTTPStatus::OK);

    ////////////////////////////////////////
    // if method is trace we should write //
    // the request header as the body.    //
    ////////////////////////////////////////
    if (s->method == HTTP_WKSIDX_TRACE) {
      TxnDbg(dbg_ctl_http_trans, "[handle_trace] inserting request in body.");
      int req_length = incoming_hdr->length_get();
      HTTP_RELEASE_ASSERT(req_length > 0);

      s->free_internal_msg_buffer();
      s->internal_msg_buffer_size = req_length * 2;

      if (s->internal_msg_buffer_size <= BUFFER_SIZE_FOR_INDEX(s->http_config_param->max_msg_iobuf_index)) {
        s->internal_msg_buffer_fast_allocator_size =
          buffer_size_to_index(s->internal_msg_buffer_size, s->http_config_param->max_msg_iobuf_index);
        s->internal_msg_buffer = static_cast<char *>(ioBufAllocator[s->internal_msg_buffer_fast_allocator_size].alloc_void());
      } else {
        s->internal_msg_buffer_fast_allocator_size = -1;
        s->internal_msg_buffer                     = static_cast<char *>(ats_malloc(s->internal_msg_buffer_size));
      }

      // clear the stupid buffer
      memset(s->internal_msg_buffer, '\0', s->internal_msg_buffer_size);

      int offset = 0;
      int used   = 0;
      int done;
      done = incoming_hdr->print(s->internal_msg_buffer, s->internal_msg_buffer_size, &used, &offset);
      HTTP_RELEASE_ASSERT(done);
      s->internal_msg_buffer_size = used;
      s->internal_msg_buffer_type = ats_strdup("message/http");

      s->hdr_info.client_response.set_content_length(used);
    } else {
      // For OPTIONS request insert supported methods in ALLOW field
      TxnDbg(dbg_ctl_http_trans, "[handle_options] inserting methods in Allow.");
      HttpTransactHeaders::insert_supported_methods_in_response(&s->hdr_info.client_response, s->scheme);
    }
    return true;
  } else { /* max-forwards != 0 */

    // Logically want to make sure max_forwards is a legitimate non-zero non-negative integer
    // Since max_forwards is a signed integer, no sense making sure it is less than INT_MAX.
    // Would be negative in that case.  Already checked negative in the other case.  Noted by coverity

    --max_forwards;
    TxnDbg(dbg_ctl_http_trans, "[handle_trace_options] Decrementing max_forwards to %d", max_forwards);
    incoming_hdr->set_max_forwards(max_forwards);

    // Trace and Options requests should not be looked up in cache.
    // s->cache_info.action = CacheAction_t::NO_ACTION;
    s->current.mode = ProxyMode_t::TUNNELLING;
    Metrics::Counter::increment(http_rsb.tunnels);
  }

  return false;
}

void
HttpTransact::bootstrap_state_variables_from_request(State *s, HTTPHdr *incoming_request)
{
  s->current.now = s->client_request_time = ink_local_time();
  s->client_info.http_version             = incoming_request->version_get();
}

void
HttpTransact::initialize_state_variables_from_request(State *s, HTTPHdr *obsolete_incoming_request)
{
  HTTPHdr *incoming_request = &s->hdr_info.client_request;

  // Temporary, until we're confident that the second argument is redundant.
  ink_assert(incoming_request == obsolete_incoming_request);

  auto host_name{incoming_request->host_get()};

  // check if the request is conditional (IMS or INM)
  if (incoming_request->presence(MIME_PRESENCE_IF_MODIFIED_SINCE | MIME_PRESENCE_IF_NONE_MATCH)) {
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_IMS);
  } else {
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_SIMPLE);
  }

  // Is the user agent Keep-Alive?
  //  If we are transparent or if the user-agent is following
  //  the 1.1 spec, we will see a "Connection" header to
  //  indicate a keep-alive.  However most user-agents including
  //  MSIE3.0, Netscape4.04 and Netscape3.01 send Proxy-Connection
  //  when they are configured to use a proxy.  Proxy-Connection
  //  is not in the spec but was added to prevent problems
  //  with a dumb proxy forwarding all headers (including "Connection")
  //  to the origin server and confusing it.  In cases of transparent
  //  deployments we use the Proxy-Connect hdr (to be as transparent
  //  as possible).
  MIMEField *pc = incoming_request->field_find(static_cast<std::string_view>(MIME_FIELD_PROXY_CONNECTION));

  // If we need to send a close header later check to see if it should be "Proxy-Connection"
  if (pc != nullptr) {
    s->client_info.proxy_connect_hdr = true;
  }

  NetVConnection *vc = nullptr;
  if (s->state_machine->get_ua_txn()) {
    vc = s->state_machine->get_ua_txn()->get_netvc();
  }

  if (vc) {
    s->request_data.incoming_port = vc->get_local_port();
    s->request_data.internal_txn  = vc->get_is_internal_request();
  }

  // If this is an internal request, never keep alive
  if (!s->txn_conf->keep_alive_enabled_in || (vc && vc->get_is_internal_request())) {
    s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  } else {
    s->client_info.keep_alive = incoming_request->keep_alive_get();
  }

  if (!s->server_info.name || s->redirect_info.redirect_in_process) {
    s->server_info.name = s->arena.str_store(host_name.data(), static_cast<int>(host_name.length()));
    s->server_info.name_addr.load(s->server_info.name);
  }

  s->next_hop_scheme = s->scheme = incoming_request->url_get()->scheme_get_wksidx();

  // With websockets we need to make an outgoing request
  // as http or https.
  // We switch back to HTTP or HTTPS for the next hop
  // I think this is required to properly establish outbound WSS connections,
  // you'll need to force the next hop to be https.
  if (s->is_websocket) {
    if (s->next_hop_scheme == URL_WKSIDX_WS) {
      TxnDbg(dbg_ctl_http_trans, "Switching WS next hop scheme to http.");
      s->next_hop_scheme = URL_WKSIDX_HTTP;
      s->scheme          = URL_WKSIDX_HTTP;
      // s->request_data.hdr->url_get()->scheme_set(std::string_view{URL_SCHEME_HTTP});
    } else if (s->next_hop_scheme == URL_WKSIDX_WSS) {
      TxnDbg(dbg_ctl_http_trans, "Switching WSS next hop scheme to https.");
      s->next_hop_scheme = URL_WKSIDX_HTTPS;
      s->scheme          = URL_WKSIDX_HTTPS;
      // s->request_data.hdr->url_get()->scheme_set(std::string_view{URL_SCHEME_HTTPS});
    } else {
      Error("Scheme doesn't match websocket...!");
    }

    s->current.mode      = ProxyMode_t::GENERIC;
    s->cache_info.action = CacheAction_t::NO_ACTION;
  }

  s->method = incoming_request->method_get_wksidx();
  // This function may be called multiple times for the same HTTP request. But
  // we only want to increment the per-method request count once for each
  // request.
  if (!s->is_method_stats_incremented) {
    update_method_stat(s->method);
    s->is_method_stats_incremented = true;
  }

  if (s->method == 0 || s->method == HTTP_WKSIDX_METHODS_CNT) {
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_METHOD);
    s->squid_codes.log_code      = SquidLogCode::TCP_MISS;
    s->hdr_info.extension_method = true;
  }

  // if transfer encoding is chunked content length is undefined
  if (s->client_info.transfer_encoding == TransferEncoding_t::CHUNKED) {
    s->hdr_info.request_content_length = HTTP_UNDEFINED_CL;
  }
  s->request_data.hdr = &s->hdr_info.client_request;

  s->request_data.hostname_str = s->arena.str_store(host_name.data(), static_cast<int>(host_name.length()));
  ats_ip_copy(&s->request_data.src_ip, &s->client_info.src_addr);
  memset(&s->request_data.dest_ip, 0, sizeof(s->request_data.dest_ip));
  if (vc) {
    s->request_data.incoming_port = vc->get_local_port();
    s->pp_info.version            = vc->get_proxy_protocol_version();
    if (s->pp_info.version != ProxyProtocolVersion::UNDEFINED) {
      ats_ip_copy(s->pp_info.src_addr, vc->get_proxy_protocol_src_addr());
      ats_ip_copy(s->pp_info.dst_addr, vc->get_proxy_protocol_dst_addr());
    }
  }
  s->request_data.xact_start                      = s->client_request_time;
  s->request_data.api_info                        = &s->api_info;
  s->request_data.cache_info_lookup_url           = &s->cache_info.lookup_url;
  s->request_data.cache_info_parent_selection_url = &s->cache_info.parent_selection_url;

  /////////////////////////////////////////////
  // Do dns lookup for the host. We need     //
  // the expanded host for cache lookup, and //
  // the host ip for reverse proxy.          //
  /////////////////////////////////////////////
  s->dns_info.looking_up  = ResolveInfo::ORIGIN_SERVER;
  s->dns_info.lookup_name = s->server_info.name;
  s->dns_info.resolved_p  = false;
}

void
HttpTransact::update_method_stat(int method)
{
  if (method == HTTP_WKSIDX_GET) {
    Metrics::Counter::increment(http_rsb.get_requests);
  } else if (method == HTTP_WKSIDX_HEAD) {
    Metrics::Counter::increment(http_rsb.head_requests);
  } else if (method == HTTP_WKSIDX_POST) {
    Metrics::Counter::increment(http_rsb.post_requests);
  } else if (method == HTTP_WKSIDX_PUT) {
    Metrics::Counter::increment(http_rsb.put_requests);
  } else if (method == HTTP_WKSIDX_CONNECT) {
    Metrics::Counter::increment(http_rsb.connect_requests);
  } else if (method == HTTP_WKSIDX_DELETE) {
    Metrics::Counter::increment(http_rsb.delete_requests);
  } else if (method == HTTP_WKSIDX_PURGE) {
    Metrics::Counter::increment(http_rsb.purge_requests);
  } else if (method == HTTP_WKSIDX_TRACE) {
    Metrics::Counter::increment(http_rsb.trace_requests);
  } else if (method == HTTP_WKSIDX_PUSH) {
    Metrics::Counter::increment(http_rsb.push_requests);
  } else if (method == HTTP_WKSIDX_OPTIONS) {
    Metrics::Counter::increment(http_rsb.options_requests);
  } else {
    Metrics::Counter::increment(http_rsb.extension_method_requests);
  }
}

void
HttpTransact::initialize_state_variables_from_response(State *s, HTTPHdr *incoming_response)
{
  /* check if the server permits caching */
  s->cache_info.directives.does_server_permit_storing = HttpTransactHeaders::does_server_allow_response_to_be_stored(
    &s->hdr_info.server_response, s->cache_control.ignore_server_no_cache);

  /*
   * A stupid moronic broken pathetic excuse
   *   for a server may send us a keep alive response even
   *   if we sent "Connection: close"  We need check the response
   *   header regardless of what we sent to the server
   */
  s->current.server->keep_alive = s->hdr_info.server_response.keep_alive_get();

  // Don't allow an upgrade request to Keep Alive
  if (s->is_upgrade_request) {
    s->current.server->keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  }

  if (s->current.server->keep_alive == HTTPKeepAlive::KEEPALIVE) {
    TxnDbg(dbg_ctl_http_hdrs, "Server is keep-alive.");
  } else if (s->state_machine->get_ua_txn() && s->state_machine->get_ua_txn()->is_outbound_transparent() &&
             s->state_machine->t_state.http_config_param->use_client_source_port) {
    /* If we are reusing the client<->ATS 4-tuple for ATS<->server then if the server side is closed, we can't
       re-open it because the 4-tuple may still be in the processing of shutting down. So if the server isn't
       keep alive we must turn that off for the client as well.
    */
    s->state_machine->t_state.client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  }

  HTTPStatus status_code = incoming_response->status_get();
  if (is_response_body_precluded(status_code, s->method)) {
    s->hdr_info.response_content_length = 0;
    s->hdr_info.trust_response_cl       = true;
  } else {
    // This code used to discriminate CL: headers when the origin disabled keep-alive.
    if (incoming_response->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
      int64_t cl = incoming_response->get_content_length();

      s->hdr_info.response_content_length = (cl >= 0) ? cl : HTTP_UNDEFINED_CL;
      s->hdr_info.trust_response_cl       = true;
    } else {
      s->hdr_info.response_content_length = HTTP_UNDEFINED_CL;
      s->hdr_info.trust_response_cl       = false;
    }
  }

  if (incoming_response->presence(MIME_PRESENCE_TRANSFER_ENCODING)) {
    MIMEField *field = incoming_response->field_find(static_cast<std::string_view>(MIME_FIELD_TRANSFER_ENCODING));
    ink_assert(field != nullptr);

    HdrCsvIter  enc_val_iter;
    int         enc_val_len;
    const char *enc_value = enc_val_iter.get_first(field, &enc_val_len);

    while (enc_value) {
      const char *wks_value = hdrtoken_string_to_wks(enc_value, enc_val_len);

      if (wks_value == HTTP_VALUE_CHUNKED.c_str() && !is_response_body_precluded(status_code, s->method)) {
        TxnDbg(dbg_ctl_http_hdrs, "transfer encoding: chunked!");
        s->current.server->transfer_encoding = TransferEncoding_t::CHUNKED;

        s->hdr_info.response_content_length = HTTP_UNDEFINED_CL;
        s->hdr_info.trust_response_cl       = false;

        // OBJECTIVE: Since we are dechunking the request remove the
        //   chunked value If this is the only value, we need to remove
        //    the whole field.
        MIMEField  *new_enc_field = nullptr;
        HdrCsvIter  new_enc_iter;
        int         new_enc_len;
        const char *new_enc_val = new_enc_iter.get_first(field, &new_enc_len);

        // Loop over the all the values in existing Trans-enc header and
        //   copy the ones that aren't our chunked value to a new field
        while (new_enc_val) {
          const char *new_wks_value = hdrtoken_string_to_wks(new_enc_val, new_enc_len);
          if (new_wks_value != wks_value) {
            if (new_enc_field) {
              new_enc_field->value_append(incoming_response->m_heap, incoming_response->m_mime, new_enc_val, new_enc_len, true);
            } else {
              new_enc_field = incoming_response->field_create();
              incoming_response->field_value_set(
                new_enc_field, std::string_view{new_enc_val, static_cast<std::string_view::size_type>(new_enc_len)});
            }
          }

          new_enc_val = new_enc_iter.get_next(&new_enc_len);
        }

        // Store the original Transfer-Encoding value for logging before we delete it.
        s->hdr_info.server_response_transfer_encoding.assign(field->value_get().data(), field->value_get().length());

        // We're done with the old field since we copied out everything
        //   we needed
        incoming_response->field_delete(field);

        // If there is a new field (ie: there was more than one
        //   transfer-encoding), insert it to the list
        if (new_enc_field) {
          new_enc_field->name_set(incoming_response->m_heap, incoming_response->m_mime,
                                  static_cast<std::string_view>(MIME_FIELD_TRANSFER_ENCODING));
          incoming_response->field_attach(new_enc_field);
        }

        return;
      } //  if (enc_value == CHUNKED)

      enc_value = enc_val_iter.get_next(&enc_val_len);
    }
  }

  s->current.server->transfer_encoding = TransferEncoding_t::NONE;
}

bool
HttpTransact::is_cache_response_returnable(State *s)
{
  if (s->cache_control.never_cache) {
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_CONFIG);
    return false;
  }

  if (!s->cache_info.directives.does_client_permit_lookup) {
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_CLIENT);
    return false;
  }

  if (!HttpTransactHeaders::is_method_cacheable(s->txn_conf, s->method) && s->api_resp_cacheable == false) {
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_NOT_ACCEPTABLE);
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_METHOD);
    return false;
  }
  // We may be caching responses to methods other than GET, such as POST. Make
  // sure that our cached resource has a method that matches the incoming
  // requests's method. If not, then we cannot reply with the cached resource.
  // That is, we cannot reply to an incoming GET request with a response to a
  // previous POST request. The only exception is replying a HEAD request with
  // a cached GET request as neither are destructive
  int const client_request_method = s->hdr_info.client_request.method_get_wksidx();
  int const cached_request_method = s->cache_info.object_read->request_get()->method_get_wksidx();
  if (client_request_method != cached_request_method &&
      (client_request_method != HTTP_WKSIDX_HEAD || cached_request_method != HTTP_WKSIDX_GET)) {
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_NOT_ACCEPTABLE);
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_METHOD);
    return false;
  }
  // If cookies in response and no TTL set, we do not cache the doc
  if ((s->cache_control.ttl_in_cache <= 0) &&
      do_cookies_prevent_caching(static_cast<int>(s->txn_conf->cache_responses_to_cookies), &s->hdr_info.client_request,
                                 s->cache_info.object_read->response_get(), s->cache_info.object_read->request_get())) {
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_NOT_ACCEPTABLE);
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_COOKIE);
    return false;
  }

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : is_stale_cache_response_returnable()
// Description: check if a stale cached response is returnable to a client
//
// Input      : State
// Output     : true or false
//
// Details    :
//
///////////////////////////////////////////////////////////////////////////////
bool
HttpTransact::is_stale_cache_response_returnable(State *s)
{
  if (s->cache_info.object_read == nullptr) {
    return false;
  }

  HTTPHdr *cached_response = s->cache_info.object_read->response_get();

  // First check if client allows cached response
  // Note does_client_permit_lookup was set to
  // does_client_Request_permit_cached_response()
  // in update_cache_control_information_from_config().
  if (!s->cache_info.directives.does_client_permit_lookup) {
    return false;
  }
  // Spec says that we can not serve a stale document with a
  //   "must-revalidate header"
  // How about "s-maxage" and "no-cache" directives?
  uint32_t cc_mask;
  cc_mask = (MIME_COOKED_MASK_CC_MUST_REVALIDATE | MIME_COOKED_MASK_CC_PROXY_REVALIDATE | MIME_COOKED_MASK_CC_NEED_REVALIDATE_ONCE |
             MIME_COOKED_MASK_CC_NO_CACHE | MIME_COOKED_MASK_CC_NO_STORE | MIME_COOKED_MASK_CC_S_MAXAGE);
  if ((cached_response->get_cooked_cc_mask() & cc_mask) || cached_response->is_pragma_no_cache_set()) {
    TxnDbg(dbg_ctl_http_trans, "document headers prevent serving stale");
    return false;
  }
  // See how old the document really is.  We don't want create a
  //   stale content museum of documents that are no longer available
  time_t current_age = HttpTransactCache::calculate_document_age(s->cache_info.object_read->request_sent_time_get(),
                                                                 s->cache_info.object_read->response_received_time_get(),
                                                                 cached_response, cached_response->get_date(), s->current.now);
  // Negative age is overflow
  if ((current_age < 0) || (current_age > s->txn_conf->cache_max_stale_age + get_max_age(cached_response))) {
    TxnDbg(dbg_ctl_http_trans, "document age is too large %" PRId64, (int64_t)current_age);
    return false;
  }
  // If the stale document requires authorization, we can't return it either.
  Authentication_t auth_needed = AuthenticationNeeded(s->txn_conf, &s->hdr_info.client_request, cached_response);

  if (auth_needed != Authentication_t::SUCCESS) {
    TxnDbg(dbg_ctl_http_trans, "authorization prevent serving stale");
    return false;
  }

  TxnDbg(dbg_ctl_http_trans, "can serve stale");
  return true;
}

bool
HttpTransact::url_looks_dynamic(URL *url)
{
  const char        *p_start, *p, *t;
  static const char *asp = ".asp";

  if (url->scheme_get_wksidx() != URL_WKSIDX_HTTP && url->scheme_get_wksidx() != URL_WKSIDX_HTTPS) {
    return false;
  }
  ////////////////////////////////////////////////////////////
  // (1) If URL contains query stuff in it, call it dynamic //
  ////////////////////////////////////////////////////////////

  if (!url->query_get().empty()) {
    return true;
  }
  ///////////////////////////////////////////////
  // (2) If path ends in "asp" call it dynamic //
  ///////////////////////////////////////////////

  auto path{url->path_get()};
  if (path.data()) {
    p = &path[path.length() - 1];
    t = &asp[3];

    while (p != path.data()) {
      if (ParseRules::ink_tolower(*p) == ParseRules::ink_tolower(*t)) {
        p -= 1;
        t -= 1;
        if (t == asp) {
          return true;
        }
      } else {
        break;
      }
    }
  }
  /////////////////////////////////////////////////////////////////
  // (3) If the path of the url contains "cgi", call it dynamic. //
  /////////////////////////////////////////////////////////////////

  if (path.data() && path.length() >= 3) {
    for (p_start = path.data(); p_start <= &path[path.length() - 3]; p_start++) {
      if (((p_start[0] == 'c') || (p_start[0] == 'C')) && ((p_start[1] == 'g') || (p_start[1] == 'G')) &&
          ((p_start[2] == 'i') || (p_start[2] == 'I'))) {
        return (true);
      }
    }
  }

  return (false);
}

///////////////////////////////////////////////////////////////////////////////
// Name       : is_request_cache_lookupable()
// Description: check if a request should be looked up in cache
//
// Input      : State, request header
// Output     : true or false
//
// Details    :
//
//
///////////////////////////////////////////////////////////////////////////////
bool
HttpTransact::is_request_cache_lookupable(State *s)
{
  // ummm, someone has already decided that proxy should tunnel
  if (s->current.mode == ProxyMode_t::TUNNELLING) {
    return false;
  }
  // don't bother with remaining checks if we already did a cache lookup
  if (s->cache_info.lookup_count > 0) {
    return true;
  }
  // is cache turned on?
  if (!s->txn_conf->cache_http) {
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_CACHE_OFF);
    return false;
  }
  // GET, HEAD, POST, DELETE, and PUT are all cache lookupable
  if (!HttpTransactHeaders::is_method_cache_lookupable(s->method) && s->api_req_cacheable == false) {
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_METHOD);
    return false;
  }
  // don't cache page if URL "looks dynamic" and this filter is enabled
  // We can do the check in is_response_cacheable() or here.
  // It may be more efficient if we are not going to cache dynamic looking urls
  // (the default config?) since we don't even need to do cache lookup.
  // So for the time being, it'll be left here.

  // If url looks dynamic but a ttl is set, request is cache lookupable
  if ((!s->txn_conf->cache_urls_that_look_dynamic) && url_looks_dynamic(s->hdr_info.client_request.url_get()) &&
      (s->cache_control.ttl_in_cache <= 0)) {
    // We do not want to forward the request for a dynamic URL onto the
    // origin server if the value of the Max-Forwards header is zero.
    int max_forwards = -1;
    if (s->hdr_info.client_request.presence(MIME_PRESENCE_MAX_FORWARDS)) {
      MIMEField *max_forwards_f = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_MAX_FORWARDS));

      if (max_forwards_f) {
        max_forwards = max_forwards_f->value_get_int();
      }
    }

    if (max_forwards != 0) {
      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_URL);
      return false;
    }
  }

  // Don't look in cache if it's a RANGE request but the cache is not enabled for RANGE.
  if (!s->txn_conf->cache_range_lookup && s->hdr_info.client_request.presence(MIME_PRESENCE_RANGE)) {
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_HEADER_FIELD);
    return false;
  }

  // Even with "no-cache" directive, we want to do a cache lookup
  // because we need to update our cached copy.
  // Client request "no-cache" directive is handle elsewhere:
  // update_cache_control_information_from_config()

  return true;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : response_cacheable_indicated_by_cc()
// Description: check if a response is cacheable as indicated by Cache-Control
//
// Input      : Response header, whether to ignored response's no-cache/no-store
// Output     : -1, 0, or +1
//
// Details    :
// (1) return -1 if cache control indicates response not cacheable,
//     ie, with no-store, or private directives;
// (2) return +1 if cache control indicates response cacheable
//     ie, with public, max-age, s-maxage, must-revalidate, or proxy-revalidate;
// (3) otherwise, return 0 if cache control does not indicate.
//
///////////////////////////////////////////////////////////////////////////////
int
response_cacheable_indicated_by_cc(HTTPHdr *response, bool ignore_no_store_and_no_cache_directives)
{
  uint32_t cc_mask;
  // the following directives imply not cacheable
  cc_mask = MIME_COOKED_MASK_CC_PRIVATE | (ignore_no_store_and_no_cache_directives ? 0 : MIME_COOKED_MASK_CC_NO_STORE);
  if (response->get_cooked_cc_mask() & cc_mask) {
    return -1;
  }
  // the following directives imply cacheable
  cc_mask = (MIME_COOKED_MASK_CC_PUBLIC | MIME_COOKED_MASK_CC_MAX_AGE | MIME_COOKED_MASK_CC_S_MAXAGE |
             MIME_COOKED_MASK_CC_MUST_REVALIDATE | MIME_COOKED_MASK_CC_PROXY_REVALIDATE);
  if (response->get_cooked_cc_mask() & cc_mask) {
    return 1;
  }
  // otherwise, no indication
  return 0;
}

///////////////////////////////////////////////////////////////////////////////
// Name       : is_response_cacheable()
// Description: check if a response is cacheable
//
// Input      : State, request header, response header
// Output     : true or false
//
// Details    :
//
///////////////////////////////////////////////////////////////////////////////
bool
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.cta_validated_p && s->client_info.is_transparent) {
    TxnDbg(dbg_ctl_http_trans, "Lookup not validated.  Possible DNS cache poison.  Don't cache");
    return false;
  }

  // the plugin may decide we don't want to cache the response
  if (s->api_server_response_no_store) {
    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->txn_conf, req_method)) && s->api_req_cacheable == false) {
    TxnDbg(dbg_ctl_http_trans, "only GET, and some HEAD and POST are cacheable");
    return false;
  }
  // TxnDbg(dbg_ctl_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))) {
    TxnDbg(dbg_ctl_http_trans, "request is not cache lookupable, response is not cacheable");
    return false;
  }
  // already has a fresh copy in the cache
  if (s->range_setup == RangeSetup_t::NOT_HANDLED) {
    return false;
  }

  // Check whether the response is cacheable 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(static_cast<int>(s->txn_conf->cache_responses_to_cookies), request, response)) {
    TxnDbg(dbg_ctl_http_trans, "response has uncachable cookies, response is not cacheable");
    return false;
  }
  // if server spits back a WWW-Authenticate
  if ((s->txn_conf->cache_ignore_auth) == 0 && response->presence(MIME_PRESENCE_WWW_AUTHENTICATE)) {
    TxnDbg(dbg_ctl_http_trans, "response has WWW-Authenticate, response is not cacheable");
    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.ttl_in_cache <= 0)) {
    TxnDbg(dbg_ctl_http_trans, "server does not permit storing and config file does not "
                               "indicate that server directive should be ignored");
    return false;
  }
  // TxnDbg(dbg_ctl_http_trans, "[is_response_cacheable] server permits storing");

  // does config explicitly forbid storing?
  // ttl overrides other config parameters
  if ((!s->cache_info.directives.does_config_permit_storing && (s->cache_control.ttl_in_cache <= 0)) ||
      (s->cache_control.never_cache)) {
    TxnDbg(dbg_ctl_http_trans, "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;
  }
  // TxnDbg(dbg_ctl_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) {
    TxnDbg(dbg_ctl_http_trans, "client does not permit storing, "
                               "and cache control does not say to ignore client no-cache");
    return false;
  }
  TxnDbg(dbg_ctl_http_trans, "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 == HTTPStatus::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 (static_cast<HttpConfigParams::CacheRequiredHeaders>(s->txn_conf->cache_required_headers)) {
      case HttpConfigParams::CacheRequiredHeaders::NONE:
        TxnDbg(dbg_ctl_http_trans, "no response headers required");
        break;

      case HttpConfigParams::CacheRequiredHeaders::AT_LEAST_LAST_MODIFIED:
        if (!response->presence(MIME_PRESENCE_EXPIRES) && !(response->get_cooked_cc_mask() & cc_mask) &&
            !response->get_last_modified()) {
          TxnDbg(dbg_ctl_http_trans, "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::CacheRequiredHeaders::CACHE_CONTROL:
        if (!response->presence(MIME_PRESENCE_EXPIRES) && !(response->get_cooked_cc_mask() & cc_mask)) {
          TxnDbg(dbg_ctl_http_trans, "expires header or max-age is required");
          return false;
        }
        break;

      default:
        break;
      }
    }
  }
  // do not cache partial content - Range response
  if (response_code == HTTPStatus::PARTIAL_CONTENT || response_code == HTTPStatus::RANGE_NOT_SATISFIABLE) {
    TxnDbg(dbg_ctl_http_trans, "response code %d - don't cache", static_cast<int>(response_code));
    return false;
  }

  // check if cache control overrides default cacheability
  int indicator;
  indicator = response_cacheable_indicated_by_cc(response, s->cache_control.ignore_server_no_cache);
  if (indicator > 0) { // cacheable indicated by cache control header
    TxnDbg(dbg_ctl_http_trans, "YES by response cache control");
    // even if it is authenticated, this is cacheable based on regular rules
    s->www_auth_content = CacheAuth_t::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) {
      TxnDbg(dbg_ctl_http_trans, "Cache-control header directives in response overridden by ttl in %s", ts::filename::CACHE);
    } else {
      TxnDbg(dbg_ctl_http_trans, "NO by response cache control");
      return false;
    }
  }
  // else no indication by cache control header
  // continue to determine cacheability

  if (response->presence(MIME_PRESENCE_EXPIRES)) {
    TxnDbg(dbg_ctl_http_trans, "YES response w/ Expires");
    return true;
  }
  // if it's a 302 or 307 and no positive indicator from cache-control, reject
  if (response_code == HTTPStatus::MOVED_TEMPORARILY || response_code == HTTPStatus::TEMPORARY_REDIRECT) {
    TxnDbg(dbg_ctl_http_trans, "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) {
      TxnDbg(dbg_ctl_http_trans, "POST method with a TTL");
    } else {
      TxnDbg(dbg_ctl_http_trans, "NO POST w/o Expires or CC");
      return false;
    }
  }

  if ((response_code == HTTPStatus::OK) || (response_code == HTTPStatus::NOT_MODIFIED) ||
      (response_code == HTTPStatus::NON_AUTHORITATIVE_INFORMATION) || (response_code == HTTPStatus::MOVED_PERMANENTLY) ||
      (response_code == HTTPStatus::MULTIPLE_CHOICES) || (response_code == HTTPStatus::GONE)) {
    TxnDbg(dbg_ctl_http_trans, "YES response code seems fine");
    return true;
  }
  // Notice that the following are not overridable by negative caching.
  if (response_code == HTTPStatus::SEE_OTHER || response_code == HTTPStatus::UNAUTHORIZED ||
      response_code == HTTPStatus::PROXY_AUTHENTICATION_REQUIRED) {
    return false;
  }
  // The response code does not look appropriate for caching. Check, however,
  // whether the user has specified it should be cached via negative response
  // caching configuration.
  if (is_negative_caching_appropriate(s)) {
    return true;
  }
  return false;
  /* 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.
  */
}

bool
HttpTransact::is_request_valid(State *s, HTTPHdr *incoming_request)
{
  RequestError_t incoming_error;
  URL           *url = nullptr;

  // If we are blind tunneling the header is just a synthesized placeholder anyway.
  // But we do have to check that we are not tunneling to a dynamic port that is
  // not in the connect_ports list.
  if (s->client_info.port_attribute == HttpProxyPort::TRANSPORT_BLIND_TUNNEL) {
    if (s->tunnel_port_is_dynamic &&
        !is_port_in_range(incoming_request->url_get()->port_get(), s->http_config_param->connect_ports)) {
      TxnDbg(dbg_ctl_http_trans, "Rejected a tunnel to port %d not in connect_ports", incoming_request->url_get()->port_get());
      return false;
    }
    return true;
  }

  if (incoming_request) {
    url = incoming_request->url_get();
  }

  incoming_error = check_request_validity(s, incoming_request);
  switch (incoming_error) {
  case RequestError_t::NO_REQUEST_HEADER_ERROR:
    TxnDbg(dbg_ctl_http_trans, "no request header errors");
    break;
  case RequestError_t::FAILED_PROXY_AUTHORIZATION:
    TxnDbg(dbg_ctl_http_trans, "failed proxy authorization");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_error_response(s, HTTPStatus::PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required",
                         "access#proxy_auth_required");
    return false;
  case RequestError_t::NON_EXISTANT_REQUEST_HEADER:
  /* fall through */
  case RequestError_t::BAD_HTTP_HEADER_SYNTAX: {
    TxnDbg(dbg_ctl_http_trans, "non-existent/bad header");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_error_response(s, HTTPStatus::BAD_REQUEST, "Invalid HTTP Request", "request#syntax_error");
    return false;
  }

  case RequestError_t::MISSING_HOST_FIELD:

    ////////////////////////////////////////////////////////////////////
    // FIX: are we sure the following logic is right?  it seems that  //
    //      we shouldn't complain about the missing host header until //
    //      we know we really need one --- are we sure we need a host //
    //      header at this point?                                     //
    //                                                                //
    // FIX: also, let's clean up the transparency code to remove the  //
    //      SunOS conditionals --- we will be transparent on all      //
    //      platforms soon!  in fact, I really want a method that i   //
    //      can call for each transaction to say if the transaction   //
    //      is a forward proxy request, a transparent request, a      //
    //      reverse proxy request, etc --- the detail of how we       //
    //      determine the cases should be hidden behind the method.   //
    ////////////////////////////////////////////////////////////////////

    TxnDbg(dbg_ctl_http_trans, "missing host field");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    if (s->http_config_param->reverse_proxy_enabled) { // host header missing and reverse proxy on
      build_error_response(s, HTTPStatus::BAD_REQUEST, "Host Header Required", "request#no_host");
    } else {
      // host header missing and reverse proxy off
      build_error_response(s, HTTPStatus::BAD_REQUEST, "Host Required In Request", "request#no_host");
    }

    return false;
  case RequestError_t::SCHEME_NOT_SUPPORTED:
  case RequestError_t::NO_REQUEST_SCHEME: {
    TxnDbg(dbg_ctl_http_trans, "unsupported or missing request scheme");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_error_response(s, HTTPStatus::BAD_REQUEST, "Unsupported URL Scheme", "request#scheme_unsupported");
    return false;
  }
  /* fall through */
  case RequestError_t::METHOD_NOT_SUPPORTED:
    TxnDbg(dbg_ctl_http_trans, "unsupported method");
    s->current.mode = ProxyMode_t::TUNNELLING;
    return true;
  case RequestError_t::BAD_CONNECT_PORT:
    int port;
    port = url ? url->port_get() : 0;
    TxnDbg(dbg_ctl_http_trans, "%d is an invalid connect port", port);
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_error_response(s, HTTPStatus::FORBIDDEN, "Tunnel Forbidden", "access#connect_forbidden");
    return false;
  case RequestError_t::NO_POST_CONTENT_LENGTH: {
    TxnDbg(dbg_ctl_http_trans, "post request without content length");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_error_response(s, HTTPStatus::LENGTH_REQUIRED, "Content Length Required", "request#no_content_length");
    return false;
  }
  case RequestError_t::UNACCEPTABLE_TE_REQUIRED: {
    TxnDbg(dbg_ctl_http_trans, "TE required is unacceptable.");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_error_response(s, HTTPStatus::NOT_ACCEPTABLE, "Transcoding Not Available", "transcoding#unsupported");
    return false;
  }
  case RequestError_t::INVALID_POST_CONTENT_LENGTH: {
    TxnDbg(dbg_ctl_http_trans, "post request with negative content length value");
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    build_error_response(s, HTTPStatus::BAD_REQUEST, "Invalid Content Length", "request#invalid_content_length");
    return false;
  }
  default:
    return true;
  }

  return true;
}

// bool HttpTransact::is_request_retryable
//
// In the general case once bytes have been sent on the wire the request cannot be retried.
// The reason we cannot retry is that the rfc2616 does not make any guarantees about the
// retry-ability of a request. In fact in the reverse proxy case it is quite common for GET
// requests on the origin to fire tracking events etc. So, as a proxy, once bytes have been ACKd
// by the server we cannot guarantee that the request is safe to retry or redispatch to another server.
// This is distinction of "ACKd" vs "sent" is intended, and has reason. In the case of a
// new origin connection there is little difference, as the chance of a RST between setup
// and the first set of bytes is relatively small. This distinction is more apparent in the
// case where the origin connection is a KA session. In this case, the session may not have
// been used for a long time. In that case, we'll immediately queue up session to send to the
// origin, without any idea of the state of the connection. If the origin is down (or the connection
// is broken for some other reason) we'll immediately get a RST back. In that case-- since no
// bytes where ACKd by the remote end, we can retry/redispatch the request.
//
bool
HttpTransact::is_request_retryable(State *s)
{
  // If safe requests are  retryable, it should be safe to retry safe requests irrespective of bytes sent or connection state
  // according to RFC the following methods are safe (https://tools.ietf.org/html/rfc7231#section-4.2.1)
  // Otherwise, if there was no error establishing the connection (and we sent bytes)-- we cannot retry
  if (!HttpTransactHeaders::is_method_safe(s->method) && s->current.state != CONNECTION_ERROR &&
      s->state_machine->server_request_hdr_bytes > 0) {
    return false;
  }

  // FIXME: disable the post transform retry currently.
  if (s->state_machine->is_post_transform_request()) {
    return false;
  }

  if (s->state_machine->plugin_tunnel_type != HttpPluginTunnel_t::NONE) {
    // API can override
    if (s->state_machine->plugin_tunnel_type == HttpPluginTunnel_t::AS_SERVER && s->api_info.retry_intercept_failures == true) {
      // This used to be an == comparison, which made no sense. Changed
      // to be an assignment, hoping the state is correct.
      s->state_machine->plugin_tunnel_type = HttpPluginTunnel_t::NONE;
    } else {
      return false;
    }
  }

  return true;
}

void
HttpTransact::process_quick_http_filter(State *s, int method)
{
  // connection already disabled by previous ACL filtering, don't modify it.
  if (!s->client_connection_allowed) {
    s->http_return_code_setter_name = "ip_allow";
    return;
  }

  // if the "ip_allow" named filter is deactivated in the remap.config, then don't modify anything
  url_mapping const *const mp = s->url_map.getMapping();
  if (nullptr != mp && !mp->ip_allow_check_enabled_p) {
    return;
  }

  // if a ACL filter in the remap.config forces skipping ip_allow.yaml check, do nothing
  if (s->skip_ip_allow_yaml) {
    return;
  }

  if (s->state_machine->get_ua_txn()) {
    auto            &acl          = s->state_machine->get_ua_txn()->get_acl();
    bool             deny_request = !acl.isValid();
    std::string_view method_str;

    if (acl.isValid() && !acl.isAllowAll()) {
      if (method != -1) {
        deny_request = !acl.isMethodAllowed(method);
      } else {
        method_str   = s->hdr_info.client_request.method_get();
        deny_request = !acl.isNonstandardMethodAllowed(method_str);
      }
    }
    if (deny_request) {
      if (dbg_ctl_ip_allow.on()) {
        ip_text_buffer ipb;
        if (method != -1) {
          method_str = std::string_view{hdrtoken_index_to_wks(method)};
        } else if (method_str.empty()) {
          method_str = s->hdr_info.client_request.method_get();
        }
        TxnDbg(dbg_ctl_ip_allow, "Line %d denial for '%.*s' from %s", acl.source_line(), static_cast<int>(method_str.length()),
               method_str.data(), ats_ip_ntop(&s->client_info.src_addr.sa, ipb, sizeof(ipb)));
      }
      s->http_return_code_setter_name = "ip_allow";
      s->client_connection_allowed    = false;
    }
  }
}

bool
HttpTransact::will_this_request_self_loop(State *s)
{
  // The self-loop detection for this ATS node will allow up to max_proxy_cycles
  // (each time it sees it returns to itself it is one cycle) before declaring a self-looping condition detected.
  // If max_proxy_cycles is > 0 then next-hop is disabled since --
  //   * if first cycle then it is alright okay
  //   * if not first cycle then will be detected by via string checking the next time that
  //     it enters the node
  int max_proxy_cycles = s->txn_conf->max_proxy_cycles;

  ////////////////////////////////////////
  // check if we are about to self loop //
  ////////////////////////////////////////
  if (s->dns_info.active) {
    TxnDbg(dbg_ctl_http_transact, "max_proxy_cycles = %d", max_proxy_cycles);
    if (max_proxy_cycles == 0) {
      in_port_t dst_port   = s->hdr_info.client_request.url_get()->port_get(); // going to this port.
      in_port_t local_port = s->client_info.dst_addr.host_order_port();        // already connected proxy port.
      // It's a loop if connecting to the same port as it already connected to the proxy and
      // it's a proxy address or the same address it already connected to.
      TxnDbg(dbg_ctl_http_transact, "dst_port = %d local_port = %d", dst_port, local_port);
      if (dst_port == local_port && ((s->dns_info.active->data.ip == &Machine::instance()->ip.sa) ||
                                     (s->dns_info.active->data.ip == s->client_info.dst_addr))) {
        switch (s->dns_info.looking_up) {
        case ResolveInfo::ORIGIN_SERVER:
          TxnDbg(dbg_ctl_http_transact, "host ip and port same as local ip and port - bailing");
          break;
        case ResolveInfo::PARENT_PROXY:
          TxnDbg(dbg_ctl_http_transact, "parent proxy ip and port same as local ip and port - bailing");
          break;
        default:
          TxnDbg(dbg_ctl_http_transact, "unknown's ip and port same as local ip and port - bailing");
          break;
        }
        SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_LOOP_DETECTED);
        Metrics::Counter::increment(http_rsb.proxy_loop_detected);
        build_error_response(s, HTTPStatus::BAD_REQUEST, "Cycle Detected", "request#cycle_detected");
        return true;
      }
    }

    // Now check for a loop using the Via string.
    int              count     = 0;
    MIMEField       *via_field = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_VIA));
    std::string_view uuid{Machine::instance()->process_uuid.getString()};

    while (via_field) {
      // No need to waste cycles comma separating the via values since we want to do a match anywhere in the
      // in the string.  We can just loop over the dup hdr fields
      auto via_string{via_field->value_get()};

      if ((count <= max_proxy_cycles) && via_string.data()) {
        std::string_view            current{via_field->value_get()};
        std::string_view::size_type offset;
        TxnDbg(dbg_ctl_http_transact, "Incoming via: \"%.*s\" --has-- (%s[%s] (%s))", static_cast<int>(via_string.length()),
               via_string.data(), s->http_config_param->proxy_hostname, uuid.data(),
               s->http_config_param->proxy_request_via_string);
        while ((count <= max_proxy_cycles) && (std::string_view::npos != (offset = current.find(uuid)))) {
          current.remove_prefix(offset + TS_UUID_STRING_LEN);
          count++;
          TxnDbg(dbg_ctl_http_transact, "count = %d current = %.*s", count, static_cast<int>(current.length()), current.data());
        }
      }

      via_field = via_field->m_next_dup;
    }
    if (count > max_proxy_cycles) {
      TxnDbg(dbg_ctl_http_transact, "count = %d > max_proxy_cycles = %d : detected loop", count, max_proxy_cycles);
      SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_LOOP_DETECTED);
      Metrics::Counter::increment(http_rsb.proxy_mh_loop_detected);
      build_error_response(s, HTTPStatus::BAD_REQUEST, "Multi-Hop Cycle Detected", "request#cycle_detected");
      return true;
    } else {
      TxnDbg(dbg_ctl_http_transact, "count = %d <= max_proxy_cycles = %d : allowing loop", count, max_proxy_cycles);
    }
  }
  return false;
}

/*
 * handle_content_length_header(...)
 *  Function handles the insertion of content length headers into
 * header. header CAN equal base.
 */
void
HttpTransact::handle_content_length_header(State *s, HTTPHdr *header, HTTPHdr *base)
{
  int64_t cl = HTTP_UNDEFINED_CL;
  ink_assert(header->type_get() == HTTPType::RESPONSE);
  if (base->presence(MIME_PRESENCE_CONTENT_LENGTH)) {
    cl = base->get_content_length();
    if (cl >= 0) {
      // header->set_content_length(cl);
      ink_assert(header->get_content_length() == cl);

      switch (s->source) {
      case Source_t::HTTP_ORIGIN_SERVER:
        // We made our decision about whether to trust the
        //   response content length in init_state_vars_from_response()
        if (s->range_setup != HttpTransact::RangeSetup_t::NOT_TRANSFORM_REQUESTED) {
          break;
        }
        // fallthrough

      case Source_t::CACHE:
        // if we are doing a single Range: request, calculate the new
        // C-L: header
        if (s->range_setup == HttpTransact::RangeSetup_t::NOT_TRANSFORM_REQUESTED) {
          change_response_header_because_of_range_request(s, header);
          s->hdr_info.trust_response_cl = true;
        }
        ////////////////////////////////////////////////
        //  Make sure that the cache's object size    //
        //   agrees with the Content-Length           //
        //   Otherwise, set the state's machine view  //
        //   of c-l to undefined to turn off K-A      //
        ////////////////////////////////////////////////
        else if (s->cache_info.object_read->object_size_get() == cl) {
          s->hdr_info.trust_response_cl = true;
        } else {
          TxnDbg(dbg_ctl_http_trans, "Content Length header and cache object size mismatch."
                                     "Disabling keep-alive");
          s->hdr_info.trust_response_cl = false;
        }
        break;

      case Source_t::TRANSFORM:
        if (s->range_setup == HttpTransact::RangeSetup_t::REQUESTED) {
          header->set_content_length(s->range_output_cl);
          s->hdr_info.trust_response_cl = true;
        } else if (s->hdr_info.transform_response_cl == HTTP_UNDEFINED_CL) {
          s->hdr_info.trust_response_cl = false;
        } else {
          s->hdr_info.trust_response_cl = true;
        }
        break;

      default:
        ink_release_assert(0);
        break;
      }
    } else {
      header->field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_LENGTH));
      s->hdr_info.trust_response_cl = false;
    }
    TxnDbg(dbg_ctl_http_trans, "RESPONSE cont len in hdr is %" PRId64, header->get_content_length());
  } else {
    // No content length header.
    // If the source is cache or server returned 304 response,
    // we can try to get the content length based on object size.
    // Also, we should check the scenario of server sending't  a unexpected 304 response for a non conditional request( no cached
    // object )
    if (s->source == Source_t::CACHE ||
        (s->source == Source_t::HTTP_ORIGIN_SERVER && s->hdr_info.server_response.status_get() == HTTPStatus::NOT_MODIFIED &&
         s->cache_info.object_read != nullptr)) {
      // If there is no content-length header, we can
      //   insert one since the cache knows definitely
      //   how long the object is unless we're in a
      //   read-while-write mode and object hasn't been
      //   written into a cache completely.
      cl = s->cache_info.object_read->object_size_get();
      if (cl == INT64_MAX) { // INT64_MAX cl in cache indicates rww in progress
        header->field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_LENGTH));
        s->hdr_info.trust_response_cl      = false;
        s->hdr_info.request_content_length = HTTP_UNDEFINED_CL;
        ink_assert(s->range_setup == RangeSetup_t::NONE);
      } else if (s->range_setup == RangeSetup_t::NOT_TRANSFORM_REQUESTED) {
        // if we are doing a single Range: request, calculate the new
        // C-L: header
        // either the object is in cache or origin returned a 304 Not Modified response. We can still turn this into a proper Range
        // response from the cached object.
        change_response_header_because_of_range_request(s, header);
        s->hdr_info.trust_response_cl = true;
      } else {
        if (header->status_get() != HTTPStatus::NO_CONTENT) {
          header->set_content_length(cl);
        }
        s->hdr_info.trust_response_cl = true;
      }
    } else {
      // Check to see if there is no content length
      //  header because the response precludes a
      // body
      if (is_response_body_precluded(header->status_get(), s->method)) {
        // We want to be able to do keep-alive here since
        //   there can't be body so we don't have any
        //   issues about trusting the body length
        s->hdr_info.trust_response_cl = true;
      } else {
        s->hdr_info.trust_response_cl = false;
      }
      header->field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_LENGTH));
      ink_assert(s->range_setup != RangeSetup_t::NOT_TRANSFORM_REQUESTED);
    }
  }
  return;
} /* End HttpTransact::handle_content_length_header */

//////////////////////////////////////////////////////////////////////////////
//
//      void HttpTransact::handle_request_keep_alive_headers(
//          State* s, bool ka_on, HTTPVersion ver, HTTPHdr *heads)
//
//      Removes keep alive headers from user-agent from <heads>
//
//      Adds the appropriate keep alive headers (if any) to <heads>
//      for keep-alive state <ka_on>, and HTTP version <ver>.
//
//////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_request_keep_alive_headers(State *s, HTTPVersion ver, HTTPHdr *heads)
{
  enum class KA_Action_t {
    UNKNOWN,
    DISABLED,
    CLOSE,
    CONNECTION,
  };

  KA_Action_t ka_action   = KA_Action_t::UNKNOWN;
  bool        upstream_ka = (s->current.server->keep_alive == HTTPKeepAlive::KEEPALIVE);

  ink_assert(heads->type_get() == HTTPType::REQUEST);

  // Check preconditions for Keep-Alive
  if (!upstream_ka) {
    ka_action = KA_Action_t::DISABLED;
  } else if (ver.get_major() == 0) { /* No K-A for 0.9 apps */
    ka_action = KA_Action_t::DISABLED;
  }
  // If preconditions are met, figure out what action to take
  if (ka_action == KA_Action_t::UNKNOWN) {
    int method = heads->method_get_wksidx();
    if (method == HTTP_WKSIDX_GET || method == HTTP_WKSIDX_HEAD || method == HTTP_WKSIDX_OPTIONS || method == HTTP_WKSIDX_PURGE ||
        method == HTTP_WKSIDX_DELETE || method == HTTP_WKSIDX_TRACE) {
      // These methods do not need a content-length header
      ka_action = KA_Action_t::CONNECTION;
    } else {
      // All remaining methods require a content length header
      if (heads->get_content_length() == -1) {
        ka_action = KA_Action_t::CLOSE;
      } else {
        ka_action = KA_Action_t::CONNECTION;
      }
    }
  }

  ink_assert(ka_action != KA_Action_t::UNKNOWN);

  // Since connection headers are hop-to-hop, strip the
  //  the ones we received from the user-agent
  heads->field_delete(static_cast<std::string_view>(MIME_FIELD_PROXY_CONNECTION));
  heads->field_delete(static_cast<std::string_view>(MIME_FIELD_CONNECTION));

  if (!s->is_upgrade_request) {
    // Insert K-A headers as necessary
    switch (ka_action) {
    case KA_Action_t::CONNECTION:
      ink_assert(s->current.server->keep_alive != HTTPKeepAlive::NO_KEEPALIVE);
      if (ver == HTTP_1_0) {
        if (s->current.request_to == ResolveInfo::PARENT_PROXY && parent_is_proxy(s)) {
          heads->value_set(static_cast<std::string_view>(MIME_FIELD_PROXY_CONNECTION), "keep-alive"sv);
        } else {
          heads->value_set(static_cast<std::string_view>(MIME_FIELD_CONNECTION), "keep-alive"sv);
        }
      }
      // NOTE: if the version is 1.1 we don't need to do
      //  anything since keep-alive is assumed
      break;
    case KA_Action_t::DISABLED:
    case KA_Action_t::CLOSE:
      if (s->current.server->keep_alive != HTTPKeepAlive::NO_KEEPALIVE || (ver == HTTP_1_1)) {
        /* Had keep-alive */
        s->current.server->keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
        if (s->current.request_to == ResolveInfo::PARENT_PROXY && parent_is_proxy(s)) {
          heads->value_set(static_cast<std::string_view>(MIME_FIELD_PROXY_CONNECTION), "close"sv);
        } else {
          ProxyTransaction *svr = s->state_machine->get_server_txn();
          if (svr) {
            svr->set_close_connection(*heads);
          }
        }
      }
      // Note: if we are 1.1, we always need to send the close
      //  header since persistent connections are the default
      break;
    default:
      ink_assert(0);
      break;
    }
  } else { /* websocket connection */
    s->current.server->keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
    s->client_info.keep_alive     = HTTPKeepAlive::NO_KEEPALIVE;
    heads->value_set(static_cast<std::string_view>(MIME_FIELD_CONNECTION), static_cast<std::string_view>(MIME_FIELD_UPGRADE));

    if (s->is_websocket) {
      heads->value_set(static_cast<std::string_view>(MIME_FIELD_UPGRADE), "websocket"sv);
    }
  }
} /* End HttpTransact::handle_request_keep_alive_headers */

//////////////////////////////////////////////////////////////////////////////
//
//      void HttpTransact::handle_response_keep_alive_headers(
//          State* s, bool ka_on, HTTPVersion ver, HTTPHdr *heads)
//
//      Removes keep alive headers from origin server from <heads>
//
//      Adds the appropriate Transfer-Encoding: chunked header.
//
//      Adds the appropriate keep alive headers (if any) to <heads>
//      for keep-alive state <ka_on>, and HTTP version <ver>.
//
//////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_response_keep_alive_headers(State *s, HTTPVersion ver, HTTPHdr *heads)
{
  enum class KA_Action_t {
    UNKNOWN,
    DISABLED,
    CLOSE,
    CONNECTION,
  };
  KA_Action_t ka_action = KA_Action_t::UNKNOWN;

  ink_assert(heads->type_get() == HTTPType::RESPONSE);

  // Since connection headers are hop-to-hop, strip the
  //  the ones we received from upstream
  heads->field_delete(static_cast<std::string_view>(MIME_FIELD_CONNECTION));
  heads->field_delete(static_cast<std::string_view>(MIME_FIELD_PROXY_CONNECTION));

  // Handle the upgrade cases
  if (s->is_upgrade_request && heads->status_get() == HTTPStatus::SWITCHING_PROTOCOL && s->source == Source_t::HTTP_ORIGIN_SERVER) {
    s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
    if (s->is_websocket) {
      TxnDbg(dbg_ctl_http_trans, "transaction successfully upgraded to websockets.");
      // s->transparent_passthrough = true;
      heads->value_set(static_cast<std::string_view>(MIME_FIELD_CONNECTION), static_cast<std::string_view>(MIME_FIELD_UPGRADE));
      heads->value_set(static_cast<std::string_view>(MIME_FIELD_UPGRADE), "websocket"sv);
    }

    // We set this state so that we can jump to our blind forwarding state once
    // the response is sent to the client.
    s->did_upgrade_succeed = true;
    return;
  }

  int         c_hdr_field_len;
  const char *c_hdr_field_str;
  if (s->client_info.proxy_connect_hdr) {
    c_hdr_field_str = MIME_FIELD_PROXY_CONNECTION.c_str();
    c_hdr_field_len = static_cast<int>(MIME_FIELD_PROXY_CONNECTION.length());
  } else {
    c_hdr_field_str = MIME_FIELD_CONNECTION.c_str();
    c_hdr_field_len = static_cast<int>(MIME_FIELD_CONNECTION.length());
  }

  // Check pre-conditions for keep-alive
  if (ver.get_major() == 0) { /* No K-A for 0.9 apps */
    ka_action = KA_Action_t::DISABLED;
  } else if (heads->status_get() == HTTPStatus::NO_CONTENT &&
             ((s->source == Source_t::HTTP_ORIGIN_SERVER && s->current.server->transfer_encoding != TransferEncoding_t::NONE) ||
              heads->get_content_length() != 0)) {
    // some systems hang until the connection closes when receiving a 204 regardless of the K-A headers
    // close if there is any body response from the origin
    ka_action = KA_Action_t::CLOSE;
  } else {
    // Determine if we are going to send either a server-generated or
    // proxy-generated chunked response to the client. If we cannot
    // trust the content-length, we may be able to chunk the response
    // to the client to keep the connection alive.
    // Insert a Transfer-Encoding header in the response if necessary.

    // check that the client protocol is HTTP/1.1 and the conf allows chunking or
    // the client protocol doesn't support chunked transfer coding (i.e. HTTP/1.0, HTTP/2, and HTTP/3)
    if (s->state_machine->get_ua_txn() && s->state_machine->get_ua_txn()->is_chunked_encoding_supported() &&
        s->client_info.http_version == HTTP_1_1 && s->txn_conf->chunking_enabled == 1 &&
        s->state_machine->get_ua_txn()->is_chunked_encoding_supported() &&
        // if we're not sending a body, don't set a chunked header regardless of server response
        !is_response_body_precluded(s->hdr_info.client_response.status_get(), s->method) &&
        // we do not need chunked encoding for internal error messages
        // that are sent to the client if the server response is not valid.
        (((s->source == Source_t::HTTP_ORIGIN_SERVER || s->source == Source_t::TRANSFORM) && s->hdr_info.server_response.valid() &&
          // if we receive a 304, we will serve the client from the
          // cache and thus do not need chunked encoding.
          s->hdr_info.server_response.status_get() != HTTPStatus::NOT_MODIFIED &&
          (s->current.server->transfer_encoding == HttpTransact::TransferEncoding_t::CHUNKED ||
           // we can use chunked encoding if we cannot trust the content
           // length (e.g. no Content-Length and Connection:close in HTTP/1.1 responses)
           s->hdr_info.trust_response_cl == false)) ||
         // handle serve from cache (read-while-write) case
         (s->source == Source_t::CACHE && s->hdr_info.trust_response_cl == false) ||
         // any transform will potentially alter the content length. try chunking if possible
         (s->source == Source_t::TRANSFORM && s->hdr_info.trust_response_cl == false))) {
      s->client_info.receive_chunked_response = true;
      heads->value_append(static_cast<std::string_view>(MIME_FIELD_TRANSFER_ENCODING),
                          static_cast<std::string_view>(HTTP_VALUE_CHUNKED), true);
    } else {
      s->client_info.receive_chunked_response = false;
    }

    // make sure no content length header is send when transfer encoding is chunked
    if (s->client_info.receive_chunked_response) {
      s->hdr_info.trust_response_cl = false;

      // And delete the header if it's already been added...
      heads->field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_LENGTH));
    }

    // Close the connection if client_info is not keep-alive.
    // Otherwise, if we cannot trust the content length, we will close the connection
    // unless we are going to use chunked encoding on HTTP/1.1 or the client issued a PUSH request
    if (s->client_info.keep_alive != HTTPKeepAlive::KEEPALIVE) {
      ka_action = KA_Action_t::DISABLED;
    } else if (s->hdr_info.trust_response_cl == false && s->state_machine->get_ua_txn() &&
               s->state_machine->get_ua_txn()->is_chunked_encoding_supported() &&
               !(s->client_info.receive_chunked_response == true ||
                 (s->method == HTTP_WKSIDX_PUSH && s->client_info.keep_alive == HTTPKeepAlive::KEEPALIVE))) {
      ka_action = KA_Action_t::CLOSE;
    } else {
      ka_action = KA_Action_t::CONNECTION;
    }
  }

  ink_assert(ka_action != KA_Action_t::UNKNOWN);

  // Insert K-A headers as necessary
  switch (ka_action) {
  case KA_Action_t::CONNECTION:
    ink_assert(s->client_info.keep_alive != HTTPKeepAlive::NO_KEEPALIVE);
    // This is a hack, we send the keep-alive header for both 1.0
    // and 1.1, to be "compatible" with Akamai.
    heads->value_set(std::string_view{c_hdr_field_str, static_cast<std::string_view::size_type>(c_hdr_field_len)}, "keep-alive"sv);
    // NOTE: if the version is 1.1 we don't need to do
    //  anything since keep-alive is assumed
    break;
  case KA_Action_t::CLOSE:
  case KA_Action_t::DISABLED:
    if (s->client_info.keep_alive != HTTPKeepAlive::NO_KEEPALIVE || (ver == HTTP_1_1)) {
      if (s->client_info.proxy_connect_hdr) {
        heads->value_set(std::string_view{c_hdr_field_str, static_cast<std::string_view::size_type>(c_hdr_field_len)}, "close"sv);
      } else if (s->state_machine->get_ua_txn() != nullptr) {
        s->state_machine->get_ua_txn()->set_close_connection(*heads);
      }
      s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
    }
    // Note: if we are 1.1, we always need to send the close
    //  header since persistent connections are the default
    break;
  default:
    ink_assert(0);
    break;
  }
} /* End HttpTransact::handle_response_keep_alive_headers */

bool
HttpTransact::delete_all_document_alternates_and_return(State *s, bool cache_hit)
{
  if (cache_hit == true) {
    // ToDo: Should support other levels of cache hits here, but the cache does not support it (yet)
    if (SQUID_HIT_RAM == s->cache_info.hit_miss_code) {
      SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_RAM_CACHE_FRESH);
    } else {
      SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_FRESH);
    }
  } else {
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_NOT_CACHED);
  }

  if ((s->method != HTTP_WKSIDX_GET) && (s->method == HTTP_WKSIDX_DELETE || s->method == HTTP_WKSIDX_PURGE)) {
    bool       valid_max_forwards;
    int        max_forwards   = -1;
    MIMEField *max_forwards_f = s->hdr_info.client_request.field_find(static_cast<std::string_view>(MIME_FIELD_MAX_FORWARDS));

    // Check the max forwards value for DELETE
    if (max_forwards_f) {
      valid_max_forwards = true;
      max_forwards       = max_forwards_f->value_get_int();
    } else {
      valid_max_forwards = false;
    }

    if (s->method == HTTP_WKSIDX_PURGE || (valid_max_forwards && max_forwards <= 0)) {
      TxnDbg(dbg_ctl_http_trans, "DELETE with Max-Forwards: %d", max_forwards);

      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);

      // allow deletes to be pipelined
      //   We want to allow keep-alive so trust the response content
      //    length.  There really isn't one and the SM will add the
      //    zero content length when setting up the transfer
      s->hdr_info.trust_response_cl = true;
      build_response(s, &s->hdr_info.client_response, s->client_info.http_version,
                     (cache_hit == true) ? HTTPStatus::OK : HTTPStatus::NOT_FOUND);

      return true;
    } else {
      if (valid_max_forwards) {
        --max_forwards;
        TxnDbg(dbg_ctl_http_trans, "Decrementing max_forwards to %d", max_forwards);
        s->hdr_info.client_request.value_set_int(static_cast<std::string_view>(MIME_FIELD_MAX_FORWARDS), max_forwards);
      }
    }
  }

  return false;
}

bool
HttpTransact::does_client_request_permit_cached_response(const OverridableHttpConfigParams *p, CacheControlResult *c, HTTPHdr *h,
                                                         char *via_string)
{
  ////////////////////////////////////////////////////////////////////////
  // If aren't ignoring client's cache directives, meet client's wishes //
  ////////////////////////////////////////////////////////////////////////

  if (!c->ignore_client_no_cache) {
    if (h->is_cache_control_set(HTTP_VALUE_NO_CACHE.c_str())) {
      return (false);
    }
    if (h->is_pragma_no_cache_set()) {
      // if we are going to send out an ims anyway,
      // no need to flag this as a no-cache.
      if (!p->cache_ims_on_client_no_cache) {
        via_string[VIA_CLIENT_REQUEST] = VIA_CLIENT_NO_CACHE;
      }
      return (false);
    }
  }

  return (true);
}

bool
HttpTransact::does_client_request_permit_dns_caching(CacheControlResult *c, HTTPHdr *h)
{
  if (h->is_pragma_no_cache_set() && h->is_cache_control_set(HTTP_VALUE_NO_CACHE.c_str()) && (!c->ignore_client_no_cache)) {
    return (false);
  }
  return (true);
}

bool
HttpTransact::does_client_request_permit_storing(CacheControlResult *c, HTTPHdr *h)
{
  ////////////////////////////////////////////////////////////////////////
  // If aren't ignoring client's cache directives, meet client's wishes //
  ////////////////////////////////////////////////////////////////////////
  if (!c->ignore_client_no_cache) {
    if (h->is_cache_control_set(HTTP_VALUE_NO_STORE.c_str())) {
      return (false);
    }
  }

  return (true);
}

int
HttpTransact::get_max_age(HTTPHdr *response)
{
  int      max_age = -1;
  uint32_t cc_mask = response->get_cooked_cc_mask();

  bool max_age_is_present = false;
  if (cc_mask & MIME_COOKED_MASK_CC_S_MAXAGE) {
    // Precedence to s-maxage
    max_age            = static_cast<int>(response->get_cooked_cc_s_maxage());
    max_age_is_present = true;
  } else if (cc_mask & MIME_COOKED_MASK_CC_MAX_AGE) {
    // If s-maxage isn't set, try max-age
    max_age            = static_cast<int>(response->get_cooked_cc_max_age());
    max_age_is_present = true;
  }

  // Negative max-age values:
  //
  // Per RFC 7234, section-1.2.1, max-age values should be a non-negative
  // value. If it is negative, therefore, the value is invalid.  Per RFC 7234,
  // section-4.2.1, invalid freshness specifications should be considered
  // stale.
  //
  // Negative return values from this function are used to indicate that the
  // max-age value was not present, resulting in a default value likely being
  // used. If the max-age is negative, therefore, we return 0 to indicate to
  // the caller that the max-age directive was present and indicates that the
  // object should be considered stale.
  if (max_age_is_present && max_age < 0) {
    max_age = 0;
  }

  return max_age;
}

int
HttpTransact::calculate_document_freshness_limit(State *s, HTTPHdr *response, time_t response_date, bool *heuristic)
{
  bool    expires_set, date_set, last_modified_set;
  time_t  date_value, expires_value, last_modified_value;
  MgmtInt min_freshness_bounds, max_freshness_bounds;
  int     freshness_limit = 0;
  int     max_age         = get_max_age(response);

  *heuristic = false;

  if (max_age >= 0) {
    freshness_limit = std::min(std::max(0, max_age), static_cast<int>(s->txn_conf->cache_guaranteed_max_lifetime));
    TxnDbg(dbg_ctl_http_match, "freshness_limit = %d", freshness_limit);
  } else {
    date_set = last_modified_set = false;
    expires_set                  = (response->presence(MIME_PRESENCE_EXPIRES) != 0);
    expires_value                = response->get_expires();
    date_value                   = response_date;

    if (date_value > 0) {
      date_set = true;
    } else {
      date_value = s->request_sent_time;
      TxnDbg(dbg_ctl_http_match, "Expires header = %" PRId64 " no date, using sent time %" PRId64, (int64_t)expires_value,
             (int64_t)date_value);
    }
    ink_assert(date_value > 0);

    // Getting the cache_sm object
    HttpCacheSM &cache_sm = s->state_machine->get_cache_sm();

    // Bypassing if loop to set freshness_limit to heuristic value
    if (expires_set && !cache_sm.is_readwhilewrite_inprogress()) {
      if (expires_value == UNDEFINED_TIME || expires_value <= date_value) {
        expires_value = date_value;
        TxnDbg(dbg_ctl_http_match, "no expires, using date %" PRId64, (int64_t)expires_value);
      }
      freshness_limit = static_cast<int>(expires_value - date_value);

      TxnDbg(dbg_ctl_http_match, "Expires: %" PRId64 ", Date: %" PRId64 ", freshness_limit = %d", (int64_t)expires_value,
             (int64_t)date_value, freshness_limit);

      freshness_limit = std::min(std::max(0, freshness_limit), static_cast<int>(s->txn_conf->cache_guaranteed_max_lifetime));
    } else {
      last_modified_value = 0;
      if (response->presence(MIME_PRESENCE_LAST_MODIFIED)) {
        last_modified_set   = true;
        last_modified_value = response->get_last_modified();
        TxnDbg(dbg_ctl_http_match, "Last Modified header = %" PRId64, (int64_t)last_modified_value);

        if (last_modified_value == UNDEFINED_TIME) {
          last_modified_set = false;
        } else if (last_modified_value > date_value) {
          last_modified_value = date_value;
          TxnDbg(dbg_ctl_http_match, "no last-modified, using sent time %" PRId64, (int64_t)last_modified_value);
        }
      }

      *heuristic = true;
      if (date_set && last_modified_set) {
        MgmtFloat f = s->txn_conf->cache_heuristic_lm_factor;
        ink_assert((f >= 0.0) && (f <= 1.0));
        ink_time_t time_since_last_modify = date_value - last_modified_value;
        int        h_freshness            = static_cast<int>(time_since_last_modify * f);
        freshness_limit                   = std::max(h_freshness, 0);
        TxnDbg(dbg_ctl_http_match,
               "heuristic: date=%" PRId64 ", lm=%" PRId64 ", time_since_last_modify=%" PRId64 ", f=%g, freshness_limit = %d",
               (int64_t)date_value, (int64_t)last_modified_value, (int64_t)time_since_last_modify, f, freshness_limit);
      } else {
        freshness_limit = s->txn_conf->cache_heuristic_min_lifetime;
        TxnDbg(dbg_ctl_http_match, "heuristic: freshness_limit = %d", freshness_limit);
      }
    }
  }

  // The freshness limit must always fall within the min and max guaranteed bounds.
  min_freshness_bounds = std::max(static_cast<MgmtInt>(0), s->txn_conf->cache_guaranteed_min_lifetime);
  max_freshness_bounds = s->txn_conf->cache_guaranteed_max_lifetime;

  // Heuristic freshness can be more strict.
  if (*heuristic) {
    min_freshness_bounds = std::max(min_freshness_bounds, s->txn_conf->cache_heuristic_min_lifetime);
    max_freshness_bounds = std::min(max_freshness_bounds, s->txn_conf->cache_heuristic_max_lifetime);
  }
  // Now clip the freshness limit.
  if (freshness_limit > max_freshness_bounds) {
    freshness_limit = max_freshness_bounds;
  }
  if (freshness_limit < min_freshness_bounds) {
    freshness_limit = min_freshness_bounds;
  }

  TxnDbg(dbg_ctl_http_match, "final freshness_limit = %d", freshness_limit);

  return (freshness_limit);
}

//////////////////////////////////////////////////////////////////////////////
//
//
//      This function takes the request and response headers for a cached
//      object, and the current HTTP parameters, and decides if the object
//      is still "fresh enough" to serve.  One of the following values
//      is returned:
//
//          Freshness_t::FRESH             Fresh enough, serve it
//          Freshness_t::WARNING           Stale but client says it's okay
//          Freshness_t::STALE             Too stale, don't use
//
//////////////////////////////////////////////////////////////////////////////
HttpTransact::Freshness_t
HttpTransact::what_is_document_freshness(State *s, HTTPHdr *client_request, HTTPHdr *cached_obj_response)
{
  bool       heuristic, do_revalidate = false;
  int        age_limit;
  int        fresh_limit;
  ink_time_t current_age, response_date;
  uint32_t   cc_mask, cooked_cc_mask;
  uint32_t   os_specifies_revalidate;

  if (s->cache_open_write_fail_action & static_cast<MgmtByte>(CacheOpenWriteFailAction_t::STALE_ON_REVALIDATE)) {
    if (is_stale_cache_response_returnable(s)) {
      TxnDbg(dbg_ctl_http_match, "cache_serve_stale_on_write_lock_fail, return FRESH");
      return (Freshness_t::FRESH);
    }
  }

  //////////////////////////////////////////////////////
  // If config file has a ttl-in-cache field set,     //
  // it has priority over any other http headers and  //
  // other configuration parameters. Negative caching //
  // is different however since the user would       //
  // rather expect their explicitly configured        //
  // negative_caching_lifetime to be used instead of  //
  // ttl-in-cache.                                    //
  //////////////////////////////////////////////////////
  if (s->cache_control.ttl_in_cache > 0) {
    auto status = static_cast<int>(cached_obj_response->status_get());
    if (s->txn_conf->negative_caching_enabled && s->txn_conf->negative_caching_list.contains(status)) {
      TxnDbg(dbg_ctl_http_match, "ttl-in-cache set, but skipping for negative cached response %d", status);
    } else {
      // what matters if ttl is set is not the age of the document
      // but for how long it has been stored in the cache (resident time)
      int resident_time = s->current.now - s->response_received_time;

      TxnDbg(dbg_ctl_http_match, "ttl-in-cache = %d, resident time = %d", s->cache_control.ttl_in_cache, resident_time);
      if (resident_time > s->cache_control.ttl_in_cache) {
        return (Freshness_t::STALE);
      } else {
        return (Freshness_t::FRESH);
      }
    }
  }

  cooked_cc_mask          = cached_obj_response->get_cooked_cc_mask();
  os_specifies_revalidate = cooked_cc_mask & (MIME_COOKED_MASK_CC_MUST_REVALIDATE | MIME_COOKED_MASK_CC_PROXY_REVALIDATE);
  cc_mask                 = MIME_COOKED_MASK_CC_NEED_REVALIDATE_ONCE;

  // Check to see if the server forces revalidation

  if ((cooked_cc_mask & cc_mask) && s->cache_control.revalidate_after <= 0) {
    TxnDbg(dbg_ctl_http_match, "document stale due to server must-revalidate");
    return Freshness_t::STALE;
  }

  response_date = cached_obj_response->get_date();
  fresh_limit   = calculate_document_freshness_limit(s, cached_obj_response, response_date, &heuristic);
  ink_assert(fresh_limit >= 0);

  current_age = HttpTransactCache::calculate_document_age(s->request_sent_time, s->response_received_time, cached_obj_response,
                                                          response_date, s->current.now);

  // First check overflow status
  // Second if current_age is under the max, use the smaller value
  // Finally we take the max of current age or guaranteed max, this ensures it will
  // age out properly, otherwise a doc will never expire if guaranteed < document max-age
  if (current_age < 0) {
    current_age = s->txn_conf->cache_guaranteed_max_lifetime;
  } else if (current_age < s->txn_conf->cache_guaranteed_max_lifetime) {
    current_age = std::min(static_cast<time_t>(s->txn_conf->cache_guaranteed_max_lifetime), current_age);
  } else {
    current_age = std::max(static_cast<time_t>(s->txn_conf->cache_guaranteed_max_lifetime), current_age);
  }

  TxnDbg(dbg_ctl_http_match, "fresh_limit:  %d  current_age: %" PRId64, fresh_limit, (int64_t)current_age);

  ink_assert(client_request == &s->hdr_info.client_request);

  if (auto scheme = client_request->url_get()->scheme_get_wksidx(); scheme == URL_WKSIDX_HTTP || scheme == URL_WKSIDX_HTTPS) {
    switch (s->txn_conf->cache_when_to_revalidate) {
    case 0: // Use cache directives or heuristic (the default value)
      // Nothing to do here
      break;
    case 1: // Stale if heuristic
      if (heuristic) {
        TxnDbg(dbg_ctl_http_match, "config requires Freshness_t::STALE because heuristic calculation");
        return (Freshness_t::STALE);
      }
      break;
    case 2: // Always stale
      TxnDbg(dbg_ctl_http_match, "config specifies always Freshness_t::STALE");
      return (Freshness_t::STALE);
    case 3: // Never stale
      TxnDbg(dbg_ctl_http_match, "config specifies always Freshness_t::FRESH");
      return (Freshness_t::FRESH);
    case 4: // Stale if IMS
      if (client_request->presence(MIME_PRESENCE_IF_MODIFIED_SINCE)) {
        TxnDbg(dbg_ctl_http_match, "config specifies Freshness_t::STALE if IMS present");
        return (Freshness_t::STALE);
      }
    default: // Bad config, ignore
      break;
    }
  }
  //////////////////////////////////////////////////////////////////////
  // the normal expiration policy allows serving a doc from cache if: //
  //     basic:          (current_age <= fresh_limit)                 //
  //                                                                  //
  // this can be modified by client Cache-Control headers:            //
  //     max-age:        (current_age <= max_age)                     //
  //     min-fresh:      (current_age <= fresh_limit - min_fresh)     //
  //     max-stale:      (current_age <= fresh_limit + max_stale)     //
  //////////////////////////////////////////////////////////////////////
  age_limit = fresh_limit; // basic constraint
  TxnDbg(dbg_ctl_http_match, "initial age limit: %d", age_limit);

  cooked_cc_mask = client_request->get_cooked_cc_mask();
  cc_mask        = (MIME_COOKED_MASK_CC_MAX_STALE | MIME_COOKED_MASK_CC_MIN_FRESH | MIME_COOKED_MASK_CC_MAX_AGE);
  if (cooked_cc_mask & cc_mask) {
    /////////////////////////////////////////////////
    // if max-stale set, relax the freshness limit //
    /////////////////////////////////////////////////
    if (cooked_cc_mask & MIME_COOKED_MASK_CC_MAX_STALE) {
      if (os_specifies_revalidate) {
        TxnDbg(dbg_ctl_http_match, "OS specifies revalidation; ignoring client's max-stale request...");
      } else {
        int max_stale_val = client_request->get_cooked_cc_max_stale();

        if (max_stale_val != INT_MAX) {
          age_limit += max_stale_val;
        } else {
          age_limit = max_stale_val;
        }
        TxnDbg(dbg_ctl_http_match, "max-stale set, age limit: %d", age_limit);
      }
    }
    /////////////////////////////////////////////////////
    // if min-fresh set, constrain the freshness limit //
    /////////////////////////////////////////////////////
    if (cooked_cc_mask & MIME_COOKED_MASK_CC_MIN_FRESH) {
      age_limit = std::min(age_limit, fresh_limit - client_request->get_cooked_cc_min_fresh());
      TxnDbg(dbg_ctl_http_match, "min_fresh set, age limit: %d", age_limit);
    }
    ///////////////////////////////////////////////////
    // if max-age set, constrain the freshness limit //
    ///////////////////////////////////////////////////
    if (!s->cache_control.ignore_client_cc_max_age && (cooked_cc_mask & MIME_COOKED_MASK_CC_MAX_AGE)) {
      int age_val = client_request->get_cooked_cc_max_age();
      if (age_val == 0) {
        do_revalidate = true;
      }
      age_limit = std::min(age_limit, age_val);
      TxnDbg(dbg_ctl_http_match, "min_fresh set, age limit: %d", age_limit);
    }
  }
  /////////////////////////////////////////////////////////
  // config file may have a "revalidate_after" field set //
  /////////////////////////////////////////////////////////
  // bug fix changed ">0" to ">=0"
  if (s->cache_control.revalidate_after >= 0) {
    // if we want the minimum of the already-computed age_limit and revalidate_after
    //      age_limit = mine(age_limit, s->cache_control.revalidate_after);

    // if instead the revalidate_after overrides all other variables
    age_limit = s->cache_control.revalidate_after;

    TxnDbg(dbg_ctl_http_match, "revalidate_after set, age limit: %d", age_limit);
  }

  TxnDbg(dbg_ctl_http_match, "document_freshness --- current_age = %" PRId64, (int64_t)current_age);
  TxnDbg(dbg_ctl_http_match, "document_freshness --- age_limit   = %d", age_limit);
  TxnDbg(dbg_ctl_http_match, "document_freshness --- fresh_limit = %d", fresh_limit);
  TxnDbg(dbg_ctl_http_seq, "document_freshness --- current_age = %" PRId64, (int64_t)current_age);
  TxnDbg(dbg_ctl_http_seq, "document_freshness --- age_limit   = %d", age_limit);
  TxnDbg(dbg_ctl_http_seq, "document_freshness --- fresh_limit = %d", fresh_limit);
  ///////////////////////////////////////////
  // now, see if the age is "fresh enough" //
  ///////////////////////////////////////////

  if (do_revalidate || !age_limit || current_age > age_limit) { // client-modified limit
    TxnDbg(dbg_ctl_http_match, "document needs revalidate/too old; "
                               "returning Freshness_t::STALE");
    return (Freshness_t::STALE);
  } else if (current_age > fresh_limit) { // original limit
    if (os_specifies_revalidate) {
      TxnDbg(dbg_ctl_http_match, "document is stale and OS specifies revalidation; "
                                 "returning Freshness_t::STALE");
      return (Freshness_t::STALE);
    }
    TxnDbg(dbg_ctl_http_match, "document is stale but no revalidation explicitly required; "
                               "returning Freshness_t::WARNING");
    return (Freshness_t::WARNING);
  } else {
    TxnDbg(dbg_ctl_http_match, "document is fresh; returning Freshness_t::FRESH");
    return (Freshness_t::FRESH);
  }
}

//////////////////////////////////////////////////////////////////////////////
//
//      HttpTransact::Authentication_t HttpTransact::AuthenticationNeeded(
//          const OverridableHttpConfigParams *p,
//          HTTPHdr *client_request,
//          HTTPHdr *obj_response)
//
//      This function takes the current client request, and the headers
//      from a potential response (e.g. from cache or proxy), and decides
//      if the object needs to be authenticated with the origin server,
//      before it can be sent to the client.
//
//      The return value describes the authentication process needed.  In
//      this function, three results are possible:
//
//          AUTHENTICATION_SUCCESS              Can serve object directly
//          AUTHENTICATION_MUST_REVALIDATE      Must revalidate with server
//          AUTHENTICATION_MUST_PROXY           Must not serve object
//
//////////////////////////////////////////////////////////////////////////////

HttpTransact::Authentication_t
HttpTransact::AuthenticationNeeded(const OverridableHttpConfigParams *p, HTTPHdr *client_request, HTTPHdr *obj_response)
{
  ///////////////////////////////////////////////////////////////////////
  // from RFC2068, sec 14.8, if a client request has the Authorization //
  // header set, we can't serve it unless the response is public, or   //
  // if it has a Cache-Control revalidate flag, and we do revalidate.  //
  ///////////////////////////////////////////////////////////////////////

  if ((p->cache_ignore_auth == 0) && client_request->presence(MIME_PRESENCE_AUTHORIZATION)) {
    if (obj_response->is_cache_control_set(HTTP_VALUE_MUST_REVALIDATE.c_str()) ||
        obj_response->is_cache_control_set(HTTP_VALUE_PROXY_REVALIDATE.c_str())) {
      return Authentication_t::MUST_REVALIDATE;
    } else if (obj_response->is_cache_control_set(HTTP_VALUE_PROXY_REVALIDATE.c_str())) {
      return Authentication_t::MUST_REVALIDATE;
    } else if (obj_response->is_cache_control_set(HTTP_VALUE_PUBLIC.c_str())) {
      return Authentication_t::SUCCESS;
    } else {
      if (obj_response->field_find("@WWW-Auth"sv) && client_request->method_get_wksidx() == HTTP_WKSIDX_GET) {
        return Authentication_t::CACHE_AUTH;
      }
      return Authentication_t::MUST_PROXY;
    }
  }

  if (obj_response->field_find("@WWW-Auth"sv) && client_request->method_get_wksidx() == HTTP_WKSIDX_GET) {
    return Authentication_t::CACHE_AUTH;
  }

  return (Authentication_t::SUCCESS);
}

void
HttpTransact::handle_parent_down(State *s)
{
  ink_assert(s->parent_result.result == ParentResultType::FAIL);

  switch (s->current.state) {
  case OUTBOUND_CONGESTION:
    build_error_response(s, HTTPStatus::SERVICE_UNAVAILABLE, "Next Hop Congested", "congestion#retryAfter");
    break;
  case INACTIVE_TIMEOUT:
    build_error_response(s, HTTPStatus::GATEWAY_TIMEOUT, "Next Hop Timeout", "timeout#inactivity");
    break;
  case ACTIVE_TIMEOUT:
    build_error_response(s, HTTPStatus::GATEWAY_TIMEOUT, "Next Hop Timeout", "timeout#activity");
    break;
  default:
    build_error_response(s, HTTPStatus::BAD_GATEWAY, "Next Hop Connection Failed", "connect");
  }
  TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}

void
HttpTransact::handle_server_down(State *s)
{
  const char *reason    = nullptr;
  const char *body_type = nullptr;
  HTTPStatus  status    = HTTPStatus::BAD_GATEWAY;

  ////////////////////////////////////////////////////////
  // FIX: all the body types below need to be filled in //
  ////////////////////////////////////////////////////////

  switch (s->current.state) {
  case CONNECTION_ALIVE: /* down while alive for unknown reason */
    ink_release_assert(s->hdr_info.response_error != ResponseError_t::NO_RESPONSE_HEADER_ERROR);
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "Unknown Error";
    body_type = "response#bad_response";
    break;
  case CONNECTION_ERROR:
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = get_error_string(s->cause_of_death_errno == 0 ? -ENET_CONNECT_FAILED : s->cause_of_death_errno);
    body_type = "connect#failed_connect";
    break;
  case OPEN_RAW_ERROR:
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "Tunnel Connection Failed";
    body_type = "connect#failed_connect";
    break;
  case CONNECTION_CLOSED:
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "Server Hangup";
    body_type = "connect#hangup";
    break;
  case ACTIVE_TIMEOUT:
    if (s->api_txn_active_timeout_value != -1) {
      TxnDbg(dbg_ctl_http_timeout, "Maximum active time of %d msec exceeded", s->api_txn_active_timeout_value);
    }
    status    = HTTPStatus::GATEWAY_TIMEOUT;
    reason    = "Maximum Transaction Time Exceeded";
    body_type = "timeout#activity";
    break;
  case INACTIVE_TIMEOUT:
    if (s->api_txn_connect_timeout_value != -1) {
      TxnDbg(dbg_ctl_http_timeout, "Maximum connect time of %d msec exceeded", s->api_txn_connect_timeout_value);
    }
    status    = HTTPStatus::GATEWAY_TIMEOUT;
    reason    = "Connection Timed Out";
    body_type = "timeout#inactivity";
    break;
  case PARSE_ERROR:
  case BAD_INCOMING_RESPONSE:
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "Invalid HTTP Response";
    body_type = "response#bad_response";
    break;
  case OUTBOUND_CONGESTION:
    status                     = HTTPStatus::SERVICE_UNAVAILABLE;
    reason                     = "Origin server congested";
    body_type                  = "congestion#retryAfter";
    s->hdr_info.response_error = ResponseError_t::TOTAL_TYPES;
    break;
  case STATE_UNDEFINED:
  case TRANSACTION_COMPLETE:
  default: /* unknown death */
    ink_release_assert(!"[handle_server_down] Unreasonable state - not down, shouldn't be here");
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = nullptr;
    body_type = "response#bad_response";
    break;
  }

  ////////////////////////////////////////////////////////
  // FIX: comment stuff above and below here, not clear //
  ////////////////////////////////////////////////////////

  switch (s->hdr_info.response_error) {
  case ResponseError_t::NON_EXISTANT_RESPONSE_HEADER:
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "No Response Header From Server";
    body_type = "response#bad_response";
    break;
  case ResponseError_t::MISSING_REASON_PHRASE:
  case ResponseError_t::NO_RESPONSE_HEADER_ERROR:
  case ResponseError_t::NOT_A_RESPONSE_HEADER:
#ifdef REALLY_NEED_TO_CHECK_DATE_VALIDITY
  case ResponseError_t::BOGUS_OR_NO_DATE_IN_RESPONSE:
#endif
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "Malformed Server Response";
    body_type = "response#bad_response";
    break;
  case ResponseError_t::MISSING_STATUS_CODE:
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "Malformed Server Response Status";
    body_type = "response#bad_response";
    break;
  default:
    break;
  }

  if (reason == nullptr) {
    status    = HTTPStatus::BAD_GATEWAY;
    reason    = "Server Connection Failed";
    body_type = "connect#failed_connect";
  }

  build_error_response(s, status, reason, body_type);

  return;
}

// return true if the response to the given request is likely cacheable
// This function is called by build_request() to determine if the conditional
// headers should be removed from server request.
bool
HttpTransact::is_request_likely_cacheable(State *s, HTTPHdr *request)
{
  if ((s->method == HTTP_WKSIDX_GET || s->api_req_cacheable) && !s->api_server_response_no_store &&
      !request->presence(MIME_PRESENCE_AUTHORIZATION) &&
      (!request->presence(MIME_PRESENCE_RANGE) || s->txn_conf->cache_range_write)) {
    return true;
  }
  return false;
}

bool
HttpTransact::is_fresh_cache_hit(CacheLookupResult_t r)
{
  return (r == CacheLookupResult_t::HIT_FRESH || r == CacheLookupResult_t::HIT_WARNING);
}

bool
HttpTransact::is_cache_hit(CacheLookupResult_t r)
{
  return (is_fresh_cache_hit(r) || r == CacheLookupResult_t::HIT_STALE);
}

void
HttpTransact::build_request(State *s, HTTPHdr *base_request, HTTPHdr *outgoing_request, HTTPVersion outgoing_version)
{
  // this part is to restore the original URL in case, multiple cache
  // lookups have happened - client request has been changed as the result
  //
  // notice that currently, based_request IS client_request
  if (base_request == &s->hdr_info.client_request) {
    if (!s->redirect_info.redirect_in_process) {
      // this is for multiple cache lookup
      URL *o_url = &s->cache_info.original_url;

      if (o_url->valid()) {
        base_request->url_get()->copy(o_url);
      }
    }

    // Perform any configured normalization (including per-remap-rule configuration overrides) of the Accept-Encoding header
    // field (if any).  This has to be done in the request from the client, for the benefit of the gzip plugin.
    //
    HttpTransactHeaders::normalize_accept_encoding(s->txn_conf, base_request);
  }

  HttpTransactHeaders::copy_header_fields(base_request, outgoing_request, s->txn_conf->fwd_proxy_auth_to_parent);
  add_client_ip_to_outgoing_request(s, outgoing_request);
  HttpTransactHeaders::add_forwarded_field_to_request(s, outgoing_request);
  HttpTransactHeaders::remove_privacy_headers_from_request(s->http_config_param, s->txn_conf, outgoing_request);
  HttpTransactHeaders::add_global_user_agent_header_to_request(s->txn_conf, outgoing_request);
  handle_request_keep_alive_headers(s, outgoing_version, outgoing_request);

  if (s->next_hop_scheme < 0) {
    s->next_hop_scheme = URL_WKSIDX_HTTP;
  }
  if (s->orig_scheme < 0) {
    s->orig_scheme = URL_WKSIDX_HTTP;
  }

  if (s->txn_conf->insert_request_via_string) {
    HttpTransactHeaders::insert_via_header_in_request(s, outgoing_request);
  }

  // We build 1.1 request header and then convert as necessary to
  //  the appropriate version in HttpTransact::build_request
  outgoing_request->version_set(HTTP_1_1);

  // Make sure our request version is defined
  ink_assert(outgoing_version != HTTP_0_9);

  // HttpTransactHeaders::convert_request(outgoing_version, outgoing_request); // commented out this idea
  URL *url = outgoing_request->url_get();

  // Remove fragment from upstream URL
  url->fragment_set({nullptr, 0});

  // Check whether a Host header field is missing from a 1.0 or 1.1 request.
  if (outgoing_version != HTTP_0_9 && !outgoing_request->presence(MIME_PRESENCE_HOST)) {
    auto host{url->host_get()};

    // Add a ':port' to the HOST header if the request is not going
    // to the default port.
    int port = url->port_get();
    if (port != url_canonicalize_port(URLType::HTTP, 0)) {
      auto  host_len{static_cast<int>(host.length())};
      char *buf = static_cast<char *>(alloca(host_len + 15));
      memcpy(buf, host.data(), host_len);
      host_len += snprintf(buf + host_len, 15, ":%d", port);
      outgoing_request->value_set(static_cast<std::string_view>(MIME_FIELD_HOST),
                                  std::string_view{buf, static_cast<std::string_view::size_type>(host_len)});
    } else {
      outgoing_request->value_set(static_cast<std::string_view>(MIME_FIELD_HOST), host);
    }
  }

  // Figure out whether to force the outgoing request URL into absolute or relative styles.
  if (outgoing_request->method_get_wksidx() == HTTP_WKSIDX_CONNECT) {
    // CONNECT method requires a target in the URL, so always force it from the Host header.
    outgoing_request->set_url_target_from_host_field();
  } else if (s->current.request_to == ResolveInfo::PARENT_PROXY && parent_is_proxy(s)) {
    // If we have a parent proxy set the URL target field.
    if (!outgoing_request->is_target_in_url()) {
      TxnDbg(dbg_ctl_http_trans, "adding target to URL for parent proxy");
      outgoing_request->set_url_target_from_host_field();
    }
  } else if (s->next_hop_scheme == URL_WKSIDX_HTTP || s->next_hop_scheme == URL_WKSIDX_HTTPS ||
             s->next_hop_scheme == URL_WKSIDX_WS || s->next_hop_scheme == URL_WKSIDX_WSS) {
    // Otherwise, remove the URL target from HTTP and Websocket URLs since certain origins
    // cannot deal with absolute URLs.
    TxnDbg(dbg_ctl_http_trans, "removing host name from url");
    HttpTransactHeaders::remove_host_name_from_url(outgoing_request);
  }

  // If we are going to a peer cache and want to use the pristine URL, get it from the base request
  if (s->parent_result.use_pristine) {
    auto host{s->unmapped_url.host_get()};
    outgoing_request->url_get()->host_set(host);
  }

  // If the response is most likely not cacheable, eg, request with Authorization,
  // do we really want to remove conditional headers to get large 200 response?
  // Answer: NO.  Since if the response is most likely not cacheable,
  // we don't remove conditional headers so that for a non-200 response
  // from the O.S., we will save bandwidth between proxy and O.S.
  if (s->current.mode == ProxyMode_t::GENERIC) {
    if (is_request_likely_cacheable(s, base_request)) {
      if (s->txn_conf->cache_when_to_revalidate != 4) {
        TxnDbg(dbg_ctl_http_trans, "request like cacheable and conditional headers removed");
        HttpTransactHeaders::remove_conditional_headers(outgoing_request);
      } else {
        TxnDbg(dbg_ctl_http_trans, "request like cacheable but keep conditional headers");
      }
    } else {
      // In this case, we send a conditional request
      // instead of the normal non-conditional request.
      TxnDbg(dbg_ctl_http_trans, "request not like cacheable and conditional headers not removed");
    }
  }

  if (s->hdr_info.client_request.m_100_continue_sent) {
    HttpTransactHeaders::remove_100_continue_headers(s, outgoing_request);
    TxnDbg(dbg_ctl_http_trans, "request expect 100-continue headers removed");
  }

  if (base_request->is_early_data()) {
    outgoing_request->value_set_int(static_cast<std::string_view>(MIME_FIELD_EARLY_DATA), 1);
  }

  s->request_sent_time = ink_local_time();
  s->current.now       = s->request_sent_time;

  // The assert is backwards in this case because request is being (re)sent.
  ink_assert(s->request_sent_time >= s->response_received_time);

  TxnDbg(dbg_ctl_http_trans, "request_sent_time: %" PRId64, (int64_t)s->request_sent_time);
  dump_header(dbg_ctl_http_hdrs, outgoing_request, s->state_machine_id(), "Proxy's Request");

  Metrics::Counter::increment(http_rsb.outgoing_requests);
}

// build a (status_code) response based upon the given info

void
HttpTransact::build_response(State *s, HTTPHdr *base_response, HTTPHdr *outgoing_response, HTTPVersion outgoing_version)
{
  build_response(s, base_response, outgoing_response, outgoing_version, HTTPStatus::NONE, nullptr);
  return;
}

void
HttpTransact::build_response(State *s, HTTPHdr *outgoing_response, HTTPVersion outgoing_version, HTTPStatus status_code,
                             const char *reason_phrase)
{
  build_response(s, nullptr, outgoing_response, outgoing_version, status_code, reason_phrase);
  return;
}

void
HttpTransact::build_response(State *s, HTTPHdr *base_response, HTTPHdr *outgoing_response, HTTPVersion outgoing_version,
                             HTTPStatus status_code, const char *reason_phrase)
{
  if (reason_phrase == nullptr) {
    if (status_code != HTTPStatus::NONE) {
      reason_phrase = http_hdr_reason_lookup(status_code);
      Dbg(dbg_ctl_http_transact, "Using reason phrase from status %d: %s", static_cast<int>(status_code), reason_phrase);
    } else if (base_response != nullptr && base_response->status_get() != HTTPStatus::NONE) {
      HTTPStatus const base_response_status = base_response->status_get();
      reason_phrase                         = http_hdr_reason_lookup(base_response_status);
      Dbg(dbg_ctl_http_transact, "Using reason phrase from base_response status %d: %s", static_cast<int>(base_response_status),
          reason_phrase);
    } else {
      // We have to set some value for build_base_response which expects a
      // non-nullptr reason_phrase.
      reason_phrase = http_hdr_reason_lookup(status_code);
      Dbg(dbg_ctl_http_transact, "Using HTTPStatus::NONE reason phrase %d: %s", static_cast<int>(status_code), reason_phrase);
    }
  }

  if (base_response == nullptr) {
    HttpTransactHeaders::build_base_response(outgoing_response, status_code, reason_phrase, strlen(reason_phrase), s->current.now);
  } else {
    if ((status_code == HTTPStatus::NONE) || (status_code == base_response->status_get())) {
      HttpTransactHeaders::copy_header_fields(base_response, outgoing_response, s->txn_conf->fwd_proxy_auth_to_parent);

      if (s->txn_conf->insert_age_in_response) {
        HttpTransactHeaders::insert_time_and_age_headers_in_response(s->request_sent_time, s->response_received_time,
                                                                     s->current.now, base_response, outgoing_response);
      }

      // Note: We need to handle the "Content-Length" header first here
      //  since handle_content_length_header()
      //  determines whether we accept origin server's content-length.
      //  We need to have made a decision regard the content-length
      //  before processing the keep_alive headers
      //
      handle_content_length_header(s, outgoing_response, base_response);
    } else {
      switch (status_code) {
      case HTTPStatus::NOT_MODIFIED:
        HttpTransactHeaders::build_base_response(outgoing_response, status_code, reason_phrase, strlen(reason_phrase),
                                                 s->current.now);

        // According to RFC 2616, Section 10.3.5,
        // a 304 response MUST contain Date header,
        // Etag and/or Content-location header,
        // and Expires, Cache-control, and Vary
        // (if they might be changed).
        // Since a proxy doesn't know if a header differs from
        // a user agent's cached document or not, all are sent.
        {
          static const struct {
            std::string_view name;
            uint64_t         presence;
          } fields[] = {
            {static_cast<std::string_view>(MIME_FIELD_ETAG),             MIME_PRESENCE_ETAG            },
            {static_cast<std::string_view>(MIME_FIELD_CONTENT_LOCATION), MIME_PRESENCE_CONTENT_LOCATION},
            {static_cast<std::string_view>(MIME_FIELD_EXPIRES),          MIME_PRESENCE_EXPIRES         },
            {static_cast<std::string_view>(MIME_FIELD_CACHE_CONTROL),    MIME_PRESENCE_CACHE_CONTROL   },
            {static_cast<std::string_view>(MIME_FIELD_VARY),             MIME_PRESENCE_VARY            },
          };

          for (size_t i = 0; i < countof(fields); i++) {
            if (base_response->presence(fields[i].presence)) {
              MIMEField *field;

              field = base_response->field_find(fields[i].name);
              ink_assert(field != nullptr);
              auto value{field->value_get()};
              outgoing_response->value_append(fields[i].name, value, false);
              if (field->has_dups()) {
                field = field->m_next_dup;
                while (field) {
                  value = field->value_get();
                  outgoing_response->value_append(fields[i].name, value, true);
                  field = field->m_next_dup;
                }
              }
            }
          }
        }
        break;

      case HTTPStatus::PRECONDITION_FAILED:
      // fall through
      case HTTPStatus::RANGE_NOT_SATISFIABLE:
        HttpTransactHeaders::build_base_response(outgoing_response, status_code, reason_phrase, strlen(reason_phrase),
                                                 s->current.now);
        break;
      default:
        // ink_assert(!"unexpected status code in build_response()");
        break;
      }
    }
  }

  // the following is done whether base_response == NULL or not

  // If the response is prohibited from containing a body,
  //  we know the content length is trustable for keep-alive
  if (is_response_body_precluded(status_code, s->method)) {
    s->hdr_info.trust_response_cl = true;
  }

  handle_response_keep_alive_headers(s, outgoing_version, outgoing_response);

  if (s->next_hop_scheme < 0) {
    s->next_hop_scheme = URL_WKSIDX_HTTP;
  }

  // Add HSTS header (Strict-Transport-Security) if max-age is set and the request was https
  // and the incoming request was remapped correctly
  if (s->orig_scheme == URL_WKSIDX_HTTPS && s->txn_conf->proxy_response_hsts_max_age >= 0 && s->url_remap_success == true) {
    TxnDbg(dbg_ctl_http_hdrs, "hsts max-age=%" PRId64, s->txn_conf->proxy_response_hsts_max_age);
    HttpTransactHeaders::insert_hsts_header_in_response(s, outgoing_response);
  }

  if (s->txn_conf->insert_response_via_string) {
    HttpTransactHeaders::insert_via_header_in_response(s, outgoing_response);
  }

  // When converting a response, only set a reason phrase if one was not already
  // set via some explicit call above.
  char const *reason_phrase_for_convert = nullptr;
  if (outgoing_response->reason_get().empty()) {
    reason_phrase_for_convert = reason_phrase;
  }
  HttpTransactHeaders::convert_response(outgoing_version, outgoing_response, reason_phrase_for_convert);

  // process reverse mappings on the location header
  // TS-1364: do this regardless of response code
  response_url_remap(outgoing_response, s->state_machine->m_remap);

  if (s->http_config_param->enable_http_stats) {
    HttpTransactHeaders::generate_and_set_squid_codes(outgoing_response, s->via_string, &s->squid_codes);
  }

  HttpTransactHeaders::add_server_header_to_response(s->txn_conf, outgoing_response);

  if (s->state_machine->get_ua_txn() && s->state_machine->get_ua_txn()->get_proxy_ssn()->is_draining()) {
    HttpTransactHeaders::add_connection_close(outgoing_response);
  }

  if (dbg_ctl_http_hdrs.on()) {
    if (base_response) {
      dump_header(dbg_ctl_http_hdrs, base_response, s->state_machine_id(), "Base Header for Building Response");
    }

    dump_header(dbg_ctl_http_hdrs, outgoing_response, s->state_machine_id(), "Proxy's Response 2");
  }

  return;
}

//////////////////////////////////////////////////////////////////////////////
//
//      void HttpTransact::build_error_response(
//          State *s,
//          HTTPStatus status_code,
//          char *reason_phrase_or_null,
//          char *error_body_type,
//          char *format, ...)
//
//      This method sets the requires state for an error reply, including
//      the error text, status code, reason phrase, and reply headers.  The
//      caller calls the method with the HttpTransact::State <s>, the
//      HTTP status code <status_code>, a user-specified reason phrase
//      string (or NULL) <reason_phrase_or_null>, and a printf-like
//      text format and arguments which are appended to the error text.
//
//      The <error_body_type> is the error message type, as specified by
//      the HttpBodyFactory customized error page system.
//
//      If the descriptive text <format> is not NULL or "", it is also
//      added to the error text body as descriptive text in the error body.
//      If <reason_phrase_or_null> is NULL, the default HTTP reason phrase
//      is used.  This routine DOES NOT check for buffer overflows.  The
//      caller should keep the messages small to be sure the error text
//      fits in the error buffer (ok, it's nasty, but at least I admit it!).
//
//////////////////////////////////////////////////////////////////////////////
void
HttpTransact::build_error_response(State *s, HTTPStatus status_code, const char *reason_phrase_or_null, const char *error_body_type)
{
  char body_language[256], body_type[256];

  if (nullptr == error_body_type) {
    error_body_type = "default";
  }

  // Make sure that if this error occurred before we initialized the state variables that we do now.
  initialize_state_variables_from_request(s, &s->hdr_info.client_request);

  //////////////////////////////////////////////////////
  //  If there is a request body, we must disable     //
  //  keep-alive to prevent the body being read as    //
  //  the next header (unless we've already drained   //
  //  which we do for NTLM auth)                      //
  //////////////////////////////////////////////////////
  if (status_code == HTTPStatus::REQUEST_TIMEOUT || s->hdr_info.client_request.get_content_length() != 0 ||
      s->client_info.transfer_encoding == HttpTransact::TransferEncoding_t::CHUNKED) {
    s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  } else {
    // We don't have a request body.  Since we are
    //  generating the error, we know we can trust
    //  the content-length
    s->hdr_info.trust_response_cl = true;
  }
  // If transparent and the forward server connection looks unhappy don't
  // keep alive the ua connection.
  if ((s->state_machine->get_ua_txn() && s->state_machine->get_ua_txn()->is_outbound_transparent()) &&
      (status_code == HTTPStatus::INTERNAL_SERVER_ERROR || status_code == HTTPStatus::GATEWAY_TIMEOUT ||
       status_code == HTTPStatus::BAD_GATEWAY || status_code == HTTPStatus::SERVICE_UNAVAILABLE)) {
    s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  }

  // If there is a parse error on reading the request it can leave reading the request stream in an undetermined state
  if (status_code == HTTPStatus::BAD_REQUEST) {
    s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  }

  switch (status_code) {
  case HTTPStatus::BAD_REQUEST:
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_ERROR);
    // Did the via error already get set by the loop detection
    if (s->via_string[VIA_ERROR_TYPE] != VIA_ERROR_LOOP_DETECTED) {
      SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_HEADER_SYNTAX);
    }
    break;
  case HTTPStatus::BAD_GATEWAY:
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_CONNECTION);
    break;
  case HTTPStatus::GATEWAY_TIMEOUT:
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_TIMEOUT);
    break;
  case HTTPStatus::NOT_FOUND:
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_SERVER);
    break;
  case HTTPStatus::FORBIDDEN:
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_ERROR);
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_FORBIDDEN);
    break;
  case HTTPStatus::HTTPVER_NOT_SUPPORTED:
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_ERROR);
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_SERVER);
    break;
  case HTTPStatus::INTERNAL_SERVER_ERROR:
    if (Dns_error_body == error_body_type) {
      SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_DNS_FAILURE);
    } else {
      SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_UNKNOWN);
    }
    break;
  case HTTPStatus::MOVED_TEMPORARILY:
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_MOVED_TEMPORARILY);
    break;
  case HTTPStatus::PROXY_AUTHENTICATION_REQUIRED:
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_ERROR);
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_AUTHORIZATION);
    break;
  case HTTPStatus::UNAUTHORIZED:
    SET_VIA_STRING(VIA_CLIENT_REQUEST, VIA_CLIENT_ERROR);
    SET_VIA_STRING(VIA_ERROR_TYPE, VIA_ERROR_AUTHORIZATION);
    break;
  default:
    break;
  }

  const char *reason_phrase =
    (reason_phrase_or_null ? reason_phrase_or_null : const_cast<char *>(http_hdr_reason_lookup(status_code)));
  if (unlikely(!reason_phrase)) {
    reason_phrase = "Unknown HTTP Status";
  }

  // set the source to internal so that chunking is handled correctly
  s->source = Source_t::INTERNAL;
  build_response(s, &s->hdr_info.client_response, s->client_info.http_version, status_code, reason_phrase);

  if (status_code == HTTPStatus::SERVICE_UNAVAILABLE) {
    int retry_after = 0;

    if (auto ret_tmp{s->hdr_info.client_response.value_get(static_cast<std::string_view>(MIME_FIELD_RETRY_AFTER))};
        !ret_tmp.empty()) {
      retry_after = static_cast<int>(ret_tmp.length());
    }
    s->congestion_control_crat = retry_after;
  } else if (status_code == HTTPStatus::BAD_REQUEST) {
    // Close the client connection after a malformed request
    s->client_info.keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
  }

  // Add a bunch of headers to make sure that caches between
  // the Traffic Server and the client do not cache the error
  // page.
  s->hdr_info.client_response.value_set(static_cast<std::string_view>(MIME_FIELD_CACHE_CONTROL), "no-store"sv);
  // Make sure there are no Expires and Last-Modified headers.
  s->hdr_info.client_response.field_delete(static_cast<std::string_view>(MIME_FIELD_EXPIRES));
  s->hdr_info.client_response.field_delete(static_cast<std::string_view>(MIME_FIELD_LAST_MODIFIED));

  if ((status_code == HTTPStatus::PERMANENT_REDIRECT || status_code == HTTPStatus::TEMPORARY_REDIRECT ||
       status_code == HTTPStatus::MOVED_TEMPORARILY || status_code == HTTPStatus::MOVED_PERMANENTLY) &&
      s->remap_redirect) {
    s->hdr_info.client_response.value_set(static_cast<std::string_view>(MIME_FIELD_LOCATION), s->remap_redirect);
  }

  ////////////////////////////////////////////////////////////////////
  // create the error message using the "body factory", which will  //
  // build a customized error message if available, or generate the //
  // old style internal defaults otherwise --- the body factory     //
  // supports language targeting using the Accept-Language header   //
  ////////////////////////////////////////////////////////////////////

  int64_t len;
  char   *new_msg;

  new_msg = body_factory->fabricate_with_old_api(
    error_body_type, s, s->http_config_param->body_factory_response_max_size, &len, body_language, sizeof(body_language), body_type,
    sizeof(body_type), s->internal_msg_buffer_size, s->internal_msg_buffer_size ? s->internal_msg_buffer : nullptr);

  // After the body factory is called, a new "body" is allocated, and we must replace it. It is
  // unfortunate that there's no way to avoid this fabrication even when there is no substitutions...
  s->free_internal_msg_buffer();
  if (len == 0) {
    // If the file is empty, we may have a malloc(1) buffer. Release it.
    new_msg = static_cast<char *>(ats_free_null(new_msg));
  }
  s->internal_msg_buffer                     = new_msg;
  s->internal_msg_buffer_size                = len;
  s->internal_msg_buffer_fast_allocator_size = -1;

  if (len > 0) {
    s->hdr_info.client_response.value_set(static_cast<std::string_view>(MIME_FIELD_CONTENT_TYPE), body_type);
    s->hdr_info.client_response.value_set(static_cast<std::string_view>(MIME_FIELD_CONTENT_LANGUAGE), body_language);
  } else {
    s->hdr_info.client_response.field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_TYPE));
    s->hdr_info.client_response.field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_LANGUAGE));
  }

  s->next_action = StateMachineAction_t::SEND_ERROR_CACHE_NOOP;
  return;
}

void
HttpTransact::build_redirect_response(State *s)
{
  TxnDbg(dbg_ctl_http_redirect, "Entering HttpTransact::build_redirect_response");
  URL        *u;
  const char *new_url = nullptr;
  int         new_url_len;
  char       *to_free = nullptr;

  HTTPStatus status_code   = HTTPStatus::MOVED_TEMPORARILY;
  char      *reason_phrase = const_cast<char *>(http_hdr_reason_lookup(status_code));

  build_response(s, &s->hdr_info.client_response, s->client_info.http_version, status_code, reason_phrase);

  //////////////////////////////////////////////////////////
  // figure out what new url should be.  this little hack //
  // inserts expanded hostname into old url in order to   //
  // get scheme information, then puts the old url back.  //
  //////////////////////////////////////////////////////////
  u = s->hdr_info.client_request.url_get();
  auto old_host{u->host_get()};
  u->host_set({s->dns_info.lookup_name});
  new_url = to_free = u->string_get(&s->arena, &new_url_len);
  assert(to_free != nullptr); // needed to avoid false positive nullptr deref from clang-analyzer.
  // The following code may not be needed if string_get above always returns non nullptr,
  // or we must guard str_free at the end with if (to_free) otherwise.
  if (new_url == nullptr) {
    new_url = "";
  }
  u->host_set(old_host);

  //////////////////////////
  // set redirect headers //
  //////////////////////////
  HTTPHdr *h = &s->hdr_info.client_response;
  if (s->txn_conf->insert_response_via_string) {
    constexpr auto pa{"Proxy-agent"sv};

    h->value_append(
      pa, std::string_view{s->http_config_param->proxy_response_via_string,
                           static_cast<std::string_view::size_type>(s->http_config_param->proxy_response_via_string_len)});
  }
  h->value_set(static_cast<std::string_view>(MIME_FIELD_LOCATION),
               std::string_view{new_url, static_cast<std::string_view::size_type>(new_url_len)});

  //////////////////////////
  // set descriptive text //
  //////////////////////////
  s->free_internal_msg_buffer();
  s->internal_msg_buffer_fast_allocator_size = -1;
  // template redirect#temporarily can not be used here since there is no way to pass the computed url to the template.
  s->internal_msg_buffer = body_factory->getFormat(8192, &s->internal_msg_buffer_size, "%s <a href=\"%s\">%s</a>.  %s.",
                                                   "The document you requested is now", new_url, new_url,
                                                   "Please update your documents and bookmarks accordingly", nullptr);

  h->set_content_length(s->internal_msg_buffer_size);
  h->value_set(static_cast<std::string_view>(MIME_FIELD_CONTENT_TYPE), "text/html"sv);

  s->arena.str_free(to_free);
}

const char *
HttpTransact::get_error_string(int erno)
{
  if (erno >= 0) {
    return (strerror(erno));
  } else {
    switch (-erno) {
    case ENET_THROTTLING:
      return ("throttling");
    case ESOCK_DENIED:
      return ("socks error - denied");
    case ESOCK_TIMEOUT:
      return ("socks error - timeout");
    case ESOCK_NO_SOCK_SERVER_CONN:
      return ("socks error - no server connection");
    //              this assumes that the following case occurs
    //              when HttpSM.cc::state_origin_server_read_response
    //                 receives an HTTP_EVENT_EOS. (line 1729 in HttpSM.cc,
    //                 version 1.145.2.13.2.57)
    case ENET_CONNECT_FAILED:
      return ("connect failed");
    case UNKNOWN_INTERNAL_ERROR:
      return ("internal error - server connection terminated");
    default:
      return ("");
    }
  }
}

ink_time_t
ink_local_time()
{
  return ink_get_hrtime() / HRTIME_SECOND;
}

//
// The stat functions
//

void
HttpTransact::milestone_start_api_time(State *s)
{
  s->state_machine->api_timer = ink_get_hrtime();
}

void
HttpTransact::milestone_update_api_time(State *s)
{
  s->state_machine->milestone_update_api_time();
}

void
HttpTransact::origin_server_connection_speed(ink_hrtime transfer_time, int64_t nbytes)
{
  float bytes_per_hrtime =
    (transfer_time == 0) ? (nbytes) : (static_cast<float>(nbytes) / static_cast<float>(static_cast<int64_t>(transfer_time)));
  int bytes_per_sec = static_cast<int>(bytes_per_hrtime * HRTIME_SECOND);

  if (bytes_per_sec <= 100) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_100);
  } else if (bytes_per_sec <= 1024) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_1k);
  } else if (bytes_per_sec <= 10240) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_10k);
  } else if (bytes_per_sec <= 102400) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_100k);
  } else if (bytes_per_sec <= 1048576) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_1M);
  } else if (bytes_per_sec <= 10485760) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_10M);
  } else if (bytes_per_sec <= 104857600) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_100M);
  } else if (bytes_per_sec <= 2 * 104857600) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_200M);
  } else if (bytes_per_sec <= 4 * 104857600) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_400M);
  } else if (bytes_per_sec <= 8 * 104857600) {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_800M);
  } else {
    Metrics::Counter::increment(http_rsb.user_agent_speed_bytes_per_sec_1G);
  }
  return;
}

void
HttpTransact::user_agent_connection_speed(ink_hrtime transfer_time, int64_t nbytes)
{
  float bytes_per_hrtime =
    (transfer_time == 0) ? (nbytes) : (static_cast<float>(nbytes) / static_cast<float>(static_cast<int64_t>(transfer_time)));
  int64_t bytes_per_sec = static_cast<int64_t>(bytes_per_hrtime * HRTIME_SECOND);

  if (bytes_per_sec <= 100) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_100);
  } else if (bytes_per_sec <= 1024) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_1k);
  } else if (bytes_per_sec <= 10240) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_10k);
  } else if (bytes_per_sec <= 102400) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_100k);
  } else if (bytes_per_sec <= 1048576) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_1M);
  } else if (bytes_per_sec <= 10485760) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_10M);
  } else if (bytes_per_sec <= 104857600) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_100M);
  } else if (bytes_per_sec <= 2 * 104857600) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_200M);
  } else if (bytes_per_sec <= 4 * 104857600) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_400M);
  } else if (bytes_per_sec <= 8 * 104857600) {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_800M);
  } else {
    Metrics::Counter::increment(http_rsb.origin_server_speed_bytes_per_sec_1G);
  }
}

/*
 * added request_process_time stat for loadshedding foo
 */
void
HttpTransact::client_result_stat(State *s, ink_hrtime total_time, ink_hrtime request_process_time)
{
  ClientTransactionResult_t client_transaction_result = ClientTransactionResult_t::UNDEFINED;

  ///////////////////////////////////////////////////////
  // don't count errors we generated as hits or misses //
  ///////////////////////////////////////////////////////
  auto client_response_status = HTTPStatus::NONE;
  if (s->hdr_info.client_response.valid()) {
    client_response_status = s->hdr_info.client_response.status_get();
  }

  if ((s->source == Source_t::INTERNAL) && client_response_status >= HTTPStatus::BAD_REQUEST) {
    client_transaction_result = ClientTransactionResult_t::ERROR_OTHER;
  }

  switch (s->squid_codes.log_code) {
  case SquidLogCode::ERR_CONNECT_FAIL:
    Metrics::Counter::increment(http_rsb.cache_miss_cold);
    client_transaction_result = ClientTransactionResult_t::ERROR_CONNECT_FAIL;
    break;

  case SquidLogCode::TCP_CF_HIT:
    Metrics::Counter::increment(http_rsb.cache_hit_rww);
    client_transaction_result = ClientTransactionResult_t::HIT_FRESH;
    break;

  case SquidLogCode::TCP_MEM_HIT:
    Metrics::Counter::increment(http_rsb.cache_hit_mem_fresh);
    // fallthrough

  case SquidLogCode::TCP_HIT:
    // It's possible to have two stat's instead of one, if needed.
    Metrics::Counter::increment(http_rsb.cache_hit_fresh);
    client_transaction_result = ClientTransactionResult_t::HIT_FRESH;
    break;

  case SquidLogCode::TCP_REFRESH_HIT:
    Metrics::Counter::increment(http_rsb.cache_hit_reval);
    client_transaction_result = ClientTransactionResult_t::HIT_REVALIDATED;
    break;

  case SquidLogCode::TCP_IMS_HIT:
    Metrics::Counter::increment(http_rsb.cache_hit_ims);
    client_transaction_result = ClientTransactionResult_t::HIT_FRESH;
    break;

  case SquidLogCode::TCP_REF_FAIL_HIT:
    Metrics::Counter::increment(http_rsb.cache_hit_stale_served);
    client_transaction_result = ClientTransactionResult_t::HIT_FRESH;
    break;

  case SquidLogCode::TCP_MISS:
    if ((GET_VIA_STRING(VIA_CACHE_RESULT) == VIA_IN_CACHE_NOT_ACCEPTABLE) || (GET_VIA_STRING(VIA_CACHE_RESULT) == VIA_CACHE_MISS)) {
      Metrics::Counter::increment(http_rsb.cache_miss_cold);
      client_transaction_result = ClientTransactionResult_t::MISS_COLD;
    } else {
      // FIX: what case is this for?  can it ever happen?
      Metrics::Counter::increment(http_rsb.cache_miss_uncacheable);
      client_transaction_result = ClientTransactionResult_t::MISS_UNCACHABLE;
    }
    break;

  case SquidLogCode::TCP_REFRESH_MISS:
    Metrics::Counter::increment(http_rsb.cache_miss_changed);
    client_transaction_result = ClientTransactionResult_t::MISS_CHANGED;
    break;

  case SquidLogCode::TCP_CLIENT_REFRESH:
    Metrics::Counter::increment(http_rsb.cache_miss_client_no_cache);
    client_transaction_result = ClientTransactionResult_t::MISS_CLIENT_NO_CACHE;
    break;

  case SquidLogCode::TCP_IMS_MISS:
    Metrics::Counter::increment(http_rsb.cache_miss_ims);
    client_transaction_result = ClientTransactionResult_t::MISS_COLD;
    break;

  case SquidLogCode::TCP_SWAPFAIL:
    Metrics::Counter::increment(http_rsb.cache_read_error);
    client_transaction_result = ClientTransactionResult_t::HIT_FRESH;
    break;

  case SquidLogCode::ERR_READ_TIMEOUT:
  case SquidLogCode::TCP_DENIED:
    // No cache result due to error
    client_transaction_result = ClientTransactionResult_t::ERROR_OTHER;
    break;

  default:
    // FIX: What is the conditional below doing?
    //          if (s->local_trans_stats[http_cache_lookups_stat].count == 1L)
    //              HTTP_INCREMENT_DYN_STAT(http_cache_miss_cold_stat);

    // FIX: I suspect the following line should not be set here,
    //      because it overrides the error classification above.
    //      Commenting out.
    // client_transaction_result = ClientTransactionResult_t::MISS_COLD;

    break;
  }

  //////////////////////////////////////////
  // don't count aborts as hits or misses //
  //////////////////////////////////////////
  if (s->client_info.abort == ABORTED) {
    client_transaction_result = ClientTransactionResult_t::ERROR_ABORT;
  }
  // Count the status codes, assuming the client didn't abort (i.e. there is an m_http)
  if ((s->source != Source_t::NONE) && (s->client_info.abort == DIDNOT_ABORT)) {
    switch (static_cast<int>(client_response_status)) {
    case 100:
      Metrics::Counter::increment(http_rsb.response_status_100_count);
      break;
    case 101:
      Metrics::Counter::increment(http_rsb.response_status_101_count);
      break;
    case 200:
      Metrics::Counter::increment(http_rsb.response_status_200_count);
      break;
    case 201:
      Metrics::Counter::increment(http_rsb.response_status_201_count);
      break;
    case 202:
      Metrics::Counter::increment(http_rsb.response_status_202_count);
      break;
    case 203:
      Metrics::Counter::increment(http_rsb.response_status_203_count);
      break;
    case 204:
      Metrics::Counter::increment(http_rsb.response_status_204_count);
      break;
    case 205:
      Metrics::Counter::increment(http_rsb.response_status_205_count);
      break;
    case 206:
      Metrics::Counter::increment(http_rsb.response_status_206_count);
      break;
    case 300:
      Metrics::Counter::increment(http_rsb.response_status_300_count);
      break;
    case 301:
      Metrics::Counter::increment(http_rsb.response_status_301_count);
      break;
    case 302:
      Metrics::Counter::increment(http_rsb.response_status_302_count);
      break;
    case 303:
      Metrics::Counter::increment(http_rsb.response_status_303_count);
      break;
    case 304:
      Metrics::Counter::increment(http_rsb.response_status_304_count);
      break;
    case 305:
      Metrics::Counter::increment(http_rsb.response_status_305_count);
      break;
    case 307:
      Metrics::Counter::increment(http_rsb.response_status_307_count);
      break;
    case 308:
      Metrics::Counter::increment(http_rsb.response_status_308_count);
      break;
    case 400:
      Metrics::Counter::increment(http_rsb.response_status_400_count);
      break;
    case 401:
      Metrics::Counter::increment(http_rsb.response_status_401_count);
      break;
    case 402:
      Metrics::Counter::increment(http_rsb.response_status_402_count);
      break;
    case 403:
      Metrics::Counter::increment(http_rsb.response_status_403_count);
      break;
    case 404:
      Metrics::Counter::increment(http_rsb.response_status_404_count);
      break;
    case 405:
      Metrics::Counter::increment(http_rsb.response_status_405_count);
      break;
    case 406:
      Metrics::Counter::increment(http_rsb.response_status_406_count);
      break;
    case 407:
      Metrics::Counter::increment(http_rsb.response_status_407_count);
      break;
    case 408:
      Metrics::Counter::increment(http_rsb.response_status_408_count);
      break;
    case 409:
      Metrics::Counter::increment(http_rsb.response_status_409_count);
      break;
    case 410:
      Metrics::Counter::increment(http_rsb.response_status_410_count);
      break;
    case 411:
      Metrics::Counter::increment(http_rsb.response_status_411_count);
      break;
    case 412:
      Metrics::Counter::increment(http_rsb.response_status_412_count);
      break;
    case 413:
      Metrics::Counter::increment(http_rsb.response_status_413_count);
      break;
    case 414:
      Metrics::Counter::increment(http_rsb.response_status_414_count);
      break;
    case 415:
      Metrics::Counter::increment(http_rsb.response_status_415_count);
      break;
    case 416:
      Metrics::Counter::increment(http_rsb.response_status_416_count);
      break;
    case 500:
      Metrics::Counter::increment(http_rsb.response_status_500_count);
      break;
    case 501:
      Metrics::Counter::increment(http_rsb.response_status_501_count);
      break;
    case 502:
      Metrics::Counter::increment(http_rsb.response_status_502_count);
      break;
    case 503:
      Metrics::Counter::increment(http_rsb.response_status_503_count);
      break;
    case 504:
      Metrics::Counter::increment(http_rsb.response_status_504_count);
      break;
    case 505:
      Metrics::Counter::increment(http_rsb.response_status_505_count);
      break;
    default:
      break;
    }
    switch (static_cast<int>(client_response_status) / 100) {
    case 1:
      Metrics::Counter::increment(http_rsb.response_status_1xx_count);
      break;
    case 2:
      Metrics::Counter::increment(http_rsb.response_status_2xx_count);
      break;
    case 3:
      Metrics::Counter::increment(http_rsb.response_status_3xx_count);
      break;
    case 4:
      Metrics::Counter::increment(http_rsb.response_status_4xx_count);
      break;
    case 5:
      Metrics::Counter::increment(http_rsb.response_status_5xx_count);
      break;
    default:
      break;
    }
  }

  // Increment the completed connection count
  Metrics::Counter::increment(http_rsb.completed_requests);

  // Set the stat now that we know what happend
  ink_hrtime total_msec   = ink_hrtime_to_msec(total_time);
  ink_hrtime process_msec = ink_hrtime_to_msec(request_process_time);
  switch (client_transaction_result) {
  case ClientTransactionResult_t::HIT_FRESH:
    Metrics::Counter::increment(http_rsb.ua_counts_hit_fresh);
    Metrics::Counter::increment(http_rsb.ua_msecs_hit_fresh, total_msec);
    Metrics::Counter::increment(http_rsb.ua_counts_hit_fresh_process);
    Metrics::Counter::increment(http_rsb.ua_msecs_hit_fresh_process, process_msec);
    break;
  case ClientTransactionResult_t::HIT_REVALIDATED:
    Metrics::Counter::increment(http_rsb.ua_counts_hit_reval);
    Metrics::Counter::increment(http_rsb.ua_msecs_hit_reval, total_msec);
    break;
  case ClientTransactionResult_t::MISS_COLD:
    Metrics::Counter::increment(http_rsb.ua_counts_miss_cold);
    Metrics::Counter::increment(http_rsb.ua_msecs_miss_cold, total_msec);
    break;
  case ClientTransactionResult_t::MISS_CHANGED:
    Metrics::Counter::increment(http_rsb.ua_counts_miss_changed);
    Metrics::Counter::increment(http_rsb.ua_msecs_miss_changed, total_msec);
    break;
  case ClientTransactionResult_t::MISS_CLIENT_NO_CACHE:
    Metrics::Counter::increment(http_rsb.ua_counts_miss_client_no_cache);
    Metrics::Counter::increment(http_rsb.ua_msecs_miss_client_no_cache, total_msec);
    break;
  case ClientTransactionResult_t::MISS_UNCACHABLE:
    Metrics::Counter::increment(http_rsb.ua_counts_miss_uncacheable);
    Metrics::Counter::increment(http_rsb.ua_msecs_miss_uncacheable, total_msec);
    break;
  case ClientTransactionResult_t::ERROR_ABORT:
    Metrics::Counter::increment(http_rsb.ua_counts_errors_aborts);
    Metrics::Counter::increment(http_rsb.ua_msecs_errors_aborts, total_msec);
    break;
  case ClientTransactionResult_t::ERROR_POSSIBLE_ABORT:
    Metrics::Counter::increment(http_rsb.ua_counts_errors_possible_aborts);
    Metrics::Counter::increment(http_rsb.ua_msecs_errors_possible_aborts, total_msec);
    break;
  case ClientTransactionResult_t::ERROR_CONNECT_FAIL:
    Metrics::Counter::increment(http_rsb.ua_counts_errors_connect_failed);
    Metrics::Counter::increment(http_rsb.ua_msecs_errors_connect_failed, total_msec);
    break;
  case ClientTransactionResult_t::ERROR_OTHER:
    Metrics::Counter::increment(http_rsb.ua_counts_errors_other);
    Metrics::Counter::increment(http_rsb.ua_msecs_errors_other, total_msec);
    break;
  default:
    Metrics::Counter::increment(http_rsb.ua_counts_other_unclassified);
    Metrics::Counter::increment(http_rsb.ua_msecs_other_unclassified, total_msec);
    // This can happen if a plugin manually sets the status code after an error.
    TxnDbg(dbg_ctl_http, "Unclassified statistic");
    break;
  }
}

void
HttpTransact::update_size_and_time_stats(State *s, ink_hrtime total_time, ink_hrtime user_agent_write_time,
                                         ink_hrtime origin_server_read_time, int user_agent_request_header_size,
                                         int64_t user_agent_request_body_size, int user_agent_response_header_size,
                                         int64_t user_agent_response_body_size, int origin_server_request_header_size,
                                         int64_t origin_server_request_body_size, int origin_server_response_header_size,
                                         int64_t origin_server_response_body_size, int pushed_response_header_size,
                                         int64_t pushed_response_body_size, const TransactionMilestones &milestones)
{
  int64_t user_agent_request_size  = user_agent_request_header_size + user_agent_request_body_size;
  int64_t user_agent_response_size = user_agent_response_header_size + user_agent_response_body_size;
  int64_t user_agent_bytes         = user_agent_request_size + user_agent_response_size;

  int64_t origin_server_request_size  = origin_server_request_header_size + origin_server_request_body_size;
  int64_t origin_server_response_size = origin_server_response_header_size + origin_server_response_body_size;
  int64_t origin_server_bytes         = origin_server_request_size + origin_server_response_size;

  // Background fill stats
  switch (s->state_machine->background_fill) {
  case BackgroundFill_t::COMPLETED: {
    int64_t bg_size = origin_server_response_body_size - user_agent_response_body_size;
    bg_size         = std::max(static_cast<int64_t>(0), bg_size);
    Metrics::Counter::increment(http_rsb.background_fill_bytes_completed, bg_size);
    break;
  }
  case BackgroundFill_t::ABORTED: {
    int64_t bg_size = origin_server_response_body_size - user_agent_response_body_size;

    if (bg_size < 0) {
      bg_size = 0;
    }
    Metrics::Counter::increment(http_rsb.background_fill_bytes_aborted, bg_size);
    break;
  }
  case BackgroundFill_t::NONE:
    break;
  case BackgroundFill_t::STARTED:
  default:
    ink_assert(0);
  }

  // Bandwidth Savings
  switch (s->squid_codes.log_code) {
  case SquidLogCode::TCP_HIT:
  case SquidLogCode::TCP_MEM_HIT:
  case SquidLogCode::TCP_CF_HIT:
    // It's possible to have two stat's instead of one, if needed.
    Metrics::Counter::increment(http_rsb.tcp_hit_count);
    Metrics::Counter::increment(http_rsb.tcp_hit_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_hit_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::TCP_MISS:
    Metrics::Counter::increment(http_rsb.tcp_miss_count);
    Metrics::Counter::increment(http_rsb.tcp_miss_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_miss_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::TCP_EXPIRED_MISS:
    Metrics::Counter::increment(http_rsb.tcp_expired_miss_count);
    Metrics::Counter::increment(http_rsb.tcp_expired_miss_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_expired_miss_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::TCP_REFRESH_HIT:
    Metrics::Counter::increment(http_rsb.tcp_refresh_hit_count);
    Metrics::Counter::increment(http_rsb.tcp_refresh_hit_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_refresh_hit_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::TCP_REFRESH_MISS:
    Metrics::Counter::increment(http_rsb.tcp_refresh_miss_count);
    Metrics::Counter::increment(http_rsb.tcp_refresh_miss_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_refresh_miss_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::TCP_CLIENT_REFRESH:
    Metrics::Counter::increment(http_rsb.tcp_client_refresh_count);
    Metrics::Counter::increment(http_rsb.tcp_client_refresh_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_client_refresh_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::TCP_IMS_HIT:
    Metrics::Counter::increment(http_rsb.tcp_ims_hit_count);
    Metrics::Counter::increment(http_rsb.tcp_ims_hit_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_ims_hit_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::TCP_IMS_MISS:
    Metrics::Counter::increment(http_rsb.tcp_ims_miss_count);
    Metrics::Counter::increment(http_rsb.tcp_ims_miss_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.tcp_ims_miss_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::ERR_CLIENT_ABORT:
    Metrics::Counter::increment(http_rsb.err_client_abort_count);
    Metrics::Counter::increment(http_rsb.err_client_abort_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.err_client_abort_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::ERR_CLIENT_READ_ERROR:
    Metrics::Counter::increment(http_rsb.err_client_read_error_count);
    Metrics::Counter::increment(http_rsb.err_client_read_error_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.err_client_read_error_origin_server_bytes, origin_server_bytes);
    break;
  case SquidLogCode::ERR_CONNECT_FAIL:
    Metrics::Counter::increment(http_rsb.err_connect_fail_count);
    Metrics::Counter::increment(http_rsb.err_connect_fail_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.err_connect_fail_origin_server_bytes, origin_server_bytes);
    break;
  default:
    Metrics::Counter::increment(http_rsb.misc_count);
    Metrics::Counter::increment(http_rsb.misc_user_agent_bytes, user_agent_bytes);
    Metrics::Counter::increment(http_rsb.misc_origin_server_bytes, origin_server_bytes);
    break;
  }

  // times
  Metrics::Counter::increment(http_rsb.total_transactions_time, total_time);

  // sizes
  Metrics::Counter::increment(http_rsb.user_agent_request_header_total_size, user_agent_request_header_size);
  Metrics::Counter::increment(http_rsb.user_agent_response_header_total_size, user_agent_response_header_size);
  Metrics::Counter::increment(http_rsb.user_agent_request_document_total_size, user_agent_request_body_size);
  Metrics::Counter::increment(http_rsb.user_agent_response_document_total_size, user_agent_response_body_size);

  // proxy stats
  if (s->current.request_to == ResolveInfo::PARENT_PROXY) {
    Metrics::Counter::increment(http_rsb.parent_proxy_request_total_bytes,
                                origin_server_request_header_size + origin_server_request_body_size);
    Metrics::Counter::increment(http_rsb.parent_proxy_response_total_bytes,
                                origin_server_response_header_size + origin_server_response_body_size);
    Metrics::Counter::increment(http_rsb.parent_proxy_transaction_time, total_time);
  }
  // request header zero means the document was cached.
  // do not add to stats.
  if (origin_server_request_header_size > 0) {
    Metrics::Counter::increment(http_rsb.origin_server_request_header_total_size, origin_server_request_header_size);
    Metrics::Counter::increment(http_rsb.origin_server_response_header_total_size, origin_server_response_header_size);
    Metrics::Counter::increment(http_rsb.origin_server_request_document_total_size, origin_server_request_body_size);
    Metrics::Counter::increment(http_rsb.origin_server_response_document_total_size, origin_server_response_body_size);
  }

  if (user_agent_write_time >= 0) {
    user_agent_connection_speed(user_agent_write_time, user_agent_response_size);
  }

  if (origin_server_request_header_size > 0 && origin_server_read_time > 0) {
    origin_server_connection_speed(origin_server_read_time, origin_server_response_size);
  }

  if (s->method == HTTP_WKSIDX_PUSH) {
    Metrics::Counter::increment(http_rsb.pushed_response_header_total_size, pushed_response_header_size);
    Metrics::Counter::increment(http_rsb.pushed_document_total_size, pushed_response_body_size);
  }

  // update milestones stats
  Metrics::Counter::increment(http_rsb.ua_begin_time, milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_UA_BEGIN, 0));
  Metrics::Counter::increment(http_rsb.ua_first_read_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_UA_FIRST_READ, 0));
  Metrics::Counter::increment(http_rsb.ua_read_header_done_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_UA_READ_HEADER_DONE, 0));
  Metrics::Counter::increment(http_rsb.ua_begin_write_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_UA_BEGIN_WRITE, 0));
  Metrics::Counter::increment(http_rsb.ua_close_time, milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_UA_CLOSE, 0));
  Metrics::Counter::increment(http_rsb.server_first_connect_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SERVER_FIRST_CONNECT, 0));
  Metrics::Counter::increment(http_rsb.server_connect_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SERVER_CONNECT, 0));
  Metrics::Counter::increment(http_rsb.server_connect_end_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SERVER_CONNECT_END, 0));
  Metrics::Counter::increment(http_rsb.server_begin_write_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SERVER_BEGIN_WRITE, 0));
  Metrics::Counter::increment(http_rsb.server_first_read_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SERVER_FIRST_READ, 0));
  Metrics::Counter::increment(http_rsb.server_read_header_done_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SERVER_READ_HEADER_DONE, 0));
  Metrics::Counter::increment(http_rsb.server_close_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SERVER_CLOSE, 0));
  Metrics::Counter::increment(http_rsb.cache_open_read_begin_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_CACHE_OPEN_READ_BEGIN, 0));
  Metrics::Counter::increment(http_rsb.cache_open_read_end_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_CACHE_OPEN_READ_END, 0));
  Metrics::Counter::increment(http_rsb.cache_open_write_begin_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_CACHE_OPEN_WRITE_BEGIN, 0));
  Metrics::Counter::increment(http_rsb.cache_open_write_end_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_CACHE_OPEN_WRITE_END, 0));
  Metrics::Counter::increment(http_rsb.dns_lookup_begin_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_DNS_LOOKUP_BEGIN, 0));
  Metrics::Counter::increment(http_rsb.dns_lookup_end_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_DNS_LOOKUP_END, 0));
  Metrics::Counter::increment(http_rsb.sm_start_time, milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SM_START, 0));
  Metrics::Counter::increment(http_rsb.sm_finish_time,
                              milestones.difference_msec(TS_MILESTONE_SM_START, TS_MILESTONE_SM_FINISH, 0));
}

void
HttpTransact::delete_warning_value(HTTPHdr *to_warn, HTTPWarningCode warning_code)
{
  int        w_code = static_cast<int>(warning_code);
  MIMEField *field  = to_warn->field_find(static_cast<std::string_view>(MIME_FIELD_WARNING));

  // Loop over the values to see if we need to do anything
  if (field) {
    HdrCsvIter iter;
    int        val_code;
    MIMEField *new_field = nullptr;

    bool valid_p = iter.get_first_int(field, val_code);

    while (valid_p) {
      if (val_code == w_code) {
        // Ok, found the value we're look to delete Look over and create a new field appending all
        // elements that are not this value
        valid_p = iter.get_first_int(field, val_code);

        while (valid_p) {
          if (val_code != static_cast<int>(warning_code)) {
            auto value = iter.get_current();
            if (new_field) {
              new_field->value_append(to_warn->m_heap, to_warn->m_mime, value.data(), value.size(), true);
            } else {
              new_field = to_warn->field_create();
              to_warn->field_value_set(new_field, value);
            }
          }
          valid_p = iter.get_next_int(val_code);
        }

        to_warn->field_delete(static_cast<std::string_view>(MIME_FIELD_WARNING));
        if (new_field) {
          new_field->name_set(to_warn->m_heap, to_warn->m_mime, static_cast<std::string_view>(MIME_FIELD_WARNING));
          to_warn->field_attach(new_field);
        }

        return;
      }
      valid_p = iter.get_next_int(val_code);
    }
  }
}

void
HttpTransact::change_response_header_because_of_range_request(State *s, HTTPHdr *header)
{
  MIMEField *field;
  char      *reason_phrase;

  TxnDbg(dbg_ctl_http_trans, "Partial content requested, re-calculating content-length");

  header->status_set(HTTPStatus::PARTIAL_CONTENT);
  reason_phrase = const_cast<char *>(http_hdr_reason_lookup(HTTPStatus::PARTIAL_CONTENT));
  header->reason_set(std::string_view{reason_phrase});

  // set the right Content-Type for multiple entry Range
  if (s->num_range_fields > 1) {
    field = header->field_find(static_cast<std::string_view>(MIME_FIELD_CONTENT_TYPE));

    if (field != nullptr) {
      header->field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_TYPE));
    }

    field = header->field_create(static_cast<std::string_view>(MIME_FIELD_CONTENT_TYPE));
    field->value_append(header->m_heap, header->m_mime, range_type, sizeof(range_type) - 1);

    header->field_attach(field);
    // TODO: There's a known bug here where the Content-Length is not correct for multi-part
    // Range: requests.
    header->set_content_length(s->range_output_cl);
  } else {
    if (s->cache_info.object_read && s->cache_info.object_read->valid()) {
      // TODO: It's unclear under which conditions we need to update the Content-Range: header,
      // many times it's already set correctly before calling this. For now, always try do it
      // when we have the information for it available.
      // TODO: Also, it's unclear as to why object_read->valid() is not always true here.
      char numbers[RANGE_NUMBERS_LENGTH];
      header->field_delete(static_cast<std::string_view>(MIME_FIELD_CONTENT_RANGE));
      field = header->field_create(static_cast<std::string_view>(MIME_FIELD_CONTENT_RANGE));
      snprintf(numbers, sizeof(numbers), "bytes %" PRId64 "-%" PRId64 "/%" PRId64, s->ranges[0]._start, s->ranges[0]._end,
               s->cache_info.object_read->object_size_get());
      field->value_set(header->m_heap, header->m_mime, std::string_view{numbers});
      header->field_attach(field);
    }
    // Always update the Content-Length: header.
    header->set_content_length(s->range_output_cl);
  }
}

#if TS_HAS_TESTS
void forceLinkRegressionHttpTransact();
void
forceLinkRegressionHttpTransactCaller()
{
  forceLinkRegressionHttpTransact();
}
#endif
