Should I continue this way? Simply to propose patches?

On Sat, Oct 19, 2013 at 4:13 PM, Eric Covener <cove...@gmail.com> wrote:

> Currently, when the body is consumed by a handler, a side effect is
> reading footers that might be present and copying them to
> r->headers_in.
>
> This presents a series of problems.
>
> * things that inspect r->headers_in expect it to be fluffed up much
> earlier than midway through the handler phase
>
> * if the handler looks at headers before reading the body, they could
> differ from what's logged
>
> * if the handler looks at headers after reading the body, mod_headers
> was out of the loop if configured.
>
> I am thinking:
>
> now:
>
> 1) add r->footers_in and use it in 2.2 and up by default
>

Do that mean no API/ABI change ?



> 2) add a directive to copy them up to r->headers_in (for those broken
> by the change)
>
> soon:
>
> 3) add a hook to parse footers
>
> later:
> 4) try to teach mod_headers to do something useful with that hook, but
> not with existing directives.
> 5) teach mod_log_config to log from footers_in
>

Not done (yet), maybe I could try or am I completely bogged down with the
design?

Maybe it worth also :
6) teach ap_expr/ssl_lookup to interpolate from footers
7) teach mod_rewrite (hooked) how to play with footers
8) teach mod_proxy_http to forward the footers

A proposition for 8) follows.

Regards.

Index: modules/proxy/proxy_util.c
===================================================================
--- modules/proxy/proxy_util.c    (revision 1534970)
+++ modules/proxy/proxy_util.c    (working copy)
@@ -3114,11 +3114,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
                                             char **old_te_val)
 {
     conn_rec *c = r->connection;
-    int counter;
     char *buf;
-    const apr_array_header_t *headers_in_array;
-    const apr_table_entry_t *headers_in;
-    apr_table_t *headers_in_copy;
     apr_bucket *e;
     int do_100_continue;
     conn_rec *origin = p_conn->connection;
@@ -3278,19 +3274,42 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
     }

     proxy_run_fixups(r);
