]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mod_setenvif: add "early mode"
authorEric Covener <covener@apache.org>
Tue, 14 Jan 2020 23:25:24 +0000 (23:25 +0000)
committerEric Covener <covener@apache.org>
Tue, 14 Jan 2020 23:25:24 +0000 (23:25 +0000)
Primarily to run before `RequestHeader ... ... early`

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1872797 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/mod_setenvif.xml
modules/metadata/mod_setenvif.c

diff --git a/CHANGES b/CHANGES
index e0893a94c0fc6469bd591cd69f33dd0d547cf983..acee69573542fc4ecf80091cf6344d2bbef27dae 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.1
 
+  *) mod_setenvif: Passing an env-variable parameter of "--early" in non-perdir
+     context runs directives from this module before `RequestHeader ... early` 
+     are evaluated. This allows results of SetEnvIf conditionals to be used 
+     to modify request headers in early mode. [Eric Covener]
+
   *) config: Speed up graceful restarts by using pre-hashed command table. PR 64066.
      [Giovanni Bechis <giovanni paclan.it>, Jim Jagielski]
 
index 626c4cfc3d9b370dc4c426c71ef71eca5d69bd08..4024c9ec7861f988259fdc852370a1bd4cab44c2 100644 (file)
@@ -223,6 +223,13 @@ of</p>
     of <var>regex</var>. <code>$0</code> provides access to the whole
     string matched by that pattern.</p>
 
+    <p>If the special value <code>--early</code> is specified, and this
+    directive is not in directory context, the directive will be evaluated
+    earlier during request processing.  This allows the output variables
+    set by this directive to be used as input to the "early mode" option of
+    the <directive module="mod_headers">RequestHeader</directive> directive.
+    Available in 2.5.1 and later.</p>
+
 <highlight language="config">
 SetEnvIf Request_URI "\.gif$" object_is_image=gif
 SetEnvIf Request_URI "\.jpg$" object_is_image=jpg
index 23d60cdba5ac81a357c421b024a0e7a5ccc4a8ba..97e6106d966088695466b196b79c970cb9ca7b48 100644 (file)
@@ -113,13 +113,20 @@ typedef struct {
     apr_table_t *features;      /* env vars to set (or unset) */
     enum special special_type;  /* is it a "special" header ? */
     int icase;                  /* ignoring case? */
+    int early;
 } sei_entry;
 
 typedef struct {
     apr_array_header_t *conditionals;
 } sei_cfg_rec;
 
+
+typedef struct {
+   int pass;
+} sei_request_config;
+
 module AP_MODULE_DECLARE_DATA setenvif_module;
+static int has_early; /* at least 1 server-scoped SEI needs to be run early */
 
 /*
  * These routines, the create- and merge-config functions, are called
@@ -163,7 +170,6 @@ static void *merge_setenvif_config(apr_pool_t *p, void *basev, void *overridesv)
  * be used
  */
 #define ICASE_MAGIC  ((void *)(&setenvif_module))
-#define SEI_MAGIC_HEIRLOOM "setenvif-phase-flag"
 
 static ap_regex_t *is_header_regex_regex;
 
@@ -267,7 +273,13 @@ static const char *add_envvars(cmd_parms *cmd, const char *args, sei_entry *new)
             apr_table_setn(new->features, var + 1, "!");
         }
         else {
-            apr_table_setn(new->features, var, "1");
+             if (strcmp(var, "--early") == 0 && cmd->path == NULL) { 
+                 new->early = 1;
+                 has_early = 1;
+             }
+             else { 
+                 apr_table_setn(new->features, var, "1");
+             }
         }
     }
 
@@ -332,6 +344,7 @@ static const char *add_setenvif_core(cmd_parms *cmd, void *mconfig,
 
         /* no match, create a new entry */
         new = apr_array_push(sconf->conditionals);
+        new->early = 0;
         new->name = fname;
         new->regex = regex;
         new->icase = icase;
@@ -479,6 +492,7 @@ static const command_rec setenvif_module_cmds[] =
     { NULL },
 };
 
+
 /*
  * This routine gets called at two different points in request processing:
  * once before the URI has been translated (during the post-read-request
@@ -491,6 +505,7 @@ static const command_rec setenvif_module_cmds[] =
 static int match_headers(request_rec *r)
 {
     sei_cfg_rec *sconf;
+    sei_request_config *rconf;
     sei_entry *entries;
     const apr_table_entry_t *elts;
     const char *val, *err;
@@ -498,12 +513,24 @@ static int match_headers(request_rec *r)
     int i, j;
     char *last_name;
     ap_regmatch_t regm[AP_MAX_REG_MATCH];
+    int do_early = 0;
+   
+    rconf = ap_get_module_config(r->request_config, &setenvif_module);
 
-    if (!ap_get_module_config(r->request_config, &setenvif_module)) {
-        ap_set_module_config(r->request_config, &setenvif_module,
-                             SEI_MAGIC_HEIRLOOM);
+    if (!rconf) { 
+        sconf  = (sei_cfg_rec *) ap_get_module_config(r->server->module_config,
+                                                      &setenvif_module);
+        rconf = (sei_request_config*) apr_pcalloc(r->pool, sizeof(*rconf));
+        ap_set_module_config(r->request_config, &setenvif_module, rconf);
+        if (!has_early){ 
+            return DECLINED;
+        }
+        do_early = 1;
+    }
+    else if (rconf->pass == 0) { 
         sconf  = (sei_cfg_rec *) ap_get_module_config(r->server->module_config,
                                                       &setenvif_module);
+        rconf->pass++;
     }
     else {
         sconf = (sei_cfg_rec *) ap_get_module_config(r->per_dir_config,
@@ -514,6 +541,9 @@ static int match_headers(request_rec *r)
     val = NULL;
     for (i = 0; i < sconf->conditionals->nelts; ++i) {
         sei_entry *b = &entries[i];
+        if (b->early && !do_early) { 
+            continue;
+        }
 
         if (!b->expr) {
             /* Optimize the case where a bunch of directives in a row use the
@@ -636,10 +666,18 @@ static int match_headers(request_rec *r)
     return DECLINED;
 }
 
+static int sei_pre_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp)
+{
+    has_early = 0;
+    return OK;
+}
+
 static void register_hooks(apr_pool_t *p)
 {
     ap_hook_header_parser(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_post_read_request(match_headers, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_post_read_request(match_headers, NULL, NULL, APR_HOOK_REALLY_FIRST);
+    ap_hook_pre_config(sei_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
 
     is_header_regex_regex = ap_pregcomp(p, "^[-A-Za-z0-9_]*$",
                                         (AP_REG_EXTENDED | AP_REG_NOSUB ));