RewriteRule Last flag being ignored - apache

I don't get that if a rewrite rule matches and it has the Last [L] flag that it still executes the rules beneath. I redirect all calls to the public folder but I've added an exception for images, but the exception is being ignored. I thought that with the [L] flag if a rule matches it stops looking for rules beneath.
This is my .htaccess file:
RewriteRule ^image/(.*)/?$ image.php?t=$1 [L]
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
If I remove the bottom 2 rules it does work.
Thanks in advance

It is not ignored.
It is the specific of .htaccess.
It reruns every time URL is changed.
Try this instead.
RewriteEngine on
RewriteCond %{QUERY_STRING} rewritten
RewriteRule .* - [L]
RewriteRule ^image/(.*)/?$ image.php?t=$1&rewritten=1 [L,QSA]
RewriteRule ^$ public/?rewritten=1 [L,QSA]
RewriteRule (.*) public/$1?rewritten=1 [L,QSA]

Related

RewriteRule in same .htaccess on two different files

I want to make a rewrite rule that will work on two different files which are contained in the same folder.
localhost/nameOfUser will be applied to index.php
localhost/nameOfUser?score=12 or localhost/nameOfUser/12 will be applied to post.php
I've managed to make the first one work with
RewriteEngine On
RewriteRule ^(css|fonts)($|/) - [L]
RewriteRule ^(php|avatars)($|/) - [L]
RewriteRule ^(user|post)($|/) - [L]
RewriteRule ^(.*)$ index.php?user=$1 [NC,QSA]
if I add
RewriteRule ^(.*)$ post.php?user=$1 [NC,QSA]
The second starts to work, but the first one doesn't.
Is it even possible to make rewrite for two different files in the same .htaccess file?
Give the following rules a try:
RewriteEngine On
RewriteRule ^(css|fonts|php|avatars|user|post)($|/) - [L]
RewriteRule ^([^/]+)$ index.php?user=$1 [NC,QSA,L]
RewriteRule ^([^/]+)/([^/]+)$ post.php?user=$1&score=$2 [NC,QSA,L]
However, if you want nameOfUser?score=12 to work, you'll need to modify them to:
RewriteEngine On
RewriteRule ^(css|fonts|php|avatars|user|post)($|/) - [L]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^([^/]+)$ /index.php?user=$1 [NC,QSA,L]
RewriteCond %{QUERY_STRING} ^score=(.+)$
RewriteRule ^([^/]+) /post.php?user=$1&score=%1 [NC,L]

why does a matched rewriterule not work?

I have the following .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^a/(.*)$ api.php?params=$1 [L,QSA]
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
</IfModule>
I expect that when I go to /a/test that the server returns /api.php?params=test
Instead, the third rule is matched.
If I comment out the third rule, then the first rule works.
Why is that?
Eventhough you have the L flag, which stops rewriting for the current rewriting iteration, the result (the rewritten URI) will be put back into the rewrite engine, and will continue to do so, until the URI going into the rewrite engine comes out unchanged. So what's happening is the first rule gets applied, then api.php?params=test is put back into the rewrite engine, where the 3rd rule gets applied.
You can either turn off all looping, by passing through the URI if an internal redirect was made, by adding this right underneath RewriteEngine On:
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
Or add a condition to the 3rd rule so that it ignores requests to existing resources:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) app/webroot/$1 [L]
Or add an explicit condition to ignore api.php:
RewriteCond %{REQUEST_URI} !^/api\.php
RewriteRule (.*) app/webroot/$1 [L]

Apache 2.2 mod rewrite loop. How to replace [END]

