HttpTransact::build_response(State* s, HTTPHdr* base_response, HTTPHdr* outgoing_response, HTTPVersion outgoing_version,
                             HTTPStatus status_code, const char *reason_phrase)
{
  if (reason_phrase == NULL) {
    reason_phrase = http_hdr_reason_lookup(status_code);
  }

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

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

      // Note: We need to handle the "Content-Length" header first here
      //  since handle_content_length_header()
      //  determines whether we accept origin server's content-length.
      //  We need to have made a decision regard the content-length
      //  before processing the keep_alive headers
      //
      handle_content_length_header(s, outgoing_response, base_response);
    } else
      switch (status_code) {
      case HTTP_STATUS_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 char *field_name[] = { MIME_FIELD_ETAG,
                                              MIME_FIELD_CONTENT_LOCATION,
                                              MIME_FIELD_EXPIRES,
                                              MIME_FIELD_CACHE_CONTROL,
                                              MIME_FIELD_VARY
          };
          static int field_len[] = { MIME_LEN_ETAG,
                                     MIME_LEN_CONTENT_LOCATION,
                                     MIME_LEN_EXPIRES,
                                     MIME_LEN_CACHE_CONTROL,
                                     MIME_LEN_VARY
          };
          static uint64_t field_presence[] = { MIME_PRESENCE_ETAG,
                                               MIME_PRESENCE_CONTENT_LOCATION,
                                               MIME_PRESENCE_EXPIRES,
                                               MIME_PRESENCE_CACHE_CONTROL,
                                               MIME_PRESENCE_VARY
          };
          MIMEField *field;
          int len;
          const char *value;

          for (size_t i = 0; i < sizeof(field_len) / sizeof(field_len[0]); i++) {
            if (base_response->presence(field_presence[i])) {
              field = base_response->field_find(field_name[i], field_len[i]);
              value = field->value_get(&len);
              outgoing_response->value_append(field_name[i], field_len[i], value, len, 0);
            }
          }
        }
        break;

      case HTTP_STATUS_PRECONDITION_FAILED:
        // fall through
      case HTTP_STATUS_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
  if (s->orig_scheme == URL_WKSIDX_HTTPS && s->txn_conf->proxy_response_hsts_max_age >= 0) {
    Debug("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);

  HttpTransactHeaders::convert_response(outgoing_version, outgoing_response);

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

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

  // auth-response update
 // if (!s->state_machine->authAdapter.disabled()) {
  //  s->state_machine->authAdapter.UpdateResponseHeaders(outgoing_response);
 // }

  if (diags->on()) {
    if (base_response) {
      if (!s->cop_test_page)
        DUMP_HEADER("http_hdrs", base_response, s->state_machine_id, "Base Header for Building Response");
    }
    if (!s->cop_test_page)
      DUMP_HEADER("http_hdrs", outgoing_response, s->state_machine_id, "Proxy's Response 2");
  }

  return;
}