mod_rewrite overriding second RewriteRule - php

I'm running in to a mod_rewrite issue where the second rule in my .htaccess file is overriding the first. The .htaccess file in question looks like the one below:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /path/appname
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule /api/v1/(.*)$ api/v1/index.php?rquest=$1 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
</IfModule>
The issue that I'm seeing is this:
If I go directly to http://example.com/path/appname/api/v1/valid/endpoint the first RewriteRule triggers correctly and I get the result back from the API.
However, say I visit http://example.com/path/appname/app - a page which has been rewritten according to the second RewriteRule. This page makes AJAX requests to the api/v1 page. Those requests are instead directed through the second RewriteRule and send to my base index.php page.
I'm confused on how this could be, as my understanding is that the [L] flag prevents any further rules from being run once it matches and thus once any request that has 'api/v1' in it should catch that and stop checking for any further matches. What do I need to change in order for this to work correctly?
Thanks!

You should exclude the segment path for the previous rule-set, so it is not processed again. Like this:
# Don't redirect/map when folders or files exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Exclude the previous path
RewriteCond %{REQUEST_URI} !api/v1/? [NC]
# Prevent loops
RewriteCond %{REQUEST_URI} !index\.php [NC]
RewriteRule . index.php [L]
</IfModule>
Replace the last 4 lines in you question with the above lines.

Related

.htaccess to load index.php file for friendly url

I have this url:
www.mywebsite.com/news/best-ever-phones
The part best-ever-phones is variable and could be anything.
index.php file is checking database for article with url best-ever-phones
The problem is that in ./news/.htaccess file I have this code:
RewriteEngine On
RewriteBase /news/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([\w-]+)/?$ index.php?article=$1 [L,QSA]
which is supposed to load index.php file but server returns error 404 Not found when I visit www.mywebsite.com/news/best-ever-phones url.
What is wrong?
Try this
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?article=$1 [L]
I think the problem may be with Rewrite base and your relative path. But this is how i'ld do it.
<IfModule mod_rewrite.c>
Options -Indexes
RewriteEngine On
RewriteRule ^news/([A-Za-z-.]+)/?$ news.php?article=$1 [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ $1.php [NC,L]
</IfModule>
This should fix you up, rename your index to news.php
Perhaps give this a shot:
RewriteEngine On
RewriteBase /news/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([\w-\/]+)\/?$ index.php?article=$1 [L,QSA]
This is presuming that you want the / character to appear in your $article variable, so you can logically separate different parts of the friendly URI if you want to in /news/index.php. Otherwise, single segment friendly URIs like /news-item-1 or whatnot can end with a trailing slash or not.
Really you don't want trailing slashes, as it might result in duplicate content penalties for loading the same page with a different URL (the / counts), so you could either not match \/? outside of the capture group or 301 redirect in index.php to the URL with the trailing slash removed. This way you also have clean query arguments, e.g. /news/something-big?orly=yes instead of /news/something-big/?orly=yes
I am using this site to test the rewrites. Otherwise untested as we don't have your code handy, so no way to tell whether it would work or not in your environment.
This code is used when we click on any url it will hide its extension.
But If you want to goto index.php page then write
echo 'Index Page ';
?>

How to get RewriteRule to redirect both existing and non-existing pages?

Goal: Send all requests, regardless whether the directory/file exists or not, to http://example.com/index.php
What I have tried:
Rewrite Engine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://example.com/index.php [L]
It redirects URL's of non-existing directories/files fine, but when I access an existing subdirectory and file http://example.com/test/test.php it only gives me the contents of the test.php page instead of the main index.php page.
If I understand correctly, the RewriteCond %{REQUEST_FILENAME} !-f and RewriteCond %{REQUEST_FILENAME} !-d tell it to perform the RewriteRule if those criterias are met, which makes sense why it only redirects on non-existing directories and files. But I've tried removing those RewriteCond's, and all it does is put my site into a redirect loop.
I've also tried doing
Rewrite Engine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ http://example.com/index.php [L]
But then it doesn't redirect at all.
What do I have to put to accomplish this?
Your first example would only redirect things that does not exist to your index.php as the conditions you have there:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
Basically means if file or directory does not exist, do this.
Your second example is even worst as it tries to see if a file, directory exist and does not exist which makes no sense.
To redirect anything existent or not to a main handler in this case index.php all you need is the below:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !^/index.php$ [NC]
RewriteRule ^ index.php [L]
The condition makes sure you're not redirecting it to yourself to prevent a loop. If you're running HTTPD version 2.4 and above you can simple use:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
RewriteRule ^ index.php [END]
The flag [END] takes care of not executing any further redirects.

.htaccess rewrite to index.php infinite loop

I am building a clean url system using .htaccess and php.
The main idea is to rewrite everything to index.php and to split the url to segments separated by /.
It works but when I upload it to web server I get an infinite loop error.
My .htaccess file is:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]
If I get things correctly - the problem is that it redirects index.php to itself but it shouldn't because I have index.php file that handles everything and RewriteCond %{REQUEST_FILENAME} !-f which should prevent that rewrite.
Could you please help me with this .htaccess - I want it to rewrite everything to index.php and to be as portable as it can be, so I can use it in:
www.mysite.com
www.myothersite.com
or even
www.mysite.com/new/
I also want to redirect something like www.mysite.com/articles/2 to index.php as well as www.mysite.com/articles/it/2 or even www.mysite.com/articles/it/search/searchterm
Here's code taken from Drupal's .htaccess which uses the "clean urls" approach you are trying to achieve.
# Rewrite URLs of the form 'x' to the form 'index.php?q=x'.
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
In this case, it appends the clean URL as the "q" querystring parameter. So then your script can detect what content to deliver based on $_GET['q'].
And here's another approach, this one from Wordpress.
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
This one specifically looks for requests to index.php and filters them out before doing the redirection.

