]> granicus.if.org Git - apache/commitdiff
add per-dir config merging to mod_lua so LuaHook* in multiple per-dir sections
authorEric Covener <covener@apache.org>
Sun, 13 Nov 2011 15:48:06 +0000 (15:48 +0000)
committerEric Covener <covener@apache.org>
Sun, 13 Nov 2011 15:48:06 +0000 (15:48 +0000)
behaves as expected instead of discarding previous sections.

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

CHANGES
docs/manual/mod/mod_lua.html.en
docs/manual/mod/mod_lua.xml
modules/lua/lua_vmprep.h
modules/lua/mod_lua.c
modules/lua/mod_lua.h

diff --git a/CHANGES b/CHANGES
index b611a77d66a927d61f529869f4e8baf36a7fce19..5c395c37f481c9234488758c099e500213ba03f5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.3.16
 
+  *) mod_lua: Stop losing track of all but the most specific LuaHook* directives
+     when multiple per-directory config sections are used.  Adds LuaInherit 
+     directive to control how parent sections are merged.  [Eric Covener]
+
   *) mod_cache: Make sure we merge headers correctly when we handle a
      non cacheable conditional response. PR52120. [Graham Leggett]
 
index 04b59d987bd7d9f7b5b88aa5ce2d4361e8258fec..43a2553ae85a423cbc1918ae4642f80c715e4f7a 100644 (file)
@@ -57,6 +57,7 @@ at any time.</div>
 <li><img alt="" src="../images/down.gif" /> <a href="#luahookmaptostorage">LuaHookMapToStorage</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#luahooktranslatename">LuaHookTranslateName</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#luahooktypechecker">LuaHookTypeChecker</a></li>
+<li><img alt="" src="../images/down.gif" /> <a href="#luainherit">LuaInherit</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#luamaphandler">LuaMapHandler</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#luapackagecpath">LuaPackageCPath</a></li>
 <li><img alt="" src="../images/down.gif" /> <a href="#luapackagepath">LuaPackagePath</a></li>
@@ -630,6 +631,26 @@ end
 </table><p>...</p>
 </div>
 <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
+<div class="directive-section"><h2><a name="LuaInherit" id="LuaInherit">LuaInherit</a> <a name="luainherit" id="luainherit">Directive</a></h2>
+<table class="directive">
+<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Controls how parent configuration sections are merged into children</td></tr>
+<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaInherit none|parent-first|parent-last</code></td></tr>
+<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>LuaInherit parent-first</code></td></tr>
+<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr>
+<tr><th><a href="directive-dict.html#Override">Override:</a></th><td>All</td></tr>
+<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr>
+<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr>
+<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>2.5.0 and later</td></tr>
+</table><p>By default, if LuaHook* directives are used in overlapping
+    Directory or Location configuration sections, the scripts defined in the
+    more specific section are run <em>after</em> those defined in the more
+    generic section (LuaInherit parent-first).  You can reverse this order, or
+    make the parent context not apply at all.</p>
+    
+    <p> In previous 2.3.x releases, the default was effectively to ignore LuaHook*
+    directives from parent configuration sections.</p>
+</div>
+<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div>
 <div class="directive-section"><h2><a name="LuaMapHandler" id="LuaMapHandler">LuaMapHandler</a> <a name="luamaphandler" id="luamaphandler">Directive</a></h2>
 <table class="directive">
 <tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Map a path to a lua handler</td></tr>
index f28f7300daa7e6a29420346851023270ed4384bc..7c46463e36eab03a0a456ab056e070dbde3775d8 100644 (file)
@@ -725,6 +725,26 @@ hook function usually returns OK, DECLINED, or HTTP_FORBIDDEN.</p>
     <usage><p>Not Yet Implemented</p></usage>
 </directivesynopsis>
 
+<directivesynopsis>
+<name>LuaInherit</name>
+<description>Controls how parent configuration sections are merged into children</description>
+<syntax>LuaInherit none|parent-first|parent-last</syntax>
+<default>LuaInherit parent-first</default>
+<compatibility>2.5.0 and later</compatibility>
+<contextlist><context>server config</context><context>virtual host</context>
+<context>directory</context><context>.htaccess</context>
+</contextlist>
+<override>All</override>
+    <usage><p>By default, if LuaHook* directives are used in overlapping
+    Directory or Location configuration sections, the scripts defined in the
+    more specific section are run <em>after</em> those defined in the more
+    generic section (LuaInherit parent-first).  You can reverse this order, or
+    make the parent context not apply at all.</p>
+    
+    <p> In previous 2.3.x releases, the default was effectively to ignore LuaHook*
+    directives from parent configuration sections.</p></usage>
+</directivesynopsis>
+
 <directivesynopsis>
 <name>LuaQuickHandler</name>
 <description>Provide a hook for the quick handler of request processing</description>
