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