Forum Moderators: phranque

Message Too Old, No Replies

mod_rewrite: last-flag is ignored?

         

BlueScreenTheBlue

9:55 am on Jul 18, 2005 (gmt 0)

10+ Year Member



Hi,
I try using mod_rewrite to decide, if the secure subdomain should be used or not.
The secure subdomain (ssl.example.org) points to a subdirectory with a .htaccess-file, from which the following extract is taken:

# One encrypted page
RewriteRule ^d-arg1-arg2\.html$ index.php?page=arg1&id=arg2 [NC,L]
# All others go without encryption
RewriteCond %{REQUEST_URI}!^(.*)d-arg1-arg2\.html$ [NC]
RewriteRule ^(.*)$ http://www.example.org%{REQUEST_URI} [R=301,L]

When I access, for example,
https://ssl.example.org/d-arg1.html

everything works fine and I'm redirected to the non-ssl connection. But when I access
https://ssl.example.org/d-arg1-arg2.html

both RewriteRules are applied, although the [L]-flag is set. This means, instead of using
https://ssl.example.org/d-arg1-arg2.html

the browser is redirected to
http://www.example.org/index.php?page=arg1&id=arg2

Did I misunderstand the concept of mod_rewrite? Why are both rules used? Is there an other way to avoid this?

I would really appreciate all your help and comments.
Thanks, Blue

jd01

2:12 pm on Jul 18, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Blue

Welcome to WebmasterWorld

The problem appears to be, REQUEST_URI is applied to all requests, and not only the original request, so when the redirect to index.php happens it is not the requested URI and the condition for the second redirect is met.

Also, note the [L] flag says 'stop processing this request' so multiple rewrites are not applied to a single request, but after an initial rewrite has happened, the request is reprocessed as a new request, so the rules are not both being applied to a single request, but rather the first request is rewitten to the index.php? request, which is then 'sent back' and processed as a new request.

I believe the solution is to switch to THE_REQUEST which will only match an original request (EG typed in a browser or by clicking on a link), not an internal request for a page.

RewriteCond %{THE_REQUEST} !d-arg1-arg2\.html$ [NC]
RewriteRule ^(.*)$ http://www.example.org%{THE_REQUEST} [R=301,L]

Removed the ^ (beginning of the line) and the (.*) 'catch-all' and used the implicit 'anything up to', for efficiency, then left the end $ so any original request that ends in d-arg1-arg2.html is redirected.

Hope this helps and makes sense... A little tired.

Justin

jdMorgan

4:37 pm on Jul 18, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



To expand on that a little, .htaccess is processed on a per-directory basis; Each request is passed through httpd.conf and through all .htaccess files in the directory-path between the server root and the directory that the requested URL resolves to.

In addition, after any rewrite, control must be passed back to httpd.conf, and then back down through all .htaccess files in the new path in order to apply any access restrictions or further rewrites. This is required to enforce security, since any other approach would allow anyone with access to a mod_rewrite-enabled subdirectory to bypass password restrictions on other directories, etc.

As jd01 says, the answer is to use %{THE_REQUEST} which will contain only the originally-requested URL-path, unaffected by internal rewrites.

Jim

[edit] Ficksed speling errur [/edit]

[edited by: jdMorgan at 7:43 pm (utc) on July 18, 2005]

BlueScreenTheBlue

4:41 pm on Jul 18, 2005 (gmt 0)

10+ Year Member



Thank you very much, you guys really saved me ;)