[PATCH] HTTP: implement 'connect' and 'close' phases

Alessandro Ghedini alessandro at cloudflare.com
Fri Nov 20 09:45:53 UTC 2015


# HG changeset patch
# User Alessandro Ghedini <alessandro at cloudflare.com>
# Date 1447956026 0
#      Thu Nov 19 18:00:26 2015 +0000
# Node ID 9d265c320050a00ff24fa8d84371701e46147e8a
# Parent  bec5b3093337708cbdb59f9fc253f8e1cd6d7848
HTTP: implement 'connect' and 'close' phases

This patch adds the NGX_HTTP_CONNECT_PHASE and NGX_HTTP_CLOSE_PHASE
phases.

Handlers for these phases are called when a connection is estabilished
and when it is closed, and they take a ngx_connection_t as argument
instead of ngx_http_request_t like the other phase handlers.

These can be useful for keeping track of TCP connections for debugging,
monitoring and logging purposes, and can also be used to apply custom
configurations (e.g. socket options).

This patch also adds a "ctx" field to ngx_connection_t, to be used by
modules to store their own context structures (just like the ctx field
in ngx_http_request_t).

diff -r bec5b3093337 -r 9d265c320050 src/core/ngx_connection.h
--- a/src/core/ngx_connection.h	Tue Nov 17 19:41:39 2015 +0300
+++ b/src/core/ngx_connection.h	Thu Nov 19 18:00:26 2015 +0000
@@ -36,6 +36,7 @@
 
     /* handler of accepted connection */
     ngx_connection_handler_pt   handler;
+    void               *handler_data;
 
     void               *servers;  /* array of ngx_http_in_addr_t, for example */
 
@@ -133,6 +134,8 @@
     ngx_recv_chain_pt   recv_chain;
     ngx_send_chain_pt   send_chain;
 
+    void              **ctx;
+
     ngx_listening_t    *listening;
 
     off_t               sent;
diff -r bec5b3093337 -r 9d265c320050 src/http/ngx_http.c
--- a/src/http/ngx_http.c	Tue Nov 17 19:41:39 2015 +0300
+++ b/src/http/ngx_http.c	Thu Nov 19 18:00:26 2015 +0000
@@ -396,6 +396,20 @@
         return NGX_ERROR;
     }
 
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONNECT_PHASE].handlers,
+                       cf->pool, 1, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    if (ngx_array_init(&cmcf->phases[NGX_HTTP_CLOSE_PHASE].handlers,
+                       cf->pool, 1, sizeof(ngx_http_handler_pt))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
     if (ngx_array_init(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers,
                        cf->pool, 1, sizeof(ngx_http_handler_pt))
         != NGX_OK)
@@ -1776,6 +1790,8 @@
     ls->pool_size = cscf->connection_pool_size;
     ls->post_accept_timeout = cscf->client_header_timeout;
 
+    ls->handler_data = cscf->ctx;
+
     clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
 
     ls->logp = clcf->error_log;
diff -r bec5b3093337 -r 9d265c320050 src/http/ngx_http_core_module.h
--- a/src/http/ngx_http_core_module.h	Tue Nov 17 19:41:39 2015 +0300
+++ b/src/http/ngx_http_core_module.h	Thu Nov 19 18:00:26 2015 +0000
@@ -134,6 +134,9 @@
     NGX_HTTP_TRY_FILES_PHASE,
     NGX_HTTP_CONTENT_PHASE,
 
+    NGX_HTTP_CONNECT_PHASE,
+    NGX_HTTP_CLOSE_PHASE,
+
     NGX_HTTP_LOG_PHASE
 } ngx_http_phases;
 
diff -r bec5b3093337 -r 9d265c320050 src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c	Tue Nov 17 19:41:39 2015 +0300
+++ b/src/http/ngx_http_request.c	Thu Nov 19 18:00:26 2015 +0000
@@ -37,6 +37,8 @@
 static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
+static ngx_int_t ngx_http_run_conn_phases(ngx_connection_t *c,
+    ngx_http_phases p);
 
 static void ngx_http_request_handler(ngx_event_t *ev);
 static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
@@ -214,6 +216,12 @@
 
     c->data = hc;
 
+    c->ctx = ngx_pcalloc(c->pool, sizeof(void *) * ngx_http_max_module);
+    if (c->ctx == NULL) {
+        ngx_http_close_connection(c);
+        return;
+    }
+
     /* find the server configuration for the address:port */
 
     port = c->listening->servers;
@@ -318,6 +326,8 @@
     }
 #endif
 
+    ngx_http_run_conn_phases(c, NGX_HTTP_CONNECT_PHASE);
+
 #if (NGX_HTTP_SSL)
     {
     ngx_http_ssl_srv_conf_t  *sscf;
@@ -3522,6 +3532,31 @@
 }
 
 
+ngx_int_t
+ngx_http_run_conn_phases(ngx_connection_t *c, ngx_http_phases p)
+{
+    ngx_uint_t                  i, n;
+    ngx_http_conf_ctx_t        *ctx;
+    ngx_http_conn_handler_pt   *handler;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    ctx = c->listening->handler_data;
+
+    cmcf = ngx_http_get_module_main_conf(ctx, ngx_http_core_module);
+
+    if (c->fd != (ngx_socket_t) -1) {
+        handler = cmcf->phases[p].handlers.elts;
+        n = cmcf->phases[p].handlers.nelts;
+
+        for (i = 0; i < n; i++) {
+            handler[i](c);
+        }
+    }
+
+    return NGX_OK;
+}
+
+
 void
 ngx_http_close_connection(ngx_connection_t *c)
 {
@@ -3530,6 +3565,8 @@
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "close http connection: %d", c->fd);
 
+    ngx_http_run_conn_phases(c, NGX_HTTP_CLOSE_PHASE);
+
 #if (NGX_HTTP_SSL)
 
     if (c->ssl) {
diff -r bec5b3093337 -r 9d265c320050 src/http/ngx_http_request.h
--- a/src/http/ngx_http_request.h	Tue Nov 17 19:41:39 2015 +0300
+++ b/src/http/ngx_http_request.h	Thu Nov 19 18:00:26 2015 +0000
@@ -354,6 +354,7 @@
 
 
 typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);
+typedef ngx_int_t (*ngx_http_conn_handler_pt)(ngx_connection_t *c);
 typedef void (*ngx_http_event_handler_pt)(ngx_http_request_t *r);
 
 



More information about the nginx-devel mailing list