Bug 39313 - RewriteOption Inherit adds global rules AFTER local rules. You may want the other odrer.
Summary: RewriteOption Inherit adds global rules AFTER local rules. You may want the o...
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_rewrite (show other bugs)
Version: 2.0-HEAD
Hardware: All All
: P2 enhancement with 4 votes (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: FixedInTrunk, PatchAvailable
Depends on:
Blocks:
 
Reported: 2006-04-14 12:44 UTC by J
Modified: 2012-02-26 16:40 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description J 2006-04-14 12:44:50 UTC
When you use RewriteOptions Inherit inside a VirtualHost or Directory which also has 
local rules, the global rules are added at the end of the local rules list. As a 
result, local rules are first applied, and then, global rules are applied after local 
rules. Since rules ordering in important, you may want to apply global rules first, 
and then local rules.

I propose a patch to fullfill this functionality :

- I added a new parameter "Before" to the RewriteOptions directive. You can write the 
following in a VirtualHost or Directory block in httpd.conf :

   RewriteOptions Inherit Before

which means that global rules will be applied before local rules. The default will 
still be after.

This patch modifies modules/mappers/mod_rewrite.h as follows :

# diff -c mod_rewrite.h.old mod_rewrite.h
*** mod_rewrite.h.old   Fri Feb  4 21:21:18 2005
--- mod_rewrite.h       Fri Apr 14 10:52:34 2006
***************
*** 138,143 ****
--- 138,144 ----

  #define OPTION_NONE                 1<<0
  #define OPTION_INHERIT              1<<1
+ #define OPTION_INHERIT_BEFORE       1<<2

  #define CACHEMODE_TS                1<<0
  #define CACHEMODE_TTL               1<<1


And modifies modules/mappers/mod_rewrite.c as follows (based on 2.0.55) :

# diff -c mod_rewrite.c.old mod_rewrite.c
*** mod_rewrite.c.old   Wed May 25 20:05:05 2005
--- mod_rewrite.c       Fri Apr 14 10:52:39 2006
***************
*** 212,223 ****
          a->rewritelogfp    = overrides->rewritelogfp != NULL
                               ? overrides->rewritelogfp
                               : base->rewritelogfp;
!         a->rewritemaps     = apr_array_append(p, overrides->rewritemaps,
!                                               base->rewritemaps);
!         a->rewriteconds    = apr_array_append(p, overrides->rewriteconds,
!                                               base->rewriteconds);
!         a->rewriterules    = apr_array_append(p, overrides->rewriterules,
!                                               base->rewriterules);
      }
      else {
          /*
--- 212,233 ----
          a->rewritelogfp    = overrides->rewritelogfp != NULL
                               ? overrides->rewritelogfp
                               : base->rewritelogfp;
!         if (a->options & OPTION_INHERIT_BEFORE) {
!             a->rewritemaps     = apr_array_append(p, base->rewritemaps,
!                                                   overrides->rewritemaps);
!             a->rewriteconds    = apr_array_append(p, base->rewriteconds,
!                                                   overrides->rewriteconds);
!             a->rewriterules    = apr_array_append(p, base->rewriterules,
!                                                   overrides->rewriterules);
!         }
!         else {
!             a->rewritemaps     = apr_array_append(p, overrides->rewritemaps,
!                                                   base->rewritemaps);
!             a->rewriteconds    = apr_array_append(p, overrides->rewriteconds,
!                                                   base->rewriteconds);
!             a->rewriterules    = apr_array_append(p, overrides->rewriterules,
!                                                   base->rewriterules);
!         }
      }
      else {
          /*
***************
*** 289,298 ****
                            : base->redirect_limit;

      if (a->options & OPTION_INHERIT) {
!         a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
!                                            base->rewriteconds);
!         a->rewriterules = apr_array_append(p, overrides->rewriterules,
!                                            base->rewriterules);
      }
      else {
          a->rewriteconds = overrides->rewriteconds;
--- 299,316 ----
                            : base->redirect_limit;

      if (a->options & OPTION_INHERIT) {
!         if (a->options & OPTION_INHERIT_BEFORE) {
!             a->rewriteconds = apr_array_append(p, base->rewriteconds,
!                                                overrides->rewriteconds);
!             a->rewriterules = apr_array_append(p, base->rewriterules,
!                                                overrides->rewriterules);
!         }
!         else {
!             a->rewriteconds = apr_array_append(p, overrides->rewriteconds,
!                                                base->rewriteconds);
!             a->rewriterules = apr_array_append(p, overrides->rewriterules,
!                                                base->rewriterules);
!         }
      }
      else {
          a->rewriteconds = overrides->rewriteconds;
***************
*** 339,344 ****
--- 357,365 ----
          if (!strcasecmp(w, "inherit")) {
              options |= OPTION_INHERIT;
          }
+         else if (!strcasecmp(w, "before")) {
+             options |= OPTION_INHERIT_BEFORE;
+         }
          else if (!strncasecmp(w, "MaxRedirects=", 13)) {
              limit = atoi(&w[13]);
              if (limit <= 0) {
Comment 1 Anders Kaseorg 2006-10-10 15:33:48 UTC
Yes!! The current behavior is useless.

Suppose I have a website (actually, I *do* have a website) whose URL is changing
from http://old-server.example.com/ to http://new-server.example.com/, but
staying at the same physical filesystem path. At the top level, I tell
mod_rewrite to redirect from old-server to new-server, using [L,R]. But I also
have a subdirectory /2006 with a wiki that invisibly rewrites
/2006/wiki/Main_Page to /2006/w/index.php?title=Main_Page without a redirect.

If I just tell /2006 to use RewriteOptions inherit, with the current behavior we get
  http://old-server.example.com/2006/wiki/Main_Page =>
  http://old-server.example.com/2006/w/index.php?title=Main_Page =>
  http://new-server.example.com/2006/w/index.php?title=Main_Page [L,R]
which exposes the index.php mechanism to the user. What I need is
  http://old-server.example.com/2006/wiki/Main_Page =>
  http://new-server.example.com/2006/wiki/Main_Page [L,R]
so that the user still sees the wiki/Main_Page URL. The only way I can get this
now is by duplicating the redirect across every subdirectory's .htaccess file.
Comment 2 Ruediger Pluem 2006-10-10 15:55:53 UTC
(In reply to comment #1)
> Yes!! The current behavior is useless.
> 
> Suppose I have a website (actually, I *do* have a website) whose URL is changing
> from http://old-server.example.com/ to http://new-server.example.com/, but
> staying at the same physical filesystem path. At the top level, I tell
> mod_rewrite to redirect from old-server to new-server, using [L,R]. But I also
> have a subdirectory /2006 with a wiki that invisibly rewrites
> /2006/wiki/Main_Page to /2006/w/index.php?title=Main_Page without a redirect.
> 
> If I just tell /2006 to use RewriteOptions inherit, with the current behavior
we get

Have you checked what happens, if you do not set RewriteOptions Inherit and just
place the rewrite rule that transforms  http://old-server.example.com/ into
http://new-server.example.com/ at the virtual host level?
Comment 3 Anders Kaseorg 2007-01-21 16:37:48 UTC
Ugh...this was marked NEEDINFO?  You don't need information from me, the patch
is here!

For the server in question, I don't have access to the virtual host
configuration.  If you really want me to test this, I could set up a server
myself.  But either way, that won't change the fact that the current behavior of
RewriteOption Inherit in .htaccess is sometimes (and probably always) incorrect.
Comment 4 Anders Kaseorg 2007-08-31 14:47:28 UTC
Will somebody please mark this bug as NEW again?  The patch is here, and the
information requested is not relevant to anyone.
Comment 5 Vincent Bray 2007-09-01 07:58:05 UTC
@Anders:
 - You didn't answer Ruediger's question
 - NEEDINFO is just that, the bug isn't closed
 - I expect that using the Include directive, or better yet a second vhost with the Redirect directive and 
appropriate wildcard ServerAlias, will be a better solution than extending RewriteOptions anyway.
Comment 6 Anders Kaseorg 2007-09-01 12:13:28 UTC
Okay, fine; I just tried setting up a similar situation on my own server and
putting a RewriteRule at the vhost level.  As I expected, the vhost rewrite
rules are applied before the directory rewrite rules.  So what?  This is not a
general solution.  It only lets me use *two* nested levels of redirection
properly, *if* I have administrative access, and still only one level if I
don't.  I'm still screwed if can't change my vhost config or if I want three
levels instead.

Using Include would also be a kludge; it would require me to go manually
maintain the chain of directory inheritance when I shouldn't need to.

Using two separate vhosts is not a general solution either--say I'm moving a
wiki (with internal redirect rules) from one directory to another instead of one
hostname to another.

Something like Jérôme's patch would solve these problems in a much nicer way. 
Can we have a discussion about the merits of the patch, instead of demanding, of
someone that isn't even the original reporter, an answer to an irrelevant question?
Comment 7 Vincent Bray 2007-09-02 00:32:41 UTC
(In reply to comment #6)
> Can we have a discussion about the merits of the patch, instead of demanding, of
> someone that isn't even the original reporter, an answer to an irrelevant question?

This isn't really a discussion forum, but I still think we need more information from you to figure out the 
issue. Perhaps you'd care to raise this issue on the users@ mailing list, and we can add any resolution from 
there to this bug?
Comment 8 Eric Covener 2010-12-04 17:34:38 UTC
thanks for the patch, committed to trunk in r1042255
Comment 9 Stefan Fritsch 2012-02-26 16:40:05 UTC
fixed in 2.4.1