index ed9c65ef28c8dcfbde2cd16592925c960f7a4630..be1750df7cd5eb3ddb6e5a0231a796c09a9d51f0 100644 (file)
@@ -34,6 +34,7 @@
 #ifndef VMPREP_H
 #define VMPREP_H
 
+#define AP_LUA_SCOPE_UNSET         0
 #define AP_LUA_SCOPE_ONCE          1
 #define AP_LUA_SCOPE_REQUEST       2
 #define AP_LUA_SCOPE_CONN          3
index a248e95d7d8728be9d347cbe50ea17f3c7d2ef77..53dbdab1b6911de5e052bc47878d9f69992832ba 100644 (file)
@@ -115,8 +115,9 @@ static int lua_handler(request_rec *r)
                       spec->file,
                       "handle");
 
-        switch (dcfg->vm_scope) {
+        switch (spec->scope) {
         case AP_LUA_SCOPE_ONCE:
+        case AP_LUA_SCOPE_UNSET:
           apr_pool_create(&pool, r->pool);
           break;
         case AP_LUA_SCOPE_REQUEST:
@@ -190,7 +191,7 @@ static int lua_request_rec_hook_harness(request_rec *r, const char *name, int ap
             spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec));
 
             spec->file = hook_spec->file_name;
-            spec->scope = hook_spec->scope;
+            spec->scope = cfg->vm_scope;
             spec->bytecode = hook_spec->bytecode;
             spec->bytecode_len = hook_spec->bytecode_len;
             spec->pool = r->pool;
@@ -210,6 +211,7 @@ static int lua_request_rec_hook_harness(request_rec *r, const char *name, int ap
 
             switch (spec->scope) {
             case AP_LUA_SCOPE_ONCE:
+            case AP_LUA_SCOPE_UNSET:
              apr_pool_create(&pool, r->pool);
               break;
             case AP_LUA_SCOPE_REQUEST:
@@ -864,7 +866,29 @@ static const char *register_package_cdir(cmd_parms *cmd,
     return register_package_helper(cmd, arg, cfg->package_cpaths);
 }
 
-
+static const char *register_lua_inherit(cmd_parms *cmd, 
+                                      void *_cfg,
+                                      const char *arg)
+{
+    ap_lua_dir_cfg *cfg = (ap_lua_dir_cfg *) _cfg;
+    
+    if (strcasecmp("none", arg) == 0) {
+        cfg->inherit = AP_LUA_INHERIT_NONE;
+    }
+    else if (strcasecmp("parent-first", arg) == 0) {
+        cfg->inherit = AP_LUA_INHERIT_PARENT_FIRST;
+    }
+    else if (strcasecmp("parent-last", arg) == 0) {
+        cfg->inherit = AP_LUA_INHERIT_PARENT_LAST;
+    }
+    else { 
+        return apr_psprintf(cmd->pool,
+                            "LuaInherit type of '%s' not recognized, valid "
+                            "options are 'none', 'parent-first', and 'parent-last'", 
+                            arg);
+    }
+    return NULL;
+}
 static const char *register_lua_scope(cmd_parms *cmd, 
                                       void *_cfg,
                                       const char *scope, 
@@ -900,6 +924,7 @@ static const char *register_lua_scope(cmd_parms *cmd,
 #endif
                             ,scope);
     }
+
     return NULL;
 }
 
@@ -1008,6 +1033,10 @@ command_rec lua_commands[] = {
     AP_INIT_TAKE123("LuaScope", register_lua_scope, NULL, OR_ALL,
                     "One of once, request, conn, server -- default is once"),
 
+    AP_INIT_TAKE1("LuaInherit", register_lua_inherit, NULL, OR_ALL,
+     "Controls how Lua scripts in parent contexts are merged with the current " 
+     " context: none|parent-last|parent-first (default: parent-first) "),
+
     AP_INIT_TAKE2("LuaQuickHandler", register_quick_hook, NULL, OR_ALL,
                   "Provide a hook for the quick handler of request processing"),
     AP_INIT_RAW_ARGS("<LuaQuickHandler", register_quick_block, NULL,
@@ -1030,7 +1059,8 @@ static void *create_dir_config(apr_pool_t *p, char *dir)
     cfg->pool = p;
     cfg->hooks = apr_hash_make(p);
     cfg->dir = apr_pstrdup(p, dir);
-    cfg->vm_scope = AP_LUA_SCOPE_ONCE;
+    cfg->vm_scope = AP_LUA_SCOPE_UNSET;
+
     return cfg;
 }
 
@@ -1067,6 +1097,58 @@ static int lua_post_config(apr_pool_t *pconf, apr_pool_t *plog,
     lua_ssl_is_https = APR_RETRIEVE_OPTIONAL_FN(ssl_is_https);
     return OK;
 }
+static void *overlay_hook_specs(apr_pool_t *p,
+                                        const void *key,
+                                        apr_ssize_t klen,
+                                        const void *overlay_val,
+                                        const void *base_val,
+                                        const void *data)
+{
+    const apr_array_header_t *overlay_info = (const apr_array_header_t*)overlay_val;
+    const apr_array_header_t *base_info = (const apr_array_header_t*)base_val;
+    apr_array_header_t *newspecs  = apr_array_make(p, 2, 
+                                        sizeof(ap_lua_mapped_handler_spec *));
+
+    newspecs = apr_array_append(p, base_info, overlay_info);
+    return newspecs;
+}
+
+static void *merge_dir_config(apr_pool_t *p, void *basev, void *overridesv)
+{
+    ap_lua_dir_cfg *a, *base, *overrides;
+
+    a         = (ap_lua_dir_cfg *)apr_pcalloc(p, sizeof(ap_lua_dir_cfg));
+    base      = (ap_lua_dir_cfg*)basev;
+    overrides = (ap_lua_dir_cfg*)overridesv;
+
+    a->pool = overrides->pool;
+    a->dir = apr_pstrdup(p, overrides->dir);
+
+    a->vm_scope = (overrides->vm_scope == AP_LUA_SCOPE_UNSET) ? base->vm_scope: overrides->vm_scope;
+    a->inherit = (overrides->inherit== AP_LUA_INHERIT_UNSET) ? base->inherit : overrides->inherit;
+
+    if (a->inherit == AP_LUA_INHERIT_UNSET || a->inherit == AP_LUA_INHERIT_PARENT_FIRST) { 
+        a->package_paths = apr_array_append(p, base->package_paths, overrides->package_paths);
+        a->package_cpaths = apr_array_append(p, base->package_cpaths, overrides->package_cpaths);
+        a->mapped_handlers = apr_array_append(p, base->mapped_handlers, overrides->mapped_handlers);
+        a->hooks = apr_hash_merge(p, overrides->hooks, base->hooks, overlay_hook_specs, NULL);
+    }
+    else if (a->inherit == AP_LUA_INHERIT_PARENT_LAST) { 
+        a->package_paths = apr_array_append(p, overrides->package_paths, base->package_paths);
+        a->package_cpaths = apr_array_append(p, overrides->package_cpaths, base->package_cpaths);
+        a->mapped_handlers = apr_array_append(p, overrides->mapped_handlers, base->mapped_handlers);
+        a->hooks = apr_hash_merge(p, base->hooks, overrides->hooks, overlay_hook_specs, NULL);
+    }
+    else { 
+        a->package_paths = overrides->package_paths;
+        a->package_cpaths = overrides->package_cpaths;
+        a->package_cpaths = overrides->package_cpaths;
+        a->mapped_handlers= overrides->mapped_handlers;
+        a->hooks= overrides->hooks;
+    }
+
+    return a;
+}
 
 static void lua_register_hooks(apr_pool_t *p)
 {
@@ -1126,7 +1208,7 @@ static void lua_register_hooks(apr_pool_t *p)
 AP_DECLARE_MODULE(lua) = {
     STANDARD20_MODULE_STUFF,
     create_dir_config,          /* create per-dir    config structures */
-    NULL,                       /* merge  per-dir    config structures */
+    merge_dir_config,           /* merge  per-dir    config structures */
     create_server_config,       /* create per-server config structures */
     NULL,                       /* merge  per-server config structures */
     lua_commands,               /* table of config file commands       */
index 82a0e4ffcbdcbad9d5403cc47476b55caece50c7..16627240eb2341d359d84f813e85a03b578793a3 100644 (file)
 #include "lua_request.h"
 #include "lua_vmprep.h"
 
+typedef enum {
+    AP_LUA_INHERIT_UNSET        = -1,
+    AP_LUA_INHERIT_NONE         =  0,
+    AP_LUA_INHERIT_PARENT_FIRST =  1,
+    AP_LUA_INHERIT_PARENT_LAST  =  2,
+} ap_lua_inherit_t;
 
 /**
  * make a userdata out of a C pointer, and vice versa
@@ -103,6 +109,10 @@ typedef struct
 
     /* the actual directory being configured */
     char *dir;
+  
+    /* Whether Lua scripts in a sub-dir are run before parents */
+    ap_lua_inherit_t inherit;
+
 } ap_lua_dir_cfg;
 
 typedef struct