+    return ap_proxy_fill_hdrbrgd(p, header_brigade, r->headers_in, r,
+                                 old_cl_val, old_te_val);
+}
+
+PROXY_DECLARE(int) ap_proxy_fill_hdrbrgd(apr_pool_t *p,
+                                         apr_bucket_brigade
*header_brigade,
+                                         const apr_table_t *header_table,
+                                         request_rec *r, char **old_cl_val,
+                                         char **old_te_val)
+{
+    const apr_array_header_t *headers_in_array;
+    const apr_table_entry_t *headers_in;
+    apr_table_t *headers_in_copy;
+    apr_bucket *e;
+    int counter;
+    char *buf;
+
+    /* easy path first */
+    if (apr_is_empty_table(header_table)) {
+        return OK;
+    }
+
     /*
-     * Make a copy of the headers_in table before clearing the connection
+     * Make a copy of the header_table before clearing the connection
      * headers as we need the connection headers later in the http output
      * filter to prepare the correct response headers.
      *
      * Note: We need to take r->pool for apr_table_copy as the key / value
-     * pairs in r->headers_in have been created out of r->pool and
-     * p might be (and actually is) a longer living pool.
+     * pairs in header_table (eg. r->headers/footers_in) have been created
+     * out of r->pool and p might be (and actually is) a longer living
pool.
      * This would trigger the bad pool ancestry abort in apr_table_copy if
      * apr is compiled with APR_POOL_DEBUG.
      */
-    headers_in_copy = apr_table_copy(r->pool, r->headers_in);
+    headers_in_copy = apr_table_copy(r->pool, header_table);
     ap_proxy_clear_connection(r, headers_in_copy);
+
     /* send request headers */
     headers_in_array = apr_table_elts(headers_in_copy);
     headers_in = (const apr_table_entry_t *) headers_in_array->elts;
@@ -3317,7 +3336,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
          * If we have used it then MAYBE: RFC2616 says we MAY propagate it.
          * So let's make it configurable by env.
          */
-        if (!strcasecmp(headers_in[counter].key,"Proxy-Authorization")) {
+        if (!strcasecmp(headers_in[counter].key, "Proxy-Authorization")) {
             if (r->user != NULL) { /* we've authenticated */
                 if (!apr_table_get(r->subprocess_env, "Proxy-Chain-Auth"))
{
                     continue;
@@ -3328,17 +3347,21 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
         /* Skip Transfer-Encoding and Content-Length for now.
          */
         if (!strcasecmp(headers_in[counter].key, "Transfer-Encoding")) {
-            *old_te_val = headers_in[counter].val;
+            if (old_te_val) {
+                *old_te_val = headers_in[counter].val;
+            }
             continue;
         }
         if (!strcasecmp(headers_in[counter].key, "Content-Length")) {
-            *old_cl_val = headers_in[counter].val;
+            if (old_cl_val) {
+                *old_cl_val = headers_in[counter].val;
+            }
             continue;
         }

         /* for sub-requests, ignore freshness/expiry headers */
         if (r->main) {
-            if (    !strcasecmp(headers_in[counter].key, "If-Match")
+            if (   !strcasecmp(headers_in[counter].key, "If-Match")
                 || !strcasecmp(headers_in[counter].key,
"If-Modified-Since")
                 || !strcasecmp(headers_in[counter].key, "If-Range")
                 || !strcasecmp(headers_in[counter].key,
"If-Unmodified-Since")
@@ -3351,9 +3374,11 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
                           headers_in[counter].val, CRLF,
                           NULL);
         ap_xlate_proto_to_ascii(buf, strlen(buf));
-        e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
+        e = apr_bucket_pool_create(buf, strlen(buf), p,
+                                   r->connection->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(header_brigade, e);
     }
+
     return OK;
 }

Index: modules/proxy/mod_proxy_http.c
===================================================================
--- modules/proxy/mod_proxy_http.c    (revision 1534970)
+++ modules/proxy/mod_proxy_http.c    (working copy)
@@ -339,11 +339,11 @@ static int stream_reqbody_chunked(apr_pool_t *p,
         bb = input_brigade;
     }

-    e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF
-                                   /* <trailers> */
-                                   ASCII_CRLF,
-                                   5, bucket_alloc);
+    e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF, 3, bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(bb, e);
+    ap_proxy_fill_hdrbrgd(p, bb, r->footers_in, r, NULL, NULL);
+    e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(bb, e);

     if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) {
         e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
@@ -994,6 +994,7 @@ static request_rec *make_fake_req(conn_rec *c, req
     rp->status          = HTTP_OK;

     rp->headers_in      = apr_table_make(pool, 50);
+    rp->footers_in      = apr_table_make(pool, 5);
     rp->subprocess_env  = apr_table_make(pool, 50);
     rp->headers_out     = apr_table_make(pool, 12);
     rp->err_headers_out = apr_table_make(pool, 5);
Index: modules/proxy/mod_proxy.h
===================================================================
--- modules/proxy/mod_proxy.h    (revision 1534970)
+++ modules/proxy/mod_proxy.h    (working copy)
@@ -971,6 +971,21 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
                                            char **old_te_val);

 /**
+ * Fill a HTTP request header brigade,  old_cl_val and old_te_val as
required.
+ * @param p               pool
+ * @param header_brigade  header brigade to fill
+ * @param header_table    header table to use
+ * @param r               request
+ * @param old_cl_val      stored old content-len val
+ * @param old_te_val      stored old TE val
+ * @return                OK
+ */
+PROXY_DECLARE(int) ap_proxy_fill_hdrbrgd(apr_pool_t *p,
+                                         apr_bucket_brigade
*header_brigade,
+                                         const apr_table_t *header_table,
+                                         request_rec *r, char **old_cl_val,
+                                         char **old_te_val);
+/**
  * @param bucket_alloc  bucket allocator
  * @param r             request
  * @param p_conn        proxy connection
[EOS]
Index: modules/proxy/proxy_util.c
===================================================================
--- modules/proxy/proxy_util.c	(revision 1534970)
+++ modules/proxy/proxy_util.c	(working copy)
@@ -3114,11 +3114,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
                                             char **old_te_val)
 {
     conn_rec *c = r->connection;
-    int counter;
     char *buf;
-    const apr_array_header_t *headers_in_array;
-    const apr_table_entry_t *headers_in;
-    apr_table_t *headers_in_copy;
     apr_bucket *e;
     int do_100_continue;
     conn_rec *origin = p_conn->connection;
@@ -3278,19 +3274,42 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
     }
 
     proxy_run_fixups(r);
+    return ap_proxy_fill_hdrbrgd(p, header_brigade, r->headers_in, r,
+                                 old_cl_val, old_te_val);
+}
+
+PROXY_DECLARE(int) ap_proxy_fill_hdrbrgd(apr_pool_t *p,
+                                         apr_bucket_brigade *header_brigade,
+                                         const apr_table_t *header_table,
+                                         request_rec *r, char **old_cl_val,
+                                         char **old_te_val)
+{
+    const apr_array_header_t *headers_in_array;
+    const apr_table_entry_t *headers_in;
+    apr_table_t *headers_in_copy;
+    apr_bucket *e;
+    int counter;
+    char *buf;
+
+    /* easy path first */
+    if (apr_is_empty_table(header_table)) {
+        return OK;
+    }
+
     /*
-     * Make a copy of the headers_in table before clearing the connection
+     * Make a copy of the header_table before clearing the connection
      * headers as we need the connection headers later in the http output
      * filter to prepare the correct response headers.
      *
      * Note: We need to take r->pool for apr_table_copy as the key / value
-     * pairs in r->headers_in have been created out of r->pool and
-     * p might be (and actually is) a longer living pool.
+     * pairs in header_table (eg. r->headers/footers_in) have been created
+     * out of r->pool and p might be (and actually is) a longer living pool.
      * This would trigger the bad pool ancestry abort in apr_table_copy if
      * apr is compiled with APR_POOL_DEBUG.
      */
-    headers_in_copy = apr_table_copy(r->pool, r->headers_in);
+    headers_in_copy = apr_table_copy(r->pool, header_table);
     ap_proxy_clear_connection(r, headers_in_copy);
+
     /* send request headers */
     headers_in_array = apr_table_elts(headers_in_copy);
     headers_in = (const apr_table_entry_t *) headers_in_array->elts;
@@ -3317,7 +3336,7 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
          * If we have used it then MAYBE: RFC2616 says we MAY propagate it.
          * So let's make it configurable by env.
          */
-        if (!strcasecmp(headers_in[counter].key,"Proxy-Authorization")) {
+        if (!strcasecmp(headers_in[counter].key, "Proxy-Authorization")) {
             if (r->user != NULL) { /* we've authenticated */
                 if (!apr_table_get(r->subprocess_env, "Proxy-Chain-Auth")) {
                     continue;
@@ -3328,17 +3347,21 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
         /* Skip Transfer-Encoding and Content-Length for now.
          */
         if (!strcasecmp(headers_in[counter].key, "Transfer-Encoding")) {
-            *old_te_val = headers_in[counter].val;
+            if (old_te_val) {
+                *old_te_val = headers_in[counter].val;
+            }
             continue;
         }
         if (!strcasecmp(headers_in[counter].key, "Content-Length")) {
-            *old_cl_val = headers_in[counter].val;
+            if (old_cl_val) {
+                *old_cl_val = headers_in[counter].val;
+            }
             continue;
         }
 
         /* for sub-requests, ignore freshness/expiry headers */
         if (r->main) {
-            if (    !strcasecmp(headers_in[counter].key, "If-Match")
+            if (   !strcasecmp(headers_in[counter].key, "If-Match")
                 || !strcasecmp(headers_in[counter].key, "If-Modified-Since")
                 || !strcasecmp(headers_in[counter].key, "If-Range")
                 || !strcasecmp(headers_in[counter].key, "If-Unmodified-Since")
@@ -3351,9 +3374,11 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
                           headers_in[counter].val, CRLF,
                           NULL);
         ap_xlate_proto_to_ascii(buf, strlen(buf));
-        e = apr_bucket_pool_create(buf, strlen(buf), p, c->bucket_alloc);
+        e = apr_bucket_pool_create(buf, strlen(buf), p,
+                                   r->connection->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(header_brigade, e);
     }
+
     return OK;
 }
 
Index: modules/proxy/mod_proxy_http.c
===================================================================
--- modules/proxy/mod_proxy_http.c	(revision 1534970)
+++ modules/proxy/mod_proxy_http.c	(working copy)
@@ -339,11 +339,11 @@ static int stream_reqbody_chunked(apr_pool_t *p,
         bb = input_brigade;
     }
 
-    e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF
-                                   /* <trailers> */
-                                   ASCII_CRLF,
-                                   5, bucket_alloc);
+    e = apr_bucket_immortal_create(ASCII_ZERO ASCII_CRLF, 3, bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(bb, e);
+    ap_proxy_fill_hdrbrgd(p, bb, r->footers_in, r, NULL, NULL);
+    e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(bb, e);
 
     if (apr_table_get(r->subprocess_env, "proxy-sendextracrlf")) {
         e = apr_bucket_immortal_create(ASCII_CRLF, 2, bucket_alloc);
@@ -994,6 +994,7 @@ static request_rec *make_fake_req(conn_rec *c, req
     rp->status          = HTTP_OK;
 
     rp->headers_in      = apr_table_make(pool, 50);
+    rp->footers_in      = apr_table_make(pool, 5);
     rp->subprocess_env  = apr_table_make(pool, 50);
     rp->headers_out     = apr_table_make(pool, 12);
     rp->err_headers_out = apr_table_make(pool, 5);
Index: modules/proxy/mod_proxy.h
===================================================================
--- modules/proxy/mod_proxy.h	(revision 1534970)
+++ modules/proxy/mod_proxy.h	(working copy)
@@ -971,6 +971,21 @@ PROXY_DECLARE(int) ap_proxy_create_hdrbrgd(apr_poo
                                            char **old_te_val);
 
 /**
+ * Fill a HTTP request header brigade,  old_cl_val and old_te_val as required.
+ * @param p               pool
+ * @param header_brigade  header brigade to fill
+ * @param header_table    header table to use
+ * @param r               request
+ * @param old_cl_val      stored old content-len val
+ * @param old_te_val      stored old TE val
+ * @return                OK
+ */
+PROXY_DECLARE(int) ap_proxy_fill_hdrbrgd(apr_pool_t *p,
+                                         apr_bucket_brigade *header_brigade,
+                                         const apr_table_t *header_table,
+                                         request_rec *r, char **old_cl_val,
+                                         char **old_te_val);
+/**
  * @param bucket_alloc  bucket allocator
  * @param r             request
  * @param p_conn        proxy connection

Reply via email to