Redirect [R=301] ends next iterations in .htaccess?

Viewed 49

I have this simple .htaccess:

RewriteEngine On

RewriteBase /

RewriteRule ^foo3$ foo2
RewriteRule ^foo2$ foo1
RewriteRule ^foo1$ index.php

When i type the url https://localhost/foo3 it follows de rewrite "chain" and ends into index.php. That's ok.

But for this .htaccess:

RewriteEngine On

RewriteBase /

RewriteRule ^foo3$ foo2 [R=301]
RewriteRule ^foo2$ foo1
RewriteRule ^foo1$ index.php

i was expecting it to cascade down to index.php anyway (ignoring the redirect) but the browser makes the 301 redirect to https://localhost/foo2 first (browser reflects that url) and then .htaccess "continues" from there down to index.php.

Does a R=301 act like an [END] directive in this situation somehow?

1 Answers

Does a R=301 act like an [END] directive in this situation somehow?

No END is not in effect but L (last) is. Please understand END behaves differently from L.

Hence Apache sends a 301 to browser and browser does a full redirect, then it sends /foo2 again to web server and then 2nd and 3rd rules are executed.


Update:

Thanks to comment from @MrWhite below, I have run this test while keeping rewrite logs in trace4.

Config to enable rewrite logging:

LogLevel info rewrite:trace4

And here are additional logs that came in my Apache error logs. Please note that my local host name is localhost and my DocumentRoot is /www/root.

Step: Applying rule #1, URI is /foo3:

strip per-dir prefix: /www/root/foo3 -> foo3
applying pattern '^foo3$' to uri 'foo3'
rewrite 'foo3' -> 'foo2'
add per-dir prefix: foo2 -> /www/root/foo2
explicitly forcing redirect with http://localhost/www/root/foo2

Step: Applying rule #2, URI is http://localhost/www/root/foo2 (Note that your RewriteBase / hasn't come into effect yet):

applying pattern '^foo2$' to uri 'http://localhost/www/root/foo2'

Step: Applying rule #3, URI is http://localhost/www/root/foo2:

applying pattern '^foo1$' to uri 'http://localhost/www/root/foo2'

Step: Applying external redirect 301 by stripping DocumentRoot with your RewriteBase value:

trying to replace prefix /www/root/ with /
add subst prefix: foo2 -> foo2
escaping http://localhost/foo2 for redirect
redirect to http://localhost/foo2 [REDIRECT/301]

Step: Applying rule #1, URI is /foo2:

strip per-dir prefix: /www/root/foo2 -> foo2
applying pattern '^foo3$' to uri 'foo2'

Step: Applying rule #2, URI is /foo2:

strip per-dir prefix: /www/root/foo2 -> foo2
applying pattern '^foo2$' to uri 'foo2'
rewrite 'foo2' -> 'foo1'

Step: Applying rule #3, URI is /foo1:

add per-dir prefix: foo1 -> /www/root/foo1
strip per-dir prefix: /www/root/foo1 -> foo1
applying pattern '^foo1$' to uri 'foo1'
rewrite 'foo1' -> 'index.php'

Step: Internal rewrite to /index.php:

add per-dir prefix: index.php -> /www/root/index.php
trying to replace prefix /www/root/ with /
add subst prefix: index.php -> /index.php
internal redirect with /index.php [INTERNAL REDIRECT]

Step: Applying rule #1, URI is /index.php:

strip per-dir prefix: /www/root/index.php -> index.php
applying pattern '^foo3$' to uri 'index.php'

Step: Applying rule #2, URI is /index.php:

strip per-dir prefix: /www/root/index.php -> index.php
applying pattern '^foo2$' to uri 'index.php'

Step: Applying rule #3, URI is /index.php:

strip per-dir prefix: /www/root/index.php -> index.php
applying pattern '^foo1$' to uri 'index.php'

Step: Stop rule processing, URI is /index.php:

pass through /www/root/index.php

I have added detailed trace logging and my step comment above to show how L is a side effect where rule processing is not completely stopped. However the fact mod_rewrite engines attempts to apply remaining rules on a URI that is invalid i.e. http://localhost/www/root/foo2 those rules will not execute and full redirect will be the outcome.

Related