/** @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 <algorithm>
#include <cmath>
#include <string>
#include <array>

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

std::string_view
get_at_header_source_name(HttpTransact::AtHeaderSource source)
{
  using AtHeaderSource = HttpTransact::AtHeaderSource;

  switch (source) {
  case AtHeaderSource::CLIENT_REQUEST:
    return "client request";
  case AtHeaderSource::ORIGIN_RESPONSE:
    return "origin response";
  }

  return "unknown source";
}

Metrics::Counter::AtomicType *
get_at_header_source_metric(HttpTransact::AtHeaderSource source)
{
  using AtHeaderSource = HttpTransact::AtHeaderSource;

  switch (source) {
  case AtHeaderSource::CLIENT_REQUEST:
    return http_rsb.client_request_at_headers_stripped;
  case AtHeaderSource::ORIGIN_RESPONSE:
    return http_rsb.origin_response_at_headers_stripped;
  }

  return nullptr;
}
} // namespace

/**
 * Remove internal @ headers from a parsed header before plugin hooks run.
 *
 * @param[in,out] header The header to sanitize in place.
 * @param[in] source The source of the header being sanitized.
 * @param[in] sm_id The state machine identifier for diagnostic logging.
 */
void
HttpTransact::strip_at_headers(HTTPHdr &header, AtHeaderSource source, std::int64_t sm_id)
{
  auto const metric      = get_at_header_source_metric(source);
  auto const source_name = get_at_header_source_name(source);

  for (auto field = header.begin(); field != header.end();) {
    auto current = field++;
    auto name    = current->name_get();

    if (!name.empty() && name[0] == '@') {
      Metrics::Counter::increment(metric);
      Error("[%" PRId64 "] stripped internal @ header from %.*s: %.*s", sm_id, static_cast<int>(source_name.size()),
            source_name.data(), static_cast<int>(name.size()), name.data());
      header.field_delete(&*current, false);
    }
  }
}

