HttpTransact::EndRemapRequest(State* s)
{
  DebugTxn("http_trans", "START HttpTransact::EndRemapRequest");

  HTTPHdr *incoming_request = &s->hdr_info.client_request;
  int method = incoming_request->method_get_wksidx();
  int host_len;
  const char *host = incoming_request->host_get(&host_len);
  DebugTxn("http_trans","EndRemapRequest host is %.*s", host_len,host);

  ////////////////////////////////////////////////////////////////
  // if we got back a URL to redirect to, vector the user there //
  ////////////////////////////////////////////////////////////////
  if (s->remap_redirect != NULL) {
    SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
    if (s->http_return_code == HTTP_STATUS_MOVED_PERMANENTLY) {
      build_error_response(s, HTTP_STATUS_MOVED_PERMANENTLY, "Redirect", "redirect#moved_permanently", NULL);
    } else {
      build_error_response(s, HTTP_STATUS_MOVED_TEMPORARILY, "Redirect", "redirect#moved_temporarily", NULL);
    }
    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_enabled) {
    build_error_response(s, HTTP_STATUS_FORBIDDEN, "Access Denied", "access#denied", NULL);
    s->reverse_proxy = false;
    goto done;
  }
  /////////////////////////////////////////////////////////////////
  // Check if remap plugin set HTTP return code and return body  //
  /////////////////////////////////////////////////////////////////
  if (s->http_return_code != HTTP_STATUS_NONE) {
    build_error_response(s, s->http_return_code, NULL, NULL,
                         s->internal_msg_buffer_size ? s->internal_msg_buffer : NULL);
    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)) {
      DebugTxn("http_trans", "END HttpTransact::RemapRequest");
      TRANSACT_RETURN(SM_ACTION_INTERNAL_CACHE_NOOP, NULL);
    }

    /////////////////////////////////////////////////////////
    // 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, HTTP_STATUS_MOVED_TEMPORARILY, "Redirect For Explanation", "request#no_host", NULL);
        s->hdr_info.client_response.value_set(MIME_FIELD_LOCATION, MIME_LEN_LOCATION, redirect_url, redirect_url_len);
      // socket when there is no host. Need to handle DNS failure elsewhere.
      } else if (host == NULL) {    /* no host */
        build_error_response(s, HTTP_STATUS_BAD_REQUEST, "Host Header Required", "request#no_host", NULL);
      } else {
        build_error_response(s, HTTP_STATUS_NOT_FOUND, "Not Found on Accelerator", "urlrouting#no_mapping", NULL);
      }
      s->reverse_proxy = false;
      goto done;
    } else if (s->http_config_param->url_remap_required && !s->cop_test_page) {
      ///////////////////////////////////////////////////////
      // the url mapping failed, but mappings are strictly //
      // required (except for synthetic cop accesses), so  //
      // return an error message.                          //
      ///////////////////////////////////////////////////////

      SET_VIA_STRING(VIA_DETAIL_TUNNEL, VIA_DETAIL_TUNNEL_NO_FORWARD);
      build_error_response(s, HTTP_STATUS_NOT_FOUND, "Not Found", "urlrouting#no_mapping", NULL);

      s->reverse_proxy = false;
      goto done;
    }
  } else {
    if (s->http_config_param->reverse_proxy_enabled) {
      s->req_flavor = REQ_FLAVOR_REVPROXY;
    }
  }
  s->reverse_proxy = true;
  s->server_info.is_transparent = s->state_machine->ua_session ? s->state_machine->ua_session->f_outbound_transparent : false;

done:
  if (is_debug_tag_set("http_chdr_describe") || is_debug_tag_set("http_trans") || is_debug_tag_set("url_rewrite")) {
    DebugTxn("http_trans", "After Remapping:");
    obj_describe(s->hdr_info.client_request.m_http, 1);
  }

  /*
    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 == HTTP_NO_PLUGIN_TUNNEL) {
    DebugTxn("http_trans", "END HttpTransact::EndRemapRequest");
    HTTP_INCREMENT_TRANS_STAT(http_invalid_client_requests_stat);
    TRANSACT_RETURN(SM_ACTION_SEND_ERROR_CACHE_NOOP, NULL);
  } else {
    s->hdr_info.client_response.clear(); //anything previously set is invalid from this point forward
    DebugTxn("http_trans", "END HttpTransact::EndRemapRequest");

    if (s->is_upgrade_request && s->post_remap_upgrade_return_point) {
      TRANSACT_RETURN(SM_ACTION_API_POST_REMAP, s->post_remap_upgrade_return_point);
    }

    TRANSACT_RETURN(SM_ACTION_API_POST_REMAP, HttpTransact::HandleRequest);
  }

  ink_assert(!"not reached");
}