]> granicus.if.org Git - apache/commitdiff
Remove some instances where a RewriteBase must be specified
authorEric Covener <covener@apache.org>
Sat, 29 Nov 2014 23:16:56 +0000 (23:16 +0000)
committerEric Covener <covener@apache.org>
Sat, 29 Nov 2014 23:16:56 +0000 (23:16 +0000)
Previously, any time you used a relative substitution in
per-directory/htaccess context, you needed to specify
a RewriteBase. But in case where the context document root
and context prefix are known via e.g. mod_userdir
or mod_alias, and the substitution is under the context
document root, we can determine the replacement automatically.

This makes htaccess files or config snippets a bit more
portable.

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

CHANGES
docs/manual/mod/mod_rewrite.xml
modules/mappers/mod_rewrite.c

diff --git a/CHANGES b/CHANGES
index a962108758417ddeecb7fddaf0f6ab5c1b71f5e3..650927a39aeeb662364eb98ff0aed2eb7993f513 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -5,6 +5,10 @@ Changes with Apache 2.5.0
      mod_proxy_fcgi: Fix a potential crash with response headers' size above 
      8K. [Teguh <chain rop.io>, Yann Ylavic, Jeff Trawick]
 
+  *) mod_rewrite: Improve relative substitutions in per-directory/htaccess
+     context for directories found by mod_userdir and mod_alias.  These no
+     loner require RewriteBase to be specified. [Eric Covener]
+
   *) mod_ssl: Fix recognition of OCSP stapling responses that are encoded
      improperly or too large.  [Jeff Trawick]
 
index 59904704c86cfba7749449d417bf052a7c2499ea..ff2907927aa11833403869fb1388ec75e5df684e 100644 (file)
@@ -258,8 +258,22 @@ URLs on the fly</description>
       default behavior in 2.4.0 through 2.4.3, and the flag to restore it is
       available Apache HTTP Server 2.4.4 and later.</p>
       </dd>
-      </dl>
 
+      <dt><code>IgnoreContextInfo</code></dt>
+      <dd>
+
+      <p>In versions 2.4.11 and later, when a relative substitution is made
+         in directory (htaccess) context and <directive module="mod_rewrite"
+         >RewriteBase</directive> has not been set, this module uses some
+         extended URL and filesystem context information to change the 
+         relative substitution back into a URL. Modules such as 
+         <module>mod_userdir</module> and <module>mod_alias</module>
+         supply this extended context info.  This option disable the behavior
+         introduced in 2.4.11 and should only be set if all of the conditions 
+         above are present and a substituion has an unexpected result.  </p>
+      </dd>
+
+      </dl>
 </usage>
 
 </directivesynopsis>
@@ -379,6 +393,10 @@ URLs on the fly</description>
                <directive>RewriteRule</directive>, suffixed by the relative 
                substitution is also valid as a URL path on the server 
                (this is rare).</li>
+          <li> In Apache HTTP Server 2.4.11 and later, this directive may be 
+                omitted when the request is mapped via 
+                <directive module="mod_alias">Alias</directive>
+                or <module>mod_userdir</module>.</li>
       </ul>
 
 <p> In the example below, <directive>RewriteBase</directive> is necessary
@@ -388,13 +406,14 @@ URLs on the fly</description>
     directory under the document root.</p>
 <highlight language="config">
 DocumentRoot /var/www/example.com
-Alias /myapp /opt/myapp-1.2.3
+AliasMatch ^/myapp /opt/myapp-1.2.3
 &lt;Directory /opt/myapp-1.2.3&gt;
     RewriteEngine On
     RewriteBase /myapp/
     RewriteRule ^index\.html$  welcome.html 
 &lt;/Directory&gt;
 </highlight>
+
 </usage>
 
 </directivesynopsis>
index cbab2440ad79ea324307530716c96ef569769fa7..64c287c3c3d9d742ed1c58ebe935659229d08d93 100644 (file)
@@ -200,6 +200,7 @@ static const char* really_last_key = "rewrite_really_last";
 #define OPTION_INHERIT_DOWN         1<<6
 #define OPTION_INHERIT_DOWN_BEFORE  1<<7
 #define OPTION_IGNORE_INHERIT       1<<8
+#define OPTION_IGNORE_CONTEXT_INFO  1<<9
 
 #ifndef RAND_MAX
 #define RAND_MAX 32767
@@ -935,7 +936,7 @@ static int prefix_stat(const char *path, apr_pool_t *pool)
 /*
  * substitute the prefix path 'match' in 'input' with 'subst' (RewriteBase)
  */
-static char *subst_prefix_path(request_rec *r, char *input, char *match,
+static char *subst_prefix_path(request_rec *r, char *input, const char *match,
                                const char *subst)
 {
     apr_size_t len = strlen(match);
@@ -2974,6 +2975,9 @@ static const char *cmd_rewriteoptions(cmd_parms *cmd,
         else if (!strcasecmp(w, "mergebase")) {
             options |= OPTION_MERGEBASE;
         }
+        else if (!strcasecmp(w, "ignorecontextinfo")) {
+            options |= OPTION_IGNORE_CONTEXT_INFO;
+        }
         else {
             return apr_pstrcat(cmd->pool, "RewriteOptions: unknown option '",
                                w, "'", NULL);
@@ -5006,6 +5010,7 @@ static int hook_fixup(request_rec *r)
             return n;
         }
         else {
+            const char *tmpfilename = NULL;
             /* it was finally rewritten to a local path */
 
             /* if someone used the PASSTHROUGH flag in per-dir
@@ -5039,6 +5044,8 @@ static int hook_fixup(request_rec *r)
                 return OK;
             }
 
+            tmpfilename = r->filename;
+
             /* if there is a valid base-URL then substitute
              * the per-dir prefix with this base-URL if the
              * current filename still is inside this per-dir
@@ -5076,6 +5083,27 @@ static int hook_fixup(request_rec *r)
                 }
             }
 
+            /* No base URL, or r->filename wasn't still under dconf->directory
+             * or, r->filename wasn't still under the document root. 
+             * If there's a context document root AND a context prefix, and 
+             * the context document root is a prefix of r->filename, replace.
+             * This allows a relative substitution on a path found by mod_userdir 
+             * or mod_alias without baking in a RewriteBase.
+             */
+            if (tmpfilename == r->filename && 
+                !(dconf->options & OPTION_IGNORE_CONTEXT_INFO)) { 
+                if ((ccp = ap_context_document_root(r)) != NULL) { 
+                    const char *prefix = ap_context_prefix(r);
+                    if (prefix != NULL) { 
+                        rewritelog((r, 2, dconf->directory, "trying to replace "
+                                    "context docroot %s with context prefix %s",
+                                    ccp, prefix));
+                        r->filename = subst_prefix_path(r, r->filename,
+                                ccp, prefix);
+                    }
+                }
+            }
+
             /* now initiate the internal redirect */
             rewritelog((r, 1, dconf->directory, "internal redirect with %s "
                         "[INTERNAL REDIRECT]", r->filename));