I have this .htaccess code which hides the .php extension. It works wonders.
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php
I'm now attempting to produce a 404 Not Found error when .php is present in the URL, because I want to force people to use URLs without .php. Here's the code I have now:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^$ /home.php [QSA,L]
RewriteRule ^(.+)\.php - [L,R=404]
I am a complete newbie to .htaccess but the code above is causing a 404 error whenever I go to a .php page, even if .php is not in the URL.
What adjustments must I make in order to make it only cause a 404 Not Found when .php is in the URL?
Rewrite conditions only apply to the immediately following rule, which means:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
only gets applied to
RewriteRule ^$ /home.php [QSA,L]
but not the rule that follows that:
RewriteRule ^(.+)\.php - [L,R=404]
The problem with this last rule is that it checks if the URI has a .php in it, which it will because you're adding the .php extension in your first rule:
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php
So you need to add another condition to prevent that from happening:
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^$ /home.php [QSA,L]
RewriteCond %{THE_REQUEST} \ /+[^\?\ ]+\.php
RewriteRule ^ - [L,R=404]
Related
I'm trying to create a simple htaccess script which redirects users to the appropriate page. So, as an example, if the file/folder doesn't exist, a user navigating to /listing/id will be shown listing.php?id=id instead, or if they navigate to /username they will be shown profile.php?id=username.
The problem is, when accessing /listing/id, I retrieve an internal server error. But not because of the RewriteRule that handles this part - but because of the .php extension removal part of my htaccess script (I figured this out when I commented it out). I have no idea why this isn't working, as I believe I have the correct flags set, and am using the right block of code.
My Code
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
# no php extension
# (/listing/id will work if this is commented out, but the other pages won't without the .php extension)
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
# redirect to www.*
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com [R=301,L]
# only allow rewriting to paths that don't exist
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.+) - [PT,L]
# external profile.php?id=$id to /$id
RewriteCond %{THE_REQUEST} /profile\.php\?id=([\w-]+) [NC]
RewriteRule ^ /%1? [R=301,L]
# /listing/$id
RewriteRule ^listing/([\w-]+)/?$ listing.php?id=$1 [L,QSA,NC]
# /$username
RewriteRule ^([\w-]+)/?$ profile.php?id=$1 [L,QSA]
Example cases
/ (index) works
/search works (the file exists so it redirects to search page not a user named search)
/username works (username.php doesn't exist so it redirects to the profile page)
/listing/test returns Internal Server Error 500 (removing the no PHP extension part of my htacess causes this page to work normally, but now all the others will require .php to be appended)
All help is appreciated, Cheers.
Try your rules in this order:
Options +FollowSymLinks -Indexes -MultiViews
RewriteEngine On
# redirect to www.*
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L,NE]
# external profile.php?id=$id to /$id
RewriteCond %{THE_REQUEST} /profile\.php\?id=([\w-]+)\s [NC]
RewriteRule ^ /%1? [R=301,L]
# only allow rewriting to paths that don't exist
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# /listing/$id
RewriteRule ^listing/([\w-]+)/?$ listing.php?id=$1 [L,QSA,NC]
# no php extension
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
# /$username
RewriteRule ^([\w-]+)/?$ profile.php?id=$1 [L,QSA]
I access to the file.php writing mydomain.com/file. I need to be able to access also writing mydomain.com/FILE.
In .htaccess I use the following rules to remove extension:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ /$1.php [L]
# redirect to .php-less link if requested directly
RewriteCond %{THE_REQUEST} ^[A-Z]+\s.+\.php\sHTTP/.+
RewriteRule ^(.+)\.php $1 [R=301,L]
If this rules should be changed- it's up to you.
Define this RewriteMap in Apache or vhost config:
RewriteMap lc int:tolower
Then inside your .htaccess have an additional rule to lowercase all uppercase URIs:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301,NE]
# redirect to .php-less link if requested directly
RewriteCond %{THE_REQUEST} ^[A-Z]+\s.+\.php\sHTTP [NC]
RewriteRule ^(.+)\.php$ /$1 [R=301,L,NC,NE]
# convert each REQUEST_URI to lowercase
RewriteRule ^(.*?[A-Z]+.*)$ /${lc:$1} [R=301,L,NE]
# internally add .php
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
Use [NC] flag in your rules
Use of the [NC] flag causes the RewriteRule to be matched in a
case-insensitive manner. That is, it doesn't care whether letters
appear as upper-case or lower-case in the matched URI.
https://httpd.apache.org/docs/current/rewrite/flags.html
You need to take care of two aspects: first the case insensitive matching and second the case conversion to lowercase.
Apache's rewriting module provides the NC flag for the first aspect and a somewhat more complex approach to the second one:
RewriteEngine On
# remove trailing slash (/) if no such folder exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /${lc:$1} [NC,L,R=301]
# internally rewrite to a php script if it exists and convert to lower case
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ /${lc:$1}.php [NC,L]
# redirect to .php-less link if requested directly
RewriteRule ^(.+)\.php$ ${lc:$1} [NC,L,R=301]
I have the impression though that your original set of rewriting rules does not really achieve what you attempt to, that is it syntactically invalid even. That is why I changed a few aspects.
Good day!
I want to make proper redirect by htaccess, when there is GET request like this:
example.org/directory/page/
It should give example.org/page.php
My htaccess lets only redirect this kind of request
example.org/directory/page
I use this config
#remove extension
RewriteRule ^([^\.]+)$ $1.php [NC,L]
#remove directory
RewriteRule ^directory/(.*)$ /$1 [L]
Thank you for attention!
Reorder your rules and tweak .php adding rule:
#remove directory
RewriteRule ^directory/(.*)$ /$1 [L]
#remove extension
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f [NC]
RewriteRule ^([^.]+)/?$ $1.php [L]
i need to redirect the URL as
www.domain.com/?page=news --> www.domain.com/news
Here my htaccess file:
Options -Multiviews
RewriteEngine On
RewriteBase /
# Force search engines to use www.domain.com
RewriteCond %{HTTP_HOST} !^www\.domain\.com$
RewriteRule ^(.*) http://www.domain.com/$1 [R=301,L]
# Specify search friendly URLs
RewriteRule ^http://www\.domain\.com/news/$ /http://www.domain.com/?page=news [L]
Please suggest me the exact rule to use in .htaccess file.
Thanks in advance.
Your 2nd rule is not correct as you can't match domain name in RewriteRule pattern. That pattern only matches REQUEST_URI without domain name and query string.
Your 2nd rule should be like this:
RewriteCond %{THE_REQUEST} \s/+\?page=([^&\s]+) [NC]
RewriteRule ^ /%1? [R=301,L,NE]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
# Specify search friendly URLs
RewriteCond %{QUERY_STRING} !(^|&)page=[^&]+
RewriteRule ^([^/]+)/?$ /?page=$1 [L,NC,QSA]
Reference: Apache mod_rewrite Introduction
Sorry, I do not know a thing about this, but I have seen a good tutorial posted by someone I am following on facebook:
http://www.9lessons.info/2013/11/htaccess-file-tutorial-and-tips.html
Hope this helps.
Using mod_rewrite, I want to look for all requested files in an assets directory, and otherwise fallback to index.php for API calls. This is my .htaccess.
RewriteEngine on
RewriteRule ^.+\.[^/]+$ assets/$1 [L]
RewriteRule .* index.php
Asset files are determined by whether the last last url segment has a file extension, which means a dot without following slashes. I already tested the regex at regexpal and it seems to work fine.
Unfortunately, all request result in a 500 Internal Server Error using these rewrite rules. I know that mod_rewrite is set up correctly, since omitting the second line works as expected.
Try these rules:
RewriteEngine on
# rewrite to assets/file if file exists in assets dir
RewriteCond %{DOCUMENT_ROOT}/assets/$1 -f
RewriteRule ^(.+?\.[^/]+)/?$ assets/$1 [L]
# otherwise rewrite to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^assets/ index.php [NC,L]
You need to add a condition to prevent the rewrite engine from looping:
RewriteEngine on
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule ^.+\.[^/]+$ assets/$1 [L]
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule .* index.php
The rewrite engine loops until the URI stops changing, and since .* matches index.php as well, it'll continue to loop through that rule until the internal recursion limit is reached you get a 500 error.
Additionally, you can add conditions that won't reroute existing files or directories:
RewriteEngine on
RewriteCond %{REQUEST_URI} !index\.php
RewriteRule ^.+\.[^/]+$ assets/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php