htaccess calling rewrite rule on everything - apache

This is my htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Static pages
RewriteRule ^print/([0-9]+)$ index.php?action=PublicDisplayPrint&page_id=$1 [L,QSA]
RewriteRule ^email/([0-9]+)$ index.php?action=PublicDisplayEmail&page_id=$1 [L,QSA]
RewriteRule ^login$ index.php?action=PublicDisplayLogin [L,QSA]
RewriteRule ^search$ index.php?action=PublicDisplaySearch [L,QSA]
RewriteRule ^feedback$ index.php?action=PublicDisplayFeedback [L,QSA]
RewriteRule ^sitemap$ index.php?action=PublicDisplaySitemap [L,QSA]
# Dynamic pages
RewriteRule ^(.*)$ index.php?action=PublicDisplayPage&url=$1 [L,QSA]
It seems to be calling the dynamic page rule on any file (logo.gif for example) so it doesn't seem to be running the 2nd and 3rd line. Any ideas?

The condition of a RewriteCond directive does only belong to the first following RewriteRule directive. So in this case the two RewriteCond conditions do only apply to the first RewriteRule and not to the other rules, especially not to the last rule.
So put the RewriteCond directives immediately in front of the the last RewriteRule directive:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?action=PublicDisplayPage&url=$1 [L,QSA]

The RewriteConds are applicable only to the next following RewriteRule so your last 7 rules will be applied to any request.
You could either repeat the condition for each rule, put it on the last rule or put an explicit rule to serve the content as is (this is more flexible because allows you to add more dynamic rules later):
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
#If it's a file or directory, serve as is, without rewriting
RewriteRule ^ - [L]
#Rest of the rules

Related

URL Rewrite - Multiple query

I am trying to see how I can achieve the following rewrite rules.
From
https://localhost/site/?page=place&place=west
https://localhost/site/?page=location&location=cityname
To
https://localhost/site/place/west
https://localhost/site/location/city
I am able to change
https://localhost/site/?page=place to https://localhost/site/place but not with another additional query as mentioned above.
htaccess
RewriteEngine On
#Redirect /site/?page=foobar to /site/foobar
RewriteCond %{THE_REQUEST} /site/(?:index\.php)?\?page=(.+)\sHTTP [NC]
RewriteRule ^ /site/%1? [L,R]
# Internally rewrite new path to the original one
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?:site/)?(.+)/?$ /site/?page=$1 [L,QSA]
The above htaccess works for the following which is what I also need.
https://localhost/site/place
https://localhost/site/about
https://localhost/site/contact
With your shown attempts, please try following htaccess rules file. Make sure to clear your browser cache before testing your URLs. New rules are clubbed to your already existing rules.
RewriteEngine ON
RewriteBase /site/
##New rules from here......
RewriteCond %{THE_REQUEST} \s/site/?\?page=([^&]*)&place=([^&]*)\s [NC]
RewriteRule ^ /site/%1/%2? [R=301,L]
# Internally rewrite new path to the original one
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^site/([^/]*)/(.*)/?$ index.php?page=$1&location=$2 [NC,QSA,L]

Rewrite URLs in .htaccess for replacing Query parameters with forward slash (id?=value)

I have made sure that rewrite engine is enabled and removing .php extensions is working so I know that isn't the issue.
what I'm trying to do is simply remove the ?id=value aspect of the URL, so basically making the URL look like such:
folder/medias/value
Instead of
folder/medias?id=value
My current .htaccess looks like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
RewriteRule ^404/?$ /404.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^ 404.php [L,R]
With your shown samples/attempts, please try following htaccess Rules. Please make sure to clear your browser cache before testing your URLs.
RewriteEngine ON
##Rules for external rewrite.
RewriteCond %{THE_REQUEST} \s/([^.]*)\.php\?id=(\S+)\s [NC]
RewriteRule ^ /%1/%2? [R=301,L]
##Rule for internal rewrite.
RewriteRule ^([^/]*)/([^/]*)/?$ $1?id=$3 [L]
You may try this code inside the /folder/.htaccess (create this file if it doesn't exist):
RewriteEngine On
# External redirect from /folder/media?id=val to /folder/media/val
RewriteCond %{THE_REQUEST} /(\S+?)\.php\?id=([^&\s]+)\s [NC]
RewriteRule ^ /folder/%1/%2? [R=301,L,NE]
# Internal rewrite from /folder/media/val to /folder/media?id=val
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([\w-]+)/([\w-]+)/?$ $1.php?id=$2 [L,QSA]
Trailing ? in first rule is to remove query string from original URL.
%{REQUEST_FILENAME} !-f and %{REQUEST_FILENAME} !-d is to skip existing files and directories from rewrite in 2nd rule.

Apache mod_rewrite infinite loop, cannot fix it

My htaccess:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ([^/.]+)/([^/.]+)(.*) /Application/?path=$1/$2$3 [L,QSA]
RewriteRule ^$ /Application/?path=ACFrontPage/getMainPage [L,QSA]
RewriteRule (.*) /Application/index.php?path=$1 [L,QSA]
This line causes infinite redirect:
RewriteRule (.*) /Application/index.php?path=$1 [L,QSA]
But I need if previous rules didn't match, to redirect everything to index.php file.
How can I do it?
From logs its doing this:
split uri=/Application/?path=Application/ -> uri=/Application/, args=path=Application/&path=Application/&path=Application/&path=Application/&path=Application/&path=Application/&path=Application/&path=Application/&path=Application/&path=Application/
========================
#anubhava
I tried your suggested answer and it works for everything except base domain i.e.:
http://example.com/
RewriteCond is only applicable to very next RewriteRule. Tweak your rules to avoid rewrites for all existing file or directories:
RewriteEngine On
RewriteRule ^$ /Application/?path=ACFrontPage/getMainPage [L]
# skip rewrite for all files/directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([^/.]+)/([^/.]+)(.*)$ /Application/?path=$1/$2$3 [L,QSA]
RewriteRule ^(.+)$ /Application/index.php?path=$1 [L,QSA]

multiple RewriteRules in htaccess file, the first one over writes the second one?

I am trying to run multiple RewriteRules in my htaccess file.
however, the first RewriteRule, overwrites the second RewriteRule for some reason!
this is what i have in my htaccess file:
RewriteEngine On
RewriteBase /
RewriteCond %(REQUEST_FILENAME) !-f
RewriteCond %(REQUEST_FILENAME) !-d
RewriteRule ^([a-zA-Z0-9-/]+).html$ items.php?itemsurl=$1 [L]
RewriteRule ^([a-zA-Z0-9-/]+).html/$ items.php?itemsurl=$1 [L]
RewriteCond %(REQUEST_FILENAME) !-f
RewriteCond %(REQUEST_FILENAME) !-d
RewriteRule ^([a-zA-Z0-9-/]+).html$ blog.php?blogurl=$1 [L]
RewriteRule ^([a-zA-Z0-9-/]+).html/$ blog.php?blogurl=$1 [L]
the first RewriteRule works fine but if I click on the links for blog.php?blogurl= it will simply take me to the items.php!
I could put the RewriteRules for the blog.php at the top of the htaccess file and put the RewriteRules for items.php bellow it and it will make the blog.php rewriterule work for blog.php but it will make the rewriterules for the items.php stop working and everything will point to the blog.php page!
So basically, only the first RewriteRule in the htaccess file works and it will overwrite the second one somehow.
could someone advise on this please?
Replace your code with this one:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9-/]+)\.html\/?$ items.php?itemsurl=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9-/]+)\.html\/?$ blog.php?blogurl=$1 [L]
RewriteCond affects only to the first RewriteRule.
The apache variables should be in these brakes: {}, not these ()
And one more thing - to check . you should escape it so: \.
As discussed in comments, you can use following rules:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^items/([\w-]+)\.html\/?$ items.php?itemsurl=$1 [L,QSA,NC]
RewriteRule ^blog/([\w-]+)\.html\/?$ blog.php?itemsurl=$1 [L,QSA,NC]

Order of rules in .htaccess file

I have an .htaccess file like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^foo.*$ /cgi/foo.cgi [L]
RewriteRule ^.*$ /cgi/fallback.cgi [L]
but when I go to a URL starting with foo in that folder, the browser still gets redirected to the fallback.cgi script. If I remove the second rule, the 'foo' line works OK.
According to my understanding, the first rule should take precedence, and the [L] should prevent any other rules from happening.
You are right, the 1st rule should be applied first and I think it is. The problem might be the 2nd rule is also being applied, so the code should be like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^foo.*$ /cgi/foo.cgi [L,NC]
RewriteCond %{REQUEST_URI} !/cgi/(foo|fallback)\.cgi [NC]
RewriteCond %{REQUEST_URI} !/foo [NC]
RewriteRule ^.*$ /cgi/fallback.cgi [L]
The ^ means beginning of string.
RewriteRule ^foo.*$ /cgi/foo.cgi [L]
So that rules ONLY matches /foo followed by zero or more characters.
To match a file beginning with "foo" use this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (^|/)foo.*$ /cgi/foo.cgi [L]
It matches:
/foo
/foo.php
/food.php
/foolish/dog
It does not match:
/kung-foo.cat
/FOO.php
Update
Remember that some browsers do redirect caching. I was testing this on my own server and had performed a redirect that was cached. Made me confused for a bit when my new rules weren't working.
It is applying 2nd rule because;
In 2nd rule your are matching .* (means everything)
RewriteCond lines are only being applied to 1st rule only
Correct code would be:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
# don't do anything for a file, dir or symlnk
RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d [OR]
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^ - [L]
RewriteRule (^|/)foo /cgi/foo.cgi [L,NC]
RewriteRule ^ /cgi/fallback.cgi [L]