/** @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());

    ///////////////////////////////////////////////
    // 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;
    }
  }

  // If we're serving stale due to write lock failure, override cache_lookup_result to HIT_STALE
  // so plugins see the accurate status. what_is_document_freshness returns FRESH to bypass
  // revalidation, but the content is actually stale.
  if (s->serving_stale_due_to_write_lock) {
    s->cache_lookup_result = HttpTransact::CacheLookupResult_t::HIT_STALE;
  }

  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);
  }

  // Clear the deferred flag if set (for READ_RETRY cases that found stale content)
  s->cache_lookup_complete_deferred = false;

  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)
  // Also skip revalidation if we're serving stale due to write lock failure - we've already decided
  // to serve the stale content to avoid contention, so don't try to revalidate.
  if ((((s->cache_lookup_result == CacheLookupResult_t::HIT_STALE && !s->serving_stale_due_to_write_lock) ||
        ((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 serving stale due to write lock failure (actions 2, 3, or 6), adjust VIA to reflect stale serving.
  // This ensures correct statistics attribution (cache_hit_stale_served instead of cache_hit_fresh).
  // Note: VIA_SERVER_RESULT is left as default (space) since the origin server was never contacted.
  if (s->serving_stale_due_to_write_lock) {
    TxnDbg(dbg_ctl_http_trans, "Serving stale due to write lock failure, adjusting VIA for statistics");
    SET_VIA_STRING(VIA_DETAIL_CACHE_LOOKUP, VIA_DETAIL_MISS_EXPIRED);
    SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_STALE);
  }

  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 && !s->serving_stale_due_to_write_lock) {
    ink_assert(server_up == false);
    build_response_from_cache(s, HTTPWarningCode::REVALIDATION_FAILED);
  } else if (s->serving_stale_due_to_write_lock) {
    // Serving stale due to write lock failure - no Warning header (deprecated per RFC 9111)
    build_response_from_cache(s, HTTPWarningCode::NONE);
  } 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_open_write_fail_action ==
                   static_cast<MgmtByte>(CacheOpenWriteFailAction_t::READ_RETRY_STALE_ON_REVALIDATE));
      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) {
    // For READ_RETRY with cached object, evaluate actual freshness to decide the path.
    // If the initial lookup was a MISS, cache_lookup_complete_deferred is true and we
    // need to fire the hook here with the final result. If the initial lookup was a
    // HIT_STALE (revalidation case), the hook already fired and deferred is false.
    CacheHTTPInfo *obj = s->cache_info.object_read;
    if (obj != nullptr) {
      // Restore request/response times from cached object for freshness calculations and Age header.
      // Similar to HandleCacheOpenReadHitFreshness, handle clock skew by capping times.
      s->request_sent_time      = obj->request_sent_time_get();
      s->response_received_time = obj->response_received_time_get();
      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);

      // Evaluate actual document freshness. Pass true to skip the STALE_ON_REVALIDATE
      // short-circuit so we get the real freshness, not the "return FRESH to bypass revalidation" result.
      Freshness_t freshness = what_is_document_freshness(s, &s->hdr_info.client_request, obj->response_get(), true);

      if (freshness == Freshness_t::FRESH || freshness == Freshness_t::WARNING) {
        // Object is fresh - serve it from cache for both action 5 and 6.
        // This is the main benefit of request collapsing: we found a valid cached object.
        // Clear stale-related state in case it was set during initial stale short-circuit.
        s->serving_stale_due_to_write_lock = false;
        s->cache_info.stale_fallback       = nullptr;

        // Destroy server_request since we're serving from cache.
        TxnDbg(dbg_ctl_http_trans, "READ_RETRY: found fresh object, serving from cache");
        s->hdr_info.server_request.destroy();
        s->cache_lookup_result =
          (freshness == Freshness_t::FRESH) ? CacheLookupResult_t::HIT_FRESH : CacheLookupResult_t::HIT_WARNING;

        if (s->cache_lookup_complete_deferred) {
          s->cache_lookup_complete_deferred = false;
          TRANSACT_RETURN(StateMachineAction_t::API_CACHE_LOOKUP_COMPLETE, HandleCacheOpenReadHit);
        }
        HandleCacheOpenReadHit(s);
      } else {
        // Object is stale. Save it as potential fallback, then trigger actual cache retry.
        // HandleCacheOpenReadMiss will serve stale fallback (action 6) or go to origin (action 5).
        if (is_stale_cache_response_returnable(s)) {
          s->cache_info.stale_fallback = s->cache_info.object_read;
        }
        TxnDbg(dbg_ctl_http_trans, "READ_RETRY: object stale, triggering actual cache retry");
        s->cache_info.object_read  = nullptr;
        s->cache_info.write_status = CacheWriteStatus_t::LOCK_MISS;
        s->hdr_info.server_request.destroy();
        TRANSACT_RETURN(StateMachineAction_t::CACHE_LOOKUP, nullptr);
      }
    } else {
      HandleCacheOpenReadMiss(s);
    }
  } else {
    handle_cache_write_lock_go_to_origin(s);
  }
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_cache_write_lock_go_to_origin
// Description: Helper to proceed to origin server from handle_cache_write_lock.
//              Called when write lock succeeded or failed without READ_RETRY.
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_cache_write_lock_go_to_origin(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "handle_cache_write_lock_go_to_origin - proceeding to origin");

  // If the CACHE_LOOKUP_COMPLETE hook was deferred (for action 5/6), fire it now.
  // We're going to origin without READ_RETRY, so MISS is the final result.
  if (s->cache_lookup_complete_deferred) {
    TxnDbg(dbg_ctl_http_trans, "Firing deferred CACHE_LOOKUP_COMPLETE with MISS before origin");
    s->cache_lookup_complete_deferred = false;
    s->cache_lookup_result            = CacheLookupResult_t::MISS;
    TRANSACT_RETURN(StateMachineAction_t::API_CACHE_LOOKUP_COMPLETE, handle_cache_write_lock_go_to_origin_continue);
  }

  handle_cache_write_lock_go_to_origin_continue(s);
}

///////////////////////////////////////////////////////////////////////////////
// Name       : handle_cache_write_lock_go_to_origin_continue
// Description: Continuation of handle_cache_write_lock_go_to_origin after
//              the deferred CACHE_LOOKUP_COMPLETE hook fires.
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::handle_cache_write_lock_go_to_origin_continue(State *s)
{
  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 {
    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 if (s->cache_info.write_lock_state == CacheWriteLock_t::READ_RETRY) {
    // READ_RETRY cache read failed (no fresh object found).
    // Check if we have a stale fallback (saved from action 6 revalidation case).
    bool is_action_6 =
      (s->cache_open_write_fail_action & static_cast<MgmtByte>(CacheOpenWriteFailAction_t::STALE_ON_REVALIDATE)) != 0;

    if (is_action_6 && s->cache_info.stale_fallback != nullptr) {
      // Action 6: Serve stale fallback after retries exhausted.
      TxnDbg(dbg_ctl_http_trans, "READ_RETRY: retries exhausted, serving stale (action 6)");
      s->cache_info.object_read          = s->cache_info.stale_fallback;
      s->cache_info.stale_fallback       = nullptr;
      s->serving_stale_due_to_write_lock = true;
      s->cache_lookup_result             = CacheLookupResult_t::HIT_STALE;

      if (s->cache_lookup_complete_deferred) {
        s->cache_lookup_complete_deferred = false;
        TRANSACT_RETURN(StateMachineAction_t::API_CACHE_LOOKUP_COMPLETE, HandleCacheOpenReadHit);
      }
      HandleCacheOpenReadHit(s);
      return;
    }
    // Action 5 or no stale fallback: proceed to origin without caching.
    TxnDbg(dbg_ctl_http_trans, "READ_RETRY cache read failed, bypassing cache");
    s->cache_info.stale_fallback = nullptr; // Clear unused fallback
    s->cache_info.action         = CacheAction_t::NO_ACTION;
  } else if (s->cache_info.write_lock_state == CacheWriteLock_t::SUCCESS && s->cache_info.action == CacheAction_t::WRITE) {
    // Origin retry paths such as TSHttpTxnServerAddrSet() can loop back through
    // HandleCacheOpenReadMiss after we already own the cache write lock. This
    // is still the same request, so keep the existing write lock instead of
    // re-preparing a write as if this were a redirect or a new cache miss.
    TxnDbg(dbg_ctl_http_trans, "Reusing existing cache write lock while retrying origin selection");
  } else {
    HttpTransact::set_cache_prepare_write_action_for_new_request(s);
  }

  // If the CACHE_LOOKUP_COMPLETE hook was deferred, decide whether to fire it now.
  // Only fire when we're at a terminal state for cache lookup:
  // - NO_ACTION: Not attempting write lock, MISS is the final result
  // - READ_RETRY: Already retried and still missed, MISS is the final result
  //
  // Don't fire yet if action == PREPARE_TO_WRITE and write_lock_state != READ_RETRY,
  // because we're about to attempt the write lock and may find content on retry.
  // In that case, the hook will fire later:
  // - If READ_RETRY finds HIT: handle_cache_write_lock fires CACHE_LOOKUP_COMPLETE with HIT
  // - If READ_RETRY finds MISS: We come back here with write_lock_state == READ_RETRY
  if (s->cache_lookup_complete_deferred) {
    if (s->cache_info.action == CacheAction_t::NO_ACTION || s->cache_info.write_lock_state == CacheWriteLock_t::READ_RETRY) {
      TxnDbg(dbg_ctl_http_trans, "Firing deferred CACHE_LOOKUP_COMPLETE with MISS (action=%d, write_lock_state=%d)",
             static_cast<int>(s->cache_info.action), static_cast<int>(s->cache_info.write_lock_state));
      s->cache_lookup_complete_deferred = false;
      s->cache_lookup_result            = CacheLookupResult_t::MISS;
      TRANSACT_RETURN(StateMachineAction_t::API_CACHE_LOOKUP_COMPLETE, HandleCacheOpenReadMissGoToOrigin);
    }
    TxnDbg(dbg_ctl_http_trans, "Deferring CACHE_LOOKUP_COMPLETE hook - waiting for write lock attempt");
  }

  // Proceed to origin server (handles DNS lookup, parent proxy, etc.)
  HandleCacheOpenReadMissGoToOrigin(s);
}

///////////////////////////////////////////////////////////////////////////////
// Name       : HandleCacheOpenReadMissGoToOrigin
// Description: Contains the "go to origin" logic for cache miss cases.
//              Handles DNS lookup, parent proxy selection, and request building.
//
///////////////////////////////////////////////////////////////////////////////
void
HttpTransact::HandleCacheOpenReadMissGoToOrigin(State *s)
{
  TxnDbg(dbg_ctl_http_trans, "HandleCacheOpenReadMissGoToOrigin - proceeding to origin");

  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;
  }
}

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 if (s->cache_info.write_lock_state == CacheWriteLock_t::READ_RETRY &&
             (!s->redirect_info.redirect_in_process || s->txn_conf->redirect_use_orig_cache_key)) {
    // Defensive: Should not reach here if HandleCacheOpenReadMiss check is working.
    // If we somehow get here in READ_RETRY state, bypass cache unless we're in a redirect
    // that uses a different cache key (redirect_use_orig_cache_key == 0).
    // When redirect_use_orig_cache_key is enabled, the redirect uses the same cache key
    // as the original request, so we'd hit the same write lock contention.
    Error("set_cache_prepare_write_action_for_new_request called with READ_RETRY state");
    s->cache_info.action = CacheAction_t::NO_ACTION;
  } 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='{}' sm_id={} "
                  "connection_result={::s} error={::s} retry_attempts={} url='{}'",
                  HttpDebugNames::get_server_state_name(conn_state), s->current.server->dst_addr, host_name, s->state_machine_id(),
                  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);
        SET_VIA_STRING(VIA_CACHE_RESULT, VIA_IN_CACHE_STALE);
        // change VIA_SERVER_RESULT to ERROR because this status hit the negative_revalidating_list
        SET_VIA_STRING(VIA_SERVER_RESULT, VIA_SERVER_ERROR);
        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                    = vc->get_proxy_protocol_info();
  }
  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 evaluate_actual_freshness)
{
  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;

  // This check works for STALE_ON_REVALIDATE(0x2), ERROR_ON_MISS_STALE_ON_REVALIDATE(0x3), and
  // READ_RETRY_STALE_ON_REVALIDATE(0x6).
  // We return FRESH (not STALE) intentionally to bypass the revalidation code path in
  // HandleCacheOpenReadHit. Returning STALE would trigger origin server contact for revalidation,
  // but for write lock failure scenarios we want to serve the stale content directly without
  // revalidation. The serving_stale_due_to_write_lock flag tracks that we're actually serving
  // stale content, so VIA strings and statistics can be correctly attributed.
  // When evaluate_actual_freshness is true, skip this short-circuit to get the real freshness.
  if (!evaluate_actual_freshness &&
      (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 to bypass revalidation");
      s->serving_stale_due_to_write_lock = true;
      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)
{
  ///////////////////////////////////////////////////////////////////////////////
  // Per RFC 7234 section 3.2, if a client request has the Authorization      //
  // header set, we can't serve a cached response unless the response has one //
  // of: must-revalidate, proxy-revalidate, public, or s-maxage directives.   //
  ///////////////////////////////////////////////////////////////////////////////

  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->is_cache_control_set(HTTP_VALUE_S_MAXAGE.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())) {
      // Preemptively clean up the response in case a prior 1xx informational
      // response was forwarded to the client. Otherwise, copy_header_fields
      // will fail an assertion that the new header is not yet valid.
      if (outgoing_response->valid()) {
        outgoing_response->destroy();
      }
      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 000 responses separately since they include aborts (the main source of 000).
  if (static_cast<int>(client_response_status) == 0) {
    Metrics::Counter::increment(http_rsb.response_status_000_count);
  }
  // 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 429:
      Metrics::Counter::increment(http_rsb.response_status_429_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
