You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@httpd.apache.org by Karsten Bräckelmann <gu...@rudersport.de> on 2010/05/06 23:43:28 UTC
[users@httpd] mod_rewrite Redirection ignoring the explicite code
Please Cc me on every reply. I'm subscribed to the allow post list, but
I am not subscribed to receive list posts. Can't stand yet another
mailing list at this point. ;)
Yes, I know mod_rewrite is voodoo. ;) Anyway, here's a (somewhat)
stripped down example of a case I really don't understand what's going
on, and why. I left in some of the juicy bits, which are necessary in
the full code for features. Any explanation or insight greatly
appreciated!
Oh, and if there's a better place to go I didn't find, please don't
hesitate to slap me.
So here's the deal. The full code is supposed to do some redirection of
moved legacy sub-domains (not included in the example) and directories.
Preserving the request URI in the absence of a trailing slash of the
target (which explains the env var), or just to the new domain with a
trailing slash. But that's pretty irrelevant with the stripped down
example. ;)
Use a txt rewrite map for easier reproduction.
$ cat legacy.map
/foo http://example.net/
Extract the leading part of the REQUEST_URI. Look it up in our legacy
map, and if and only if it is defined in the map, go on and rewrite the
URL with the corresponding URI.
RewriteMap legacy txt:/path/to/legacy.map
RewriteCond %{REQUEST_URI} ^(/[^/]+)(.*)
RewriteCond ${legacy:%1} !=""
RewriteRule ^ ${legacy:%1} [E=req:%2]
So at this time, a request for /foo is rewritten with the example URI.
Remember, the mod_rewrite magic is supposed to distinguish between
redirect URIs with or without a trailing slash, so I need more rules.
RewriteRule ^http://.+/$ - [R=301,L] # 302, WTF!?
Using this rule, I do get the desired redirect with the correct
Location, alas a 302 Found temporary redirect. Why? I mean, sure,
using the dash as a substitution results in no substitution being
performed. But that's OK, isn't it? The URL already is the correct, full
target URI at this point, so just force the external redirection and
stop processing.
It does stop here. It does not process subsequent rules. But it ignores
my explicit 301 return code and instead returns 302. Huh!?
RewriteRule ^(http://.+/)$ $1 [R=301,L]
Using this rule, *instead* of the previous one, works -- and returns a
301 Moved Permanently as I asked for. The only difference being a
(rather pointless and less easy to the eye) substitution of the current
URL with the very same URL.
Is this a bug, some missing or unclear documentation, or am I just being
an idiot? :)
Both rules do stop processing, both rules do redirect. Only, the first
variant ignores the explicit return code...
guenther
Oh, right! Apache HTTP 2.2.9, Debian Lenny
--
char *t="\10pse\0r\0dtu\0.@ghno\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t++,*x=t+2*h,c,i,l=*x,s=0; for (i=0;i<l;i++){ i%8? c<<=1:
(c=*++x); c&128 && (s+=h); if (!(h>>=1)||!t[s+h]){ putchar(t[s]);h=m;s=0; }}}
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite code
Posted by Eric Covener <co...@gmail.com>.
On Thu, May 6, 2010 at 6:48 PM, Karsten Bräckelmann
<gu...@rudersport.de> wrote:
> On Fri, 2010-05-07 at 08:28 +1000, Igor Cicimov wrote:
>> Your RewriteRule is wrong it works with the URI part only and not the
>> full URL. Read the mod_rewrite docos and correct your rule.
>
> Argh! An RTFM response. I probably deserve it. But...
>
> I did read the docs. Lots of 'em. Still, I don't see why it behaves as
> it does, otherwise I wouldn't have bothered you in the first place.
The RewriteLog would show you why your rule never matches. Hint: No
other example in the manual starts with anyting other then the "path"
part of the URL, as igor described.
> Also, which of the rules is wrong exactly? Or rather, why is it ok to
> ignore the explicit redirect code? Sorry, I really don't see how I
> should correct the rules. Any more detailed pointers?
That rule isn't generating the redirect. Maybe you're seeing
mod_dirs' DirectorySlash
--
Eric Covener
covener@gmail.com
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite
code
Posted by Karsten Bräckelmann <gu...@rudersport.de>.
Please do Cc me on every reply. I'm subscribed to the allow post list,
but I am not subscribed to receive list posts. Can't stand yet another
mailing list at this point, just for one thread.
> > "A dash indicates that no substitution should be performed (the
> > existing path is passed through untouched). This is used when a flag
> > (see below) needs to be applied without changing the path."
> >
> > Applying an R=301 flag in my case seems to be the intended use-case for
> > the dash...
Eric Covener wrote:
> Not the intended case at all IMO and doesn't seem to work, although
> admittedly I only skimmed.
Yup, it does not work (with the R flag), as I just proved in detail. :)
> It's generally for flags like E= or T= that are not related to the
> substitution.
Well, the docs don't differentiate, and just state the dash to be used
in cases, where no substitution needs to be performed, but flags
applied. It does not state this to work with specific flags only.
According to the docs, the intention is to apply flags. Exactly what I
want to do...
But yeah, I admit I do not grok the full history and intention of
mod_rewrite, I just use it. ;)
guenther
--
char *t="\10pse\0r\0dtu\0.@ghno\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t++,*x=t+2*h,c,i,l=*x,s=0; for (i=0;i<l;i++){ i%8? c<<=1:
(c=*++x); c&128 && (s+=h); if (!(h>>=1)||!t[s+h]){ putchar(t[s]);h=m;s=0; }}}
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite code
Posted by Eric Covener <co...@gmail.com>.
On Fri, May 7, 2010 at 6:48 PM, Karsten Bräckelmann
<gu...@rudersport.de> wrote:
> "A dash indicates that no substitution should be performed (the
> existing path is passed through untouched). This is used when a flag
> (see below) needs to be applied without changing the path."
>
> Applying an R=301 flag in my case seems to be the intended use-case for
> the dash...
>
Not the intended case at all IMO and doesn't seem to work, although
admittedly I only skimmed.
It's generally for flags like E= or T= that are not related to the
substitution.
--
Eric Covener
covener@gmail.com
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite
code
Posted by Karsten Bräckelmann <gu...@rudersport.de>.
On Sat, 2010-05-08 at 00:15 +0200, Karsten Bräckelmann wrote:
> Thanks Igor and Eric for your help. :) However, I'm not convinced
> that's the cause here. Below is a bare minimum example that shows the
> weird behavior I started with...
Sorry for replying to myself. Below is some more fodder generated by the
rewrite logs.
> "Pattern is [...]. On the first RewriteRule it is applied to the
> URL-path of the request; subsequent patterns are applied to the output
> of the last matched RewriteRule."
> So, here is a *minimal* stripped down example that demonstrates the
> weird behavior I'm asking about.
>
> RewriteRule ^/foo http://example.net/
> RewriteRule ^http:// - [R=301,L]
>
> RewriteRule ^/bar http://example.org/
> RewriteRule ^(http://.*)$ $1 [R=301,L]
>
> Now, "GET /foo HTTP/1.1" redirects to the rewritten URI as expected, but
> it ignores my explicit 301 return code and instead defaults to 302.
>
> HTTP/1.1 302 Found
> Location: http://example.net/
The first logs do show, in contrast to the logs below for the second
case, that using the dash prevents rewriting (as expected), but *also*
prevents the explicit redirect code being applied. :(
(3) applying pattern '^/foo' to uri '/foo'
(2) rewrite '/foo' -> 'http://example.net/'
(2) implicitly forcing redirect (rc=302) with http://example.net/
(3) applying pattern '^http://' to uri 'http://example.net/'
(1) escaping http://example.net/ for redirect
(1) redirect to http://example.net/ [REDIRECT/302]
> The second one, "GET /bar HTTP/1.1", does work exactly as I expected, as
> clearly shown in the result. Also, with the sub-sequent RewriteRules, it
> does match the full URI as substituted before (checked this with another
> debugging rule, appending a path).
>
> HTTP/1.1 301 Moved Permanently
> Location: http://example.org/
The logs for the second case with the no-op substitution-with-self do
show two lines more. Marked. The first is the no-op, the second line
appears to show honoring the desired R=301, unlike in the first case,
which never states "EXplicitly" but only "IMplictly" forcing redirect.
(3) applying pattern '^/bar' to uri '/bar'
(2) rewrite '/bar' -> 'http://example.org/'
(2) implicitly forcing redirect (rc=302) with http://example.org/
(3) applying pattern '^(http://.*)$' to uri 'http://example.org/'
(2) rewrite 'http://example.org/' -> 'http://example.org/' #
(2) explicitly forcing redirect with http://example.org/ #
(1) escaping http://example.org/ for redirect
(1) redirect to http://example.org/ [REDIRECT/301]
> Again, do these results show a bug? Is the dash intended and expected to
> always default to 302, no matter the explicit code given? Or do I still
> not see what is wrong with the rules?
So the question is, whether ignoring the R=301 flag is an *intended*
side-effect of using the dash, or if this actually is a bug. After all,
the dash is documented to perform no substitution, in cases where only
flags need to be applied. Yes, I want that! ;)
"A dash indicates that no substitution should be performed (the
existing path is passed through untouched). This is used when a flag
(see below) needs to be applied without changing the path."
Applying an R=301 flag in my case seems to be the intended use-case for
the dash...
guenther
--
char *t="\10pse\0r\0dtu\0.@ghno\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t++,*x=t+2*h,c,i,l=*x,s=0; for (i=0;i<l;i++){ i%8? c<<=1:
(c=*++x); c&128 && (s+=h); if (!(h>>=1)||!t[s+h]){ putchar(t[s]);h=m;s=0; }}}
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite
code
Posted by Karsten Bräckelmann <gu...@rudersport.de>.
Thanks Igor and Eric for your help. :) However, I'm not convinced
that's the cause here. Below is a bare minimum example that shows the
weird behavior I started with...
On Fri, 2010-05-07 at 09:34 +1000, Igor Cicimov wrote:
> Your 301 rule is wrong. As i said it should match the URI parth
> meaning the part after the slash following the domain name and not the
> whole URL. So no http:// in the rewrite rule hope this makes it more
> clear.
Yeah, you're referring to this early part of the RewriteRule docs,
right?
"Pattern is [...]. On the first RewriteRule it is applied to the
URL-path of the request; subsequent patterns are applied to the output
of the last matched RewriteRule."
However, it is different with sub-sequent rules, and only those I use to
match a protocol. (I just want to paranoidly ensure I'm not redirecting
by accident. And the full code also supports more than 3xx only, by
using special mappings.)
So, here is a *minimal* stripped down example that demonstrates the
weird behavior I'm asking about.
RewriteRule ^/foo http://example.net/
RewriteRule ^http:// - [R=301,L]
RewriteRule ^/bar http://example.org/
RewriteRule ^(http://.*)$ $1 [R=301,L]
Now, "GET /foo HTTP/1.1" redirects to the rewritten URI as expected, but
it ignores my explicit 301 return code and instead defaults to 302.
HTTP/1.1 302 Found
Location: http://example.net/
The second one, "GET /bar HTTP/1.1", does work exactly as I expected, as
clearly shown in the result. Also, with the sub-sequent RewriteRules, it
does match the full URI as substituted before (checked this with another
debugging rule, appending a path).
HTTP/1.1 301 Moved Permanently
Location: http://example.org/
The only difference I see -- as mentioned in my initial post -- is the
explicit substitution as opposed to "just keep it" by using the dash.
And since in this one case I do not want to add or change anything, but
keep it and just force the redirect if it matches (trailing slash in
working code), the RE backreference and substitution with itself,
verbatim and in full, just doesn't seem necessary.
However, if I do *not* do the useless substitute-with-self, I end up
with my 301 redirection code being ignored...
Again, do these results show a bug? Is the dash intended and expected to
always default to 302, no matter the explicit code given? Or do I still
not see what is wrong with the rules?
guenther
--
char *t="\10pse\0r\0dtu\0.@ghno\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t++,*x=t+2*h,c,i,l=*x,s=0; for (i=0;i<l;i++){ i%8? c<<=1:
(c=*++x); c&128 && (s+=h); if (!(h>>=1)||!t[s+h]){ putchar(t[s]);h=m;s=0; }}}
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite code
Posted by Igor Cicimov <ic...@gmail.com>.
Your 301 rule is wrong. As i said it should match the URI parth meaning the
part after the slash following the domain name and not the whole URL. So no
http:// in the rewrite rule hope this makes it more clear.
Sent from my phone
On May 7, 2010 8:48 AM, "Karsten Bräckelmann" <gu...@rudersport.de>
wrote:
On Fri, 2010-05-07 at 08:28 +1000, Igor Cicimov wrote: > Your RewriteRule is
wrong it works with the...
Argh! An RTFM response. I probably deserve it. But...
I did read the docs. Lots of 'em. Still, I don't see why it behaves as
it does, otherwise I wouldn't have bothered you in the first place.
Also, which of the rules is wrong exactly? Or rather, why is it ok to
ignore the explicit redirect code? Sorry, I really don't see how I
should correct the rules. Any more detailed pointers?
> Sent from my phone
Yeah, it's not urgent, I'm fine waiting until you're back to a decently
sized keyboard... ;)
guenther
> > On May 7, 2010 7:44 AM, "Karsten Bräckelmann" <gu...@rudersport.de>
wrote: > > > > Please ...
> > Extract the leading part of the REQUEST_URI. Look it up in our legacy >
> map, and if and only i...
--
char *t="\10pse\0r\0dtu\0.@ghno\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t+...
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite
code
Posted by Karsten Bräckelmann <gu...@rudersport.de>.
On Fri, 2010-05-07 at 08:28 +1000, Igor Cicimov wrote:
> Your RewriteRule is wrong it works with the URI part only and not the
> full URL. Read the mod_rewrite docos and correct your rule.
Argh! An RTFM response. I probably deserve it. But...
I did read the docs. Lots of 'em. Still, I don't see why it behaves as
it does, otherwise I wouldn't have bothered you in the first place.
Also, which of the rules is wrong exactly? Or rather, why is it ok to
ignore the explicit redirect code? Sorry, I really don't see how I
should correct the rules. Any more detailed pointers?
> Sent from my phone
Yeah, it's not urgent, I'm fine waiting until you're back to a decently
sized keyboard... ;)
guenther
> > On May 7, 2010 7:44 AM, "Karsten Bräckelmann" <gu...@rudersport.de> wrote:
> >
> > Please Cc me on every reply. I'm subscribed to the allow post list, but
> > I am not subscribed to receive list posts. Can't stand yet another
> > mailing list at this point. ;)
> > Extract the leading part of the REQUEST_URI. Look it up in our legacy
> > map, and if and only if it is defined in the map, go on and rewrite the
> > URL with the corresponding URI.
> >
> > RewriteMap legacy txt:/path/to/legacy.map
> >
> > RewriteCond %{REQUEST_URI} ^(/[^/]+)(.*)
> > RewriteCond ${legacy:%1} !=""
> > RewriteRule ^ ${legacy:%1} [E=req:%2]
> >
> > So at this time, a request for /foo is rewritten with the example URI.
> >
> > Remember, the mod_rewrite magic is supposed to distinguish between
> > redirect URIs with or without a trailing slash, so I need more rules.
> >
> > RewriteRule ^http://.+/$ - [R=301,L] # 302, WTF!?
> >
> > Using this rule, I do get the desired redirect with the correct
> > Location, alas a 302 Found temporary redirect. Why? I mean, sure,
> > using the dash as a substitution results in no substitution being
> > performed. But that's OK, isn't it? The URL already is the correct, full
> > target URI at this point, so just force the external redirection and
> > stop processing.
> >
> > It does stop here. It does not process subsequent rules. But it ignores
> > my explicit 301 return code and instead returns 302. Huh!?
> >
> > RewriteRule ^(http://.+/)$ $1 [R=301,L]
> >
> > Using this rule, *instead* of the previous one, works -- and returns a
> > 301 Moved Permanently as I asked for. The only difference being a
> > (rather pointless and less easy to the eye) substitution of the current
> > URL with the very same URL.
> >
> >
> > Is this a bug, some missing or unclear documentation, or am I just being
> > an idiot? :)
> >
> > Both rules do stop processing, both rules do redirect. Only, the first
> > variant ignores the explicit return code...
--
char *t="\10pse\0r\0dtu\0.@ghno\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t++,*x=t+2*h,c,i,l=*x,s=0; for (i=0;i<l;i++){ i%8? c<<=1:
(c=*++x); c&128 && (s+=h); if (!(h>>=1)||!t[s+h]){ putchar(t[s]);h=m;s=0; }}}
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org
Re: [users@httpd] mod_rewrite Redirection ignoring the explicite code
Posted by Igor Cicimov <ic...@gmail.com>.
Your RewriteRule is wrong it works with the URI part only and not the full
URL. Read the mod_rewrite docos and correct your rule.
Sent from my phone
On May 7, 2010 7:44 AM, "Karsten Bräckelmann" <gu...@rudersport.de>
wrote:
Please Cc me on every reply. I'm subscribed to the allow post list, but
I am not subscribed to receive list posts. Can't stand yet another
mailing list at this point. ;)
Yes, I know mod_rewrite is voodoo. ;) Anyway, here's a (somewhat)
stripped down example of a case I really don't understand what's going
on, and why. I left in some of the juicy bits, which are necessary in
the full code for features. Any explanation or insight greatly
appreciated!
Oh, and if there's a better place to go I didn't find, please don't
hesitate to slap me.
So here's the deal. The full code is supposed to do some redirection of
moved legacy sub-domains (not included in the example) and directories.
Preserving the request URI in the absence of a trailing slash of the
target (which explains the env var), or just to the new domain with a
trailing slash. But that's pretty irrelevant with the stripped down
example. ;)
Use a txt rewrite map for easier reproduction.
$ cat legacy.map
/foo http://example.net/
Extract the leading part of the REQUEST_URI. Look it up in our legacy
map, and if and only if it is defined in the map, go on and rewrite the
URL with the corresponding URI.
RewriteMap legacy txt:/path/to/legacy.map
RewriteCond %{REQUEST_URI} ^(/[^/]+)(.*)
RewriteCond ${legacy:%1} !=""
RewriteRule ^ ${legacy:%1} [E=req:%2]
So at this time, a request for /foo is rewritten with the example URI.
Remember, the mod_rewrite magic is supposed to distinguish between
redirect URIs with or without a trailing slash, so I need more rules.
RewriteRule ^http://.+/$ - [R=301,L] # 302, WTF!?
Using this rule, I do get the desired redirect with the correct
Location, alas a 302 Found temporary redirect. Why? I mean, sure,
using the dash as a substitution results in no substitution being
performed. But that's OK, isn't it? The URL already is the correct, full
target URI at this point, so just force the external redirection and
stop processing.
It does stop here. It does not process subsequent rules. But it ignores
my explicit 301 return code and instead returns 302. Huh!?
RewriteRule ^(http://.+/)$ $1 [R=301,L]
Using this rule, *instead* of the previous one, works -- and returns a
301 Moved Permanently as I asked for. The only difference being a
(rather pointless and less easy to the eye) substitution of the current
URL with the very same URL.
Is this a bug, some missing or unclear documentation, or am I just being
an idiot? :)
Both rules do stop processing, both rules do redirect. Only, the first
variant ignores the explicit return code...
guenther
Oh, right! Apache HTTP 2.2.9, Debian Lenny
--
char *t="\10pse\0r\0dtu\0.@ghno
\x4e\xc8\x79\xf4\xab\x51\x8a\x10\xf4\xf4\xc4";
main(){ char h,m=h=*t++,*x=t+2*h,c,i,l=*x,s=0; for (i=0;i<l;i++){ i%8?
c<<=1:
(c=*++x); c&128 && (s+=h); if (!(h>>=1)||!t[s+h]){ putchar(t[s]);h=m;s=0;
}}}
---------------------------------------------------------------------
The official User-To-User support forum of the Apache HTTP Server Project.
See <URL:http://httpd.apache.org/userslist.html> for more info.
To unsubscribe, e-mail: users-unsubscribe@httpd.apache.org
" from the digest: users-digest-unsubscribe@httpd.apache.org
For additional commands, e-mail: users-help@httpd.apache.org