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

  /*
   * 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
   */
  MIMEField *c_hdr;
  if ((s->current.request_to != ORIGIN_SERVER) &&
      (s->current.request_to == PARENT_PROXY ||
       s->current.request_to == ICP_SUGGESTED_HOST)) {
    c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION);

    // If there is a Proxy-Connection header use that,
    //   otherwise use the Connection header
    if (c_hdr == NULL) {
      c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
    }
  } else {
    c_hdr = s->hdr_info.server_response.field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION);
  }

  s->current.server->keep_alive = is_header_keep_alive(s->hdr_info.server_response.version_get(),
                                                       s->hdr_info.server_request.version_get(), c_hdr);

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

  if (s->current.server->keep_alive == HTTP_KEEPALIVE) {
    if (!s->cop_test_page)
      DebugTxn("http_hdrs", "[initialize_state_variables_from_response]" "Server is keep-alive.");
  } else if (s->state_machine->ua_session && s->state_machine->ua_session->f_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 = HTTP_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(MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING);

    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) {
        if (!s->cop_test_page) {
          DebugTxn("http_hdrs", "[init_state_vars_from_resp] transfer encoding: chunked!");
        }
        s->current.server->transfer_encoding = CHUNKED_ENCODING;

        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 = NULL;
        HdrCsvIter new_enc_iter;
        int new_enc_len;
        const char *new_enc_val = new_enc_iter.get_first(field, &new_enc_len);

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

          new_enc_val = new_enc_iter.get_next(&new_enc_len);
        }

        // 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, MIME_FIELD_TRANSFER_ENCODING,
                                  MIME_LEN_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 = NO_TRANSFER_ENCODING;
}