//////////////////////////////////////////////////////////////////////////
// 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 ? 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
host_override(HttpTransact::State *s)
{
  if (s->response_action.handled) { // should be handled by the plugin
    return false;
  } else if (nullptr != s->next_hop_strategy) {
    // remap strategies do not support the TSHttpTxnParentProxySet API.
    return s->next_hop_strategy->host_override;
  } else if (nullptr != s->parent_params) {
    return s->parent_result.host_override();
  }
  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_some(HttpTransact::State *s)
{
  if (s->response_action.handled) {
    return true;
  } else if (nullptr != s->next_hop_strategy) {
    // remap strategies do not support the TSHttpTxnParentProxySet API.
    return s->parent_result.result == ParentResultType::SPECIFIED;
  } else if (nullptr != s->parent_params) {
    return s->parent_result.is_some();
  }
  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 res = false;
  if (nullptr != s->next_hop_strategy) {
    // remap strategies do not support the TSHttpTxnParentProxySet API.
    res = false;
  } else if (nullptr != s->parent_params) {
    res = s->parent_result.is_api_result();
  }
  return res;
}

// 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)
{
  TxnDbg(dbg_ctl_http_trans, "findParent");

  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_http_trans, "nextParent");

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

/**
  ATS has two configuration options controlling how many times it retries a connection attempt against origin servers.

  - proxy.config.http.connect_attempts_max_retries
  - proxy.config.http.connect_attempts_max_retries_suspect_server

  The choice is based on the state of the active HostDBInfo.

  - HostDBInfo::State::UP: use proxy.config.http.connect_attempts_max_retries
  - HostDBInfo::State::DOWN: no retry
  - HostDBInfo::State::SUSPECT: use proxy.config.http.connect_attempts_max_retries_suspect_server

*/
uint8_t
HttpTransact::origin_server_connect_attempts_max_retries(State *s)
{
  HostDBInfo *active = s->dns_info.active;
  if (active == nullptr) {
    return 0;
  }

  switch (active->state(ts_clock::now(), s->txn_conf->down_server_timeout)) {
  case HostDBInfo::State::UP:
    return s->txn_conf->connect_attempts_max_retries;
  case HostDBInfo::State::DOWN:
    return 0;
  case HostDBInfo::State::SUSPECT:
    return s->txn_conf->connect_attempts_max_retries_suspect_server;
  default:
    break;
  }

  return 0;
}

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 (!is_some(s) || 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 (!is_some(s) || 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: {
    char const *const hostname = s->parent_result.hostname;

    if (nullptr != hostname) {
      s->parent_info.name = s->arena.str_store(hostname, strlen(hostname));

      // if host header override option enabled
      if (host_override(s)) {
        TxnDbg(dbg_ctl_http_trans, "overriding host header with parent %s", hostname);
        if (!s->hdr_info.server_request.valid()) {
          s->hdr_info.client_request.value_set(static_cast<std::string_view>(MIME_FIELD_HOST), hostname);
          s->hdr_info.client_request.mark_target_dirty();
        } else {
          s->hdr_info.server_request.value_set(static_cast<std::string_view>(MIME_FIELD_HOST), hostname);
          s->hdr_info.server_request.mark_target_dirty();
        }
      }
    }

    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";
    break;
  case HTTPStatus::BAD_GATEWAY:
    status                = s->http_return_code;
    reason                = "Bad Gateway";
    body_factory_template = "default";
    break;
  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::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 the effective URL before remap, regardless of the 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());
  s->hdr_info.client_request.set_url_target_from_host_field(&s->unmapped_url);

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

  strip_at_headers(request, AtHeaderSource::CLIENT_REQUEST, s->state_machine_id());

  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.get());
  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 {
        // HostDB has the record but every address is DOWN within `down_server.cache_time`. This is a refusal-to-attempt
        // rather than a true DNS failure; track it under down_server_no_requests.
        Metrics::Counter::increment(http_rsb.down_server_no_requests);
        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(ts_clock::now(), s->txn_conf->down_server_timeout)) {
      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) {
        if (auto host_field = incoming_request->field_find(static_cast<std::string_view>(MIME_FIELD_HOST)); host_field != nullptr) {
          std::string_view host;
          int              port     = 0;
          bool             has_port = false;

          if (http_parse_host_header(host_field->value_get(), host, port, has_port)) {
            s->cache_info.lookup_url->host_set(host);
            s->cache_info.lookup_url->port_set(has_port ? port : 0);
          }
        }
      }
      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;
  }

  // An object found under the 9.2 key cannot take a 304: the write that would
  // apply it is a create on the current key, not an update of the legacy
  // vector, and the cache aborts a header-only create. Ask for the full
  // response instead, without our validators or the client's, so the 200
  // replaces it under the current key and the legacy copy ages out. The
  // client's conditionals are still matched against that 200. HEAD and Range
  // requests are left alone: neither response is stored, and an unconditional
  // range request would draw a 206 that deletes the object rather than
  // migrating it. The next full GET migrates it instead.
  if (s->cache_info.action == CacheAction_t::PREPARE_TO_UPDATE && s->method == HTTP_WKSIDX_GET &&
      !s->hdr_info.client_request.presence(MIME_PRESENCE_RANGE) && s->state_machine != nullptr &&
      CompatCacheKey::is_legacy(s->state_machine->compatibility_cache_lookup)) {
    TxnDbg(dbg_ctl_http_trans, "object under the compatibility key, revalidating unconditionally");
    HttpTransactHeaders::remove_conditional_headers(&s->hdr_info.server_request);
    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) {
    // Guard against unbounded recursion when the host is DOWN, the cache has
    // a HIT, and a Range request cannot be satisfied from cache. Without this
    // flag, CallOSDNSLookup -> handle_server_connection_not_open ->
    // build_response_from_cache (Range branch) -> CallOSDNSLookup recurses on
    // the stack until overflow.
    if (s->host_down_cache_fallback_attempted) {
      TxnDbg(dbg_ctl_http, "host down cache fallback already attempted; returning 502");
      build_error_response(s, HTTPStatus::BAD_GATEWAY, "Next Hop Connection Failed", "connect#failed_connect");
      s->next_action = StateMachineAction_t::SEND_ERROR_CACHE_NOOP;
      return;
    }
    s->host_down_cache_fallback_attempted = true;
    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;
    }
    error_log_connection_failure(s, s->current.state);
    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);

    // For origin servers (ResolveInfo::ORIGIN_SERVER): OSDNSLookup handles serving stale when all origin servers are down.
    // For parent proxies: 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->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) {
      if (!is_read_retry_write_fail_action(s->cache_open_write_fail_action)) {
        // Fail actions 2 and 3 do not retry the cache read: they serve the
        // object this transaction already looked up. Deciding otherwise here
        // would issue a second cache lookup while the transaction still holds
        // the cache read connection from the first one, and the read that
        // completes on that second lookup replaces the connection out from
        // under it.
        TxnDbg(dbg_ctl_http_trans, "write lock lost with a cached object and no read retry configured");
        s->hdr_info.server_request.destroy();
        HandleCacheOpenReadHitFreshness(s);
        return;
      }

      // 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 and can re-use
    // it. Otherwise, we risk storing the response under the wrong cache key.
    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);

  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 {
      if (is_request_retryable(s)) {
        markParentDown(s);
      } else {
        TxnDbg(dbg_ctl_http_trans, "skipping parent markdown for unavailable_server retry because request is not retryable");
      }
      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;
    error_log_connection_failure(s, s->current.state);
    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);

  // 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
    error_log_connection_failure(s, s->current.state);
    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);
      }
    }

    unsigned 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());

    // Bail out if the request is not retryable, the global retry cap is reached, or we already have a usable response.
    if (!is_request_retryable(s) || s->current.retry_attempts.get() >= max_connect_retries ||
        HttpTransact::is_response_valid(s, &s->hdr_info.server_response)) {
      TxnDbg(dbg_ctl_http_trans, "Error. No more retries. %d/%d", s->current.retry_attempts.get(), max_connect_retries);
      SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
      error_log_connection_failure(s, s->current.state);
      s->state_machine->do_hostdb_update_if_necessary();
      handle_server_connection_not_open(s);
      break;
    }

    // Attempt was based on a client-supplied address. Re-resolve via HostDB.
    if (ResolveInfo::OS_Addr::TRY_CLIENT == s->dns_info.os_addr_style) {
      // 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);
    }

    // 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.
    if (ResolveInfo::OS_Addr::USE_API == s->dns_info.os_addr_style && !s->api_server_addr_set_retried) {
      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);
    }

    // Record the failure on the current active target.
    error_log_connection_failure(s, s->current.state);
    s->state_machine->do_hostdb_update_if_necessary();

    // Decide between switching to the next round-robin member or staying on the same target.
    if ((s->txn_conf->connect_attempts_rr_retries > 0) &&
        ((s->current.retry_attempts.get() + 1) % s->txn_conf->connect_attempts_rr_retries == 0)) {
      if (s->dns_info.select_next_rr(ts_clock::now(), s->txn_conf->down_server_timeout)) {
        // select_next_rr() only updates dns_info.active; change the dst_addr too.
        s->dns_info.addr.assign(s->dns_info.active->data.ip);
        s->server_info.dst_addr.assign(s->dns_info.active->data.ip, s->server_info.dst_addr.network_order_port());
        if (dbg_ctl_http_trans.on()) {
          ip_port_text_buffer addrbuf;
          TxnDbg(dbg_ctl_http_trans, "switched to next round-robin upstream addr=%s",
                 ats_ip_nptop(&s->server_info.dst_addr.sa, addrbuf, sizeof(addrbuf)));
        }
      } else {
        TxnDbg(dbg_ctl_http_trans, "No round-robin targets available, retrying current upstream if possible");
      }
    }

    // The active target (HostDB) may be SUSPECT state, so re-evaluate the retry limit.
    // Skip when there is no HostDBInfo (e.g. USE_CLIENT / USE_API) and keep the configured baseline.
    if (s->dns_info.active != nullptr) {
      max_connect_retries = origin_server_connect_attempts_max_retries(s);
    }
    if (max_connect_retries <= s->current.retry_attempts.get()) {
      TxnDbg(dbg_ctl_http_trans, "Per-host retries exhausted. Giving up. %d/%d", s->current.retry_attempts.get(),
             max_connect_retries);
      SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
      handle_server_connection_not_open(s);
      break;
    }

    TxnDbg(dbg_ctl_http_trans, "Error. Retrying...");
    retry_server_connection_not_open(s, max_connect_retries);
    s->next_action = how_to_open_connection(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);
    s->state_machine->do_hostdb_update_if_necessary();
    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)
{
  // No origin server was selected (e.g. a host marked DOWN whose Range request
  // falls back to a cache hit), so there is no connection to log. Bail out
  // before dereferencing a null current.server.
  if (s->current.server == nullptr) {
    TxnDbg(dbg_ctl_http_trans, "no current server; skipping connection failure log");
    return;
  }

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

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

  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 stolen 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.
  //
  // Only delete a caching header that the server response does NOT carry.
  // If the response carries it, the merge below overwrites the cached field
  // in place; deleting it first would strand a dead MIMEField slot on every
  // revalidation (see merge_response_header_with_cached_header).
  HTTPHdr *server_response = &s->hdr_info.server_response;
  if (!server_response->presence(MIME_PRESENCE_AGE)) {
    cached_hdr->field_delete(static_cast<std::string_view>(MIME_FIELD_AGE));
  }
  if (!server_response->presence(MIME_PRESENCE_ETAG)) {
    cached_hdr->field_delete(static_cast<std::string_view>(MIME_FIELD_ETAG));
  }
  if (!server_response->presence(MIME_PRESENCE_EXPIRES)) {
    cached_hdr->field_delete(static_cast<std::string_view>(MIME_FIELD_EXPIRES));
  }

  merge_response_header_with_cached_header(cached_hdr, 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)
{
  // Connection tokens are hop-by-hop header names to strip.  Real-world Connection headers
  // rarely contain more than a few tokens; use a fixed-capacity buffer to avoid allocation.
  // If a pathological response exceeds the buffer, fall back to scanning the Connection field
  // directly to ensure no token is silently skipped.
  static constexpr size_t                     MAX_CONN_TOKENS = 16;
  std::array<swoc::TextView, MAX_CONN_TOKENS> conn_tokens;
  size_t                                      conn_token_count = 0;
  bool                                        conn_overflow    = false;

  MIMEField *conn_field = response_header->field_find(static_cast<std::string_view>(MIME_FIELD_CONNECTION));
  if (conn_field != nullptr) {
    HdrCsvIter csv;

    for (auto token = csv.get_first(conn_field, true); token; token = csv.get_next()) {
      if (conn_token_count < MAX_CONN_TOKENS) {
        conn_tokens[conn_token_count++] = token;
      } else {
        conn_overflow = true;
        break;
      }
    }
  }

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

    /////////////////////////////////////
    // 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;
    }
    ///////////////////////////
    // is hop-by-hop header? //
    ///////////////////////////
    if (HttpTransactHeaders::is_this_a_hop_by_hop_header(name.data())) {
      continue;
    }
    // Check if named in Connection header (linear scan — after cheap pointer checks above).
    // On overflow, fall back to re-scanning the Connection CSV to guarantee correctness.
    if (conn_field != nullptr) {
      bool is_conn_token = false;
      if (!conn_overflow) {
        is_conn_token = std::any_of(conn_tokens.begin(), conn_tokens.begin() + conn_token_count,
                                    [&name](swoc::TextView conn_token) { return strcasecmp(name, conn_token) == 0; });
      } else {
        HdrCsvIter csv;
        for (auto token = csv.get_first(conn_field, true); token; token = csv.get_next()) {
          if (strcasecmp(name, token) == 0) {
            is_conn_token = true;
            break;
          }
        }
      }
      if (is_conn_token) {
        continue;
      }
    }

    // Reconcile the cached header's fields of this name to exactly match the
    // response's values for this name. Each response field name is processed
    // once, when we reach its dup-list head (dups are chained in slot order, so
    // the head is encountered first). Response values are matched positionally
    // against the cached fields of the same name: existing cached slots are
    // overwritten in place, any extra response values are appended, and any
    // surplus cached values are removed.
    //
    // Reusing cached slots in place keeps the merge idempotent: re-merging an
    // unchanged response mutates the existing MIMEFields instead of stranding
    // dead slots. A deleted MIMEField slot is not reclaimed until its whole
    // field block empties, so a delete-and-recreate merge grows the cached
    // header heap on every revalidation until it crosses the aggregation
    // fragment limit and the cache write can no longer commit, freezing the
    // object stale.
    if (!field.is_dup_head()) {
      continue; // a non-head dup: already handled when its dup-list head was processed
    }

    MIMEField *cached_field = cached_header->field_find(name);
    for (MIMEField *resp_field = &field; resp_field != nullptr; resp_field = resp_field->m_next_dup) {
      auto value{resp_field->value_get()};
      if (cached_field != nullptr) {
        // overwrite an existing cached value of this name in place (reuses the slot)
        cached_header->field_value_set(cached_field, value);
        cached_field = cached_field->m_next_dup;
      } else {
        // the response has more values of this name than the cached header
        MIMEField *new_field = cached_header->field_create(name);
        cached_header->field_attach(new_field);
        cached_header->field_value_set(new_field, value);
      }
    }
    // remove any surplus cached values of this name the response no longer carries
    while (cached_field != nullptr) {
      MIMEField *next = cached_field->m_next_dup;
      cached_header->field_delete(cached_field, false /* this dup only */);
      cached_field = next;
    }
  }

  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;

  // Prefer the PROXY-Protocol source address when one is present, so that
  // Client-ip and X-Forwarded-For agree with Forwarded: for= regardless of
  // whether the listener carries the :pp-clnt flag.
  IpEndpoint src_addr = s->client_info.src_addr;
  if (s->state_machine->get_ua_txn() && s->state_machine->get_ua_txn()->get_netvc()) {
    const ProxyProtocol &pp = s->state_machine->get_ua_txn()->get_netvc()->get_proxy_protocol_info();
    if (pp.version != ProxyProtocolVersion::UNDEFINED) {
      src_addr = pp.src_addr;
    }
  }

  if (!ats_is_ip(&src_addr.sa)) {
    return;
  }

  // Always prepare the IP string.
  if (ats_ip_ntop(&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;
  }

  // RFC 9112: If chunked is present in Transfer-Encoding, it must be the
  // final encoding. Reject the request if chunked appears before other values.
  if (incoming_hdr->presence(MIME_PRESENCE_TRANSFER_ENCODING)) {
    MIMEField *field         = incoming_hdr->field_find(static_cast<std::string_view>(MIME_FIELD_TRANSFER_ENCODING));
    bool       found_chunked = false;

    while (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()) {
          found_chunked = true;
        } else if (found_chunked) {
          return RequestError_t::BAD_HTTP_HEADER_SYNTAX;
        }
        enc_value = enc_val_iter.get_next(&enc_val_len);
      }
      field = field->m_next_dup;
    }
  }

  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/QUERY
    if ((scheme == URL_WKSIDX_HTTP || scheme == URL_WKSIDX_HTTPS) &&
        (method == HTTP_WKSIDX_POST || method == HTTP_WKSIDX_PUSH || method == HTTP_WKSIDX_PUT || method == HTTP_WKSIDX_QUERY) &&
        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()) {
          // Only treat as chunked if it is the last Transfer-Encoding value (RFC 9112)
          if (enc_val_iter.get_next(&enc_val_len) == nullptr) {
            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_QUERY) {
    Metrics::Counter::increment(http_rsb.query_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,
                                          std::string_view{new_enc_val, static_cast<std::string_view::size_type>(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);

  MgmtInt max_age       = get_max_age(cached_response);
  MgmtInt max_stale_age = s->txn_conf->cache_max_stale_age;
  MgmtInt max_stale_percentage =
    std::clamp(s->txn_conf->cache_max_stale_age_percent, static_cast<MgmtInt>(0), static_cast<MgmtInt>(100));

  if (max_stale_percentage > 0 && max_age >= 0) {
    MgmtInt percent_max_stale_age = max_age * max_stale_percentage / 100;

    max_stale_age = std::min(max_stale_age, percent_max_stale_age);
  }

  // Negative age is overflow
  if ((current_age < 0) || (current_age > max_age + max_stale_age)) {
    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::NO_CONTENT) ||
      (response_code == HTTPStatus::MOVED_PERMANENTLY) || (response_code == HTTPStatus::PERMANENT_REDIRECT) ||
      (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 (s->state_machine->origin_retry_body_unavailable) {
    return false;
  }

  // Safe methods (RFC 9110, section 9.2.1) can be retried irrespective of bytes sent or connection state. QUERY
  // (draft-ietf-httpbis-safe-method-w-body) is safe too, but its content is not kept for replay on this path, so once
  // any part of its request has been sent it is treated like an unsafe method, whether or not the content itself went
  // out. A buffered QUERY can still be retried when the origin reports it was not processed, see
  // HttpSM::prepare_for_origin_retry.
  // Otherwise, if there was no error establishing the connection (and we sent bytes)-- we cannot retry
  bool const retry_only_before_sending = !HttpTransactHeaders::is_method_safe(s->method) || s->method == HTTP_WKSIDX_QUERY;

  if (retry_only_before_sending && 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, bool is_outbound_transparent)
{
  // 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 any of the proxy's local addresses. In outbound-transparent mode we also allow
      // the outbound destination to match the client's original connection destination
      // (client_info.dst_addr), because that equality is expected for every transparent
      // request (the client's original destination IS the legitimate upstream) and would
      // false-positive this check.
      TxnDbg(dbg_ctl_http_transact, "dst_port = %d local_port = %d", dst_port, local_port);
      if (dst_port == local_port && (Machine::instance()->is_self(s->dns_info.active->data.ip) ||
                                     (!is_outbound_transparent && 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);

      // Report what was removed, so a caller holding one piece of a larger resource
      // can learn its extent without a second lookup. Not Content-Range itself: on
      // a 200 that is meaningless per RFC 9110, and cache_range_requests reads the
      // pair as a stored 206 being served as 200 and rewrites the status.
      if (cache_hit == true && s->method == HTTP_WKSIDX_PURGE && s->cache_info.object_read != nullptr) {
        // read by the slice plugin as PURGED_CONTENT_RANGE in plugins/slice/HttpHeader.h
        static constexpr std::string_view PURGED_CONTENT_RANGE{"X-Purged-Content-Range"};
        HTTPHdr *const                    cached_response = s->cache_info.object_read->response_get();

        if (cached_response != nullptr) {
          auto value{cached_response->value_get(static_cast<std::string_view>(MIME_FIELD_CONTENT_RANGE))};
          if (!value.empty()) {
            s->hdr_info.client_response.value_set(PURGED_CONTENT_RANGE, value);
            TxnDbg(dbg_ctl_http_trans, "PURGE reporting X-Purged-Content-Range: %.*s", static_cast<int>(value.length()),
                   value.data());
          }
        }
      }

      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.get());

  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);
    if (s->internal_msg_buffer_type == nullptr) {
      s->internal_msg_buffer_type = ats_strdup(body_type);
    }
  } else {
    s->internal_msg_buffer_type = static_cast<char *>(ats_free_null(s->internal_msg_buffer_type));
    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, 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
