Hi all,

I am currently investigating why and how to cope with the pre_connection hook is called twice for a single request. As I understand it, the reason is that the module in question handles also reverse proxy requests. And ap_run_pre_connection() is not only called by the core in ap_process_connection(), but also by several proxy related modules, e.g. from within ap_proxy_connection_create().

Now, how do I avoid executing the code hooked into the pre_connection hook more than once?

For most other hooks the request_rec is available which has the needed information in the proxyreq member. But in the pre_connection hook it isn't.

To give module authors a means to differentiate between the incoming connection that lead to creating a request and outgoing connection that are created because a request is being processed, I want to suggest to add a struct member 'direction' to the conn_rec to keep track of the direction of the connection. When zero-ing the struct (e.g. by using pcalloc), .direction is initialized to AP_CONN_INCOMING (= 0). Whenever a module creates another connection and intends to call ap_run_pre_connection on it, this module needs to make sure to set .direction to AP_CONN_OUTGOING. This way the code called from the pre_connection hook can decide whether to run on the provided conn_rec or not.

The patch below is a draft (based on some patched httpd 2.4.10 version) for how this could be implemented. It definitely needs an additional check for other places where ap_run_pre_connection() is called. But I want to provide it to get early feedback on my idea. So, what do you think?

Best regards,
Micha



diff --git a/include/httpd.h b/include/httpd.h
index e1510be..00dd5c4 100644
--- a/include/httpd.h
+++ b/include/httpd.h
@@ -1063,6 +1063,11 @@ typedef enum {
     AP_CONN_KEEPALIVE
 } ap_conn_keepalive_e;

+typedef enum {
+    AP_CONN_INCOMING = 0,
+    AP_CONN_OUTGOING
+} ap_conn_direction_e;
+
 /**
  * @brief Structure to store things which are per connection
  */
@@ -1151,6 +1156,8 @@ struct conn_rec {
      */
     const char *log_id;

+    ap_conn_direction_e direction;
+

/** This points to the current thread being used to process this request, * over the lifetime of a request, the value may change. Users of the connection
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index bc84049..26e731c 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -2853,6 +2853,9 @@ PROXY_DECLARE(int) ap_proxy_connection_create(const char *proxy_function,
         return HTTP_INTERNAL_SERVER_ERROR;
     }

+    /* Proxy connections are by definition outgoing connections */
+    conn->connection->direction = AP_CONN_OUTGOING;
+
     /* For ssl connection to backend */
     if (conn->is_ssl) {
         if (!ap_proxy_ssl_enable(conn->connection)) {

Reply via email to