RewriteEngine on
I have following code:
RewriteCond %{REQUEST_URL} ^$
RewriteRule ^files/(.*)$ getfile.php?file=$1 [L]
RewriteRule ^(.+)/index([0-9]*).html$ index.php?path=$1/&page=$2 [QSA]
RewriteRule ^(.+).html$ index.php?path=$1.html [QSA]
RewriteRule ^(.+)/(.+).htm$ index.php?path=$1/&article=$2.htm [QSA]
RewriteRule ^(.+/)$ index.php?path=$1 [QSA]
RewriteRule ^(.+)$ index.php?path=$1 [QSA]
This code translate urls to parameter path and article according to situation. All good and bad url request is routed to index.php except for files within folder files/.
I have problem with last line of code. It is primarily for all bad urls (all other is processed earlier). With this rule it start to loop over and over again, because all of url match this rule. This rule have to match once or never, but without [END] I cannot contrive. I have older version of apache (2.2) so I cannot use this direction.
Solution for this I have tried is something like this:
RewriteCond %{QUERY_STRING} !^.*path=([^&]*).*$
RewriteCond %{REQUEST_URI} !^/((files|design)/.+)$
RewriteRule ^(.+)$ index.php?path=$1 [QSA]
but cannot succeed.
Try adding a L flag to the end of each rule and add a redirect environment check in the beginning to pass through any previously internally redirected URI:
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule ^ - [L]
RewriteRule ^files/(.*)$ getfile.php?file=$1 [L]
RewriteRule ^(.+)/index([0-9]*).html$ index.php?path=$1/&page=$2 [L,QSA]
RewriteRule ^(.+).html$ index.php?path=$1.html [L,QSA]
RewriteRule ^(.+)/(.+).htm$ index.php?path=$1/&article=$2.htm [L,QSA]
RewriteRule ^(.+/)$ index.php?path=$1 [L,QSA]
RewriteRule ^(.+)$ index.php?path=$1 [L,QSA]

Adding slashes to the end of directories + more (htaccess)

This is beyond my level and I need some help.
In the htaccess make redirect rules for the following...
if example.com/1stleveldirectory doesn't end in a slash add one.
if example.com/1stleveldirectory/ ends in a slash don't add anything.
if example.com/1stleveldirectory/file is like this add .html.
if example.com/1stleveldirectory/file.html is like this don't add anything.
There are no publicly accessible directories past the first level
Thanks!
EDIT: I should have said I already have this code at the top of the file.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.([^.]+.[^.]+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
Options +FollowSymLinks
RewriteRule ^([^/]*)/([^/]*)\.html$ /index.php?cat=$1&name=$2 [L]
RewriteRule ^([^/]*)/$ /index.php?cat=$1 [L]
Try these rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^[^/]+$ %{REQUEST_URI}/ [L,R=301]
RewriteCond $0 !.+\.html$
RewriteRule ^[^/]+/[^/]+$ %{REQUEST_URI}.html [L,R=301]

.htaccess directives to *not* redirect certain URLs

In an application that heavily relies on .htaccess RewriteRules for its PrettyURLs (CakePHP in my case), how do I correctly set up directives to exclude certain directories from this rewriting? That is:
/appRoot/.htaccess
app/
static/
By default every request to /appRoot/* is being rewritten to be picked up by app/webroot/index.php, where it's being analysed and corresponding controller actions are being invoked. This is done by these directives in .htaccess:
RewriteBase /appRoot
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
I now want to exclude a few directories like static/ from this rewriting. I tried with this before the Cake RewriteRules:
RewriteCond $1 ^(static|otherDir).*$ [NC]
RewriteRule (.*) - [L]
It works in so far that requests are no longer rewritten, but now all requests are being skipped, even legitimate Cake requests which should not match ^(static|otherDir).*$.
I tried several variations of these rules but can't get it to work the way I want.
And the correct answer iiiiis...
RewriteRule ^(a|bunch|of|old|directories).* - [NC,L]
# all other requests will be forwarded to Cake
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
I still don't get why the index.php file in the root directory was called initially even with these directives in place. It is now located in
/appRoot/app/views/pages/home.ctp
and handled through Cake as well. With this in place now, I suppose this would have worked as well (slightly altered version of Mike's suggestion, untested):
RewriteCond $1 !^(a|bunch|of|old|directories).*$ [NC]
RewriteRule ^(.*)$ app/webroot/$1 [L]
Could you not apply the condition to the following rules, but with negation, as in (with some variation thereof, I'm not too good at remembering .htaccess rules, so the flags might be wrong):
RewriteCond $1 !^(static|otherDir).*$ [NC]
RewriteRule ^$ app/webroot/ [L]
RewriteCond $1 !^(static|otherDir).*$ [NC]
RewriteRule ^$ app/webroot/$1 [L]
Remove the [L] from the previous rules:
RewriteBase /appRoot
RewriteRule ^$ app/webroot/
RewriteRule (.*) app/webroot/$1
[L] means "Stop the rewriting process here and don't apply any more rewriting rules."