.htaccess file does not recognize index.php

I have created a .htaccess file that allows for vanity URLs. However, I am no longer able to type www.website.com without typing in the index file. I.e. I have to type in www.website.com/index.php in order to see the homepage. This is what my .htaccess file looks like:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
RewriteRule ^(.*)$ http://www.website.com/profile.php?u=$1 [NC]
Anyone know how to fix this? Thank you all!
The way you defined your rule increased the complexity.
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule .* - [L]
Above rule means if file name is a directory of file process as it is. after that dont process farther.
RewriteRule ^(.*)$ http://www.website.com/profile.php?u=$1 [NC]
This rule means map any request uri to profile.php?u=
Now when you request / that is www.website.com it checks the first rule and it fails to match. Then it check the second rule and maps it to profile.php?u=.
One way to fix it, would be check *if $_GET['u'] is empty or / in profile.php. If it is then load the index.php.
Another way is to find a proper regular expression for your user names once found use it here.
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(USERNAME_REGEX)$ http://www.website.com/profile.php?u=$1 [NC,L]
The best way to handle this is using PHP,
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?uri=$1 [L]
Now index.php will get every uri you pass. Now you can process the URI in index.php.
It may be due to your server set up.
Try DirectoryIndex index.php (see http://davidwalsh.name/directory-index-homepage-htaccess )
Edit (due to me not reading the question properly in the first place)
Have you tried it without the RewriteRule .* - [L] line?

Rewriting a URL - 2 variable without altering current rewrites

I've got most of the rewrites I need working but I can't get the second part working with 2 variables, here is my code:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ entity.php?vanityName=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/([^/]*)$ /entity.php?vanityName=$1&section=$2 [L]
The last bit needs to allow, for example, http://example.com/vanityName/Section however it doesn't pass the section variable.
How can I fix this while retaining the current rewrites?
How can I get it so it works for /vanityName, /vanityName/section but allows me to keep other directories free of rewriting, like /includes/?
You can add an extra rule for every directory you don't want to rewrite:
RewriteRule directoryName/? - [L]
If you write these rules directly after RewriteBase /, no other rules will be checked.

Categories