How to remove php extension and also redirect extensions to no extension form - apache

How can I have this in my htaccess:
/page.php => redirects to /page
/page => shows the page.php
/index => redirects to root
And how to remove trailing slashes from all URLs, specially the root one?
Although, I'm not familiar enough with Apache configs, but I could find these codes:
# To remove .php extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]
# To remove trailing slashes
RewriteRule ^(.*)/$ /$1 [L,R=301]
# To redirect /index to root (not sure if it works correctly)
RewriteCond %{THE_REQUEST} ^.*/index
RewriteRule ^(.*)index.php$ /$1 [R=301,L]
Could you please help me with the scenario and have it in one small code?
Thanks
According to answers, I could solve the problem using the codes below in my .htaccess file:
# To remove .php extension
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\ (.*)\.php [NC]
RewriteRule ^ %1 [R=301,L]
# To remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [R=301,L]
# To check whether the file exists then set it back internally
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L]
# To redirect /index to root
RewriteCond %{THE_REQUEST} ^.*/index
RewriteRule ^(.*)index.php$ /$1 [R=301,L]
Now, I got a new problem and that is when I browse the files with a trailing slash, it redirects me to somewhere else and occurs a 404 (page not found) response, like this:
http://domain.tld/page/ => http://domain.tld/page/home/user/public_html/domain.tld/page
Also, if I move the second part to the end or even remove it completely, the server sends me a 500 (internal server error) response.
Finally with a little research, I could find the solution for previous problem using this advice:
https://stackoverflow.com/a/27264788/5420319
So, I've changed one of the codes from this:
# To remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [R=301,L]
To this:
# To remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /(.*)/$
RewriteRule ^ /%1 [R=301,L]
And I also moved this part to the top regardless of being effective.

According the the answers and my own research, this would be the final answer:
# To remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /(.*)/$
RewriteRule ^ /%1 [R=301,L]
# To remove .php extension
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\ (.*)\.php [NC]
RewriteRule ^ %1 [R=301,L]
# To check whether the file exists then set it back internally
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L]
# To redirect /index to root
RewriteCond %{THE_REQUEST} ^.*/index
RewriteRule ^(.*)index.php$ /$1 [R=301,L]

Redirecting page.php to /page:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\ /page\.php [NC]
RewriteRule ^ /page [R=301,L]
Now, setting back internally to page.php:
RewriteRule ^page$ /page.php [NC,L]
Remove trailing slashes:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [R=301,L]
Now, checking whether a file for /some/page/foo such that /some/page/foo.php exists:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L]

A cleaned up and simplified version of the accepted answer is:
# To remove trailing slash
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [R=301,L]
# To remove .php extension
RewriteRule ^(.*)\.php$ $1 [R=301,L]
# To check whether the file exists then set it back internally
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.php -f
RewriteRule ^.*$ $0.php [L]

Options +FollowSymLinks
RewriteEngine on
AddHandler php5.3-fastcgi php
SetEnv no-gzip dont-vary
RewriteRule ^([a-z]+)$ index.php?page=$1 [QSA,L]
RewriteRule ^([a-z]+)/([a-z0-9]+)$ index.php?page=$1&subpage=$2 [QSA,L]
RewriteRule ^([a-z]+)/([a-z0-9]+)/([a-z0-9]+)$ index.php?page=$1&subpage=$2&module=$3 [QSA,L]
RewriteRule ^([a-z]+)/([a-z0-9]+)/([a-z0-9]+)/([a-z0-9]+)$ index.php?page=$1&subpage=$2&module=$3&submodule=$4 [QSA,L]
You can play with that.

Related

After removing .php and adding / file not loading (object not found)

I was trying to remove the .php extension and add a / as normal websites have. Example http://example.com/category/.
I use .htaccess to remove .php. Here is the code:
RewriteEngine On
RewriteBase /
# hide .php extension snippet
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.php [NC]
RewriteRule ^ %1/ [R,L]
# add a trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/$
RewriteRule . %{REQUEST_URI}/ [L,R=301]
This code does its task. It removes .php and adds / but the PHP page is now not loading.
This is a screenshot (file name test.php):
How to solve this?
It is because you're missing an internal rule to add .php silently to such redirect URIs.
You can add this rule in the end for that habndling:
RewriteEngine On
RewriteBase /
# hide .php extension snippet
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1/ [R=301,NE,L]
# add a trailing slash if needed
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !/$
RewriteRule . %{REQUEST_URI}/ [L,R=301]
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/$ $1.php [L]
After a few research that is actually working in my case is given below.
It removes the .php extension and adds / at the end of the URL.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
Output:
Reference: https://alexcican.com/post/how-to-remove-php-html-htm-extensions-with-htaccess/

Remove slash on redirect without .htaccess [duplicate]

My website runs a script called -> WSS wallpaper script
My Problem -> I have been trying to force remove or add trailing slash to the end of my URL to prevent duplicated content and also to clean up my URLs.
I have tried all sorts and tried everything I could think of and loads from the interwebs but no such luck yet! It might be a quick fix but I have looked at it so much I am probably blind to something dead obvious.
So I present you with all my .htaccess code:
DirectoryIndex index.php
RewriteEngine on
RewriteRule ^download/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) image.php?id=$1&width=$2&height=$3&cropratio=$4&download=1 [L]
RewriteRule ^file/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) image.php?id=$1&width=$2&height=$3&cropratio=$4 [L]
RewriteRule ^preview/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+) wallpaper_preview.php?id=$1&width=$2&height=$3&name=$4 [L]
RewriteRule ^thumbnail/([0-9]+)?/([0-9]+)x([0-9]+)/([^/\.]+)/([^/\.]+)/([^/\.]+)/([^/]+) image.php?wallpaper_id=$1&width=$2&height=$3&cropratio=$4&align=$5&valign=$6&file=$7 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/p([0-9]+) index.php?task=category&id=$1&name=$2&page=$3 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/([0-9a-zA-Z?-]+)/p([0-9]+) index.php?task=category&id=$1&name=$2&sortby=$3&page=$4 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+)/([0-9a-zA-Z?-]+)-([0-9]+) index.php?task=category&id=$1&sortby=$3&page=$4 [L]
RewriteRule ^cat/([0-9]+)?/([^/\.]+) index.php?task=category&id=$1&name=$2 [L]
RewriteRule ^tag/([^/\.]+)/([0-9a-zA-Z?-]+)/([0-9]+) index.php?task=tag&t=$1&sortby=$2&page=$3 [L]
RewriteRule ^tag/([^/\.]+) index.php?task=tag&t=$1 [L]
RewriteRule ^profile/([0-9]+)?/([^/\.]+) index.php?task=profile&id=$1&name=$2 [L]
RewriteRule ^profile/comments/([0-9]+)?/([^/\.]+) index.php?task=users_comments&id=$1&name=$2 [L]
RewriteRule ^page/([0-9]+) index.php?task=view_page&id=$1 [L]
RewriteRule ^register index.php?task=register [L]
RewriteRule ^lost-password index.php?task=lost_pass [L]
RewriteRule ^links index.php?task=links [L]
RewriteRule ^news/item/([0-9]+)/([^/\.]+) index.php?task=news&id=$1 [L]
RewriteRule ^news/page([0-9]+) index.php?task=news&page=$1 [L]
RewriteRule ^members/([^/\.]+)-([^/\.]+)/page([0-9]+)? index.php?task=member_list&sort=$1&order=$2&page=$3 [L]
RewriteRule ^members index.php?task=member_list [L]
RewriteRule ^messages index.php?task=messages [L]
RewriteRule ^submit index.php?task=submit [L]
RewriteRule ^search/([^/\.]+) index.php?task=search&q=$1 [L]
RewriteRule ^search index.php?task=search [L]
RewriteRule ^submit index.php?task=submit [L]
RewriteRule ^r-([0-9]+)?-([0-9]+)? go.php?id=$1&ref=$2 [L]
RewriteRule ^r-([0-9]+)? go.php?id=$1 [L]
RewriteRule ^([^/\.]+)/([0-9]+)/([^/\.]+) index.php?task=view&id=$2&name=$3 [L]
RewriteRule ^news/([^/\.]+) index.php?task=news&name=$1 [L]
RewriteRule ^profile/([^/\.]+) index.php?task=profile&name=$1 [L]
RewriteRule ^news index.php?task=news [L]
RewriteRule ^page/([^/\.]+) index.php?task=view_page&name=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([0-9a-zA-Z'?-]+)/([0-9]+) index.php?task=category&name=$1&sortby=$2&page=$3 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+)/([^/\.]+) index.php?task=view&name=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/\.]+) index.php?task=category&name=$1 [L]
## www reslove ##
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
## www reslove ##
## index reslove ##
Options +FollowSymLinks
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ http://www.epicwallpaper.net/$1 [R=301,L]
## index reslove ##
Right below the RewriteEngine On line, add:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]
to enforce a no-trailing-slash policy.
To enforce a trailing-slash policy:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R] # <- for test, for prod use [L,R=301]
EDIT: commented the R=301 parts because, as explained in a comment:
Be careful with that R=301! Having it there makes many browsers cache the .htaccess-file indefinitely: It somehow becomes irreversible if you can't clear the browser-cache on all machines that opened it. When testing, better go with simple R or R=302
After you've completed your tests, you can use R=301.
To complement Jon Lin's answer, here is a no-trailing-slash technique that also works if the website is located in a directory (like example.org/blog/):
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]
For the sake of completeness, here is an alternative emphasizing that REQUEST_URI starts with a slash (at least in .htaccess files):
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /(.*)/$
RewriteRule ^ /%1 [R=301,L] <-- added slash here too, don't forget it
Just don't use %{REQUEST_URI} (.*)/$. Because in the root directory REQUEST_URI equals /, the leading slash, and it would be misinterpreted as a trailing slash.
If you are interested in more reading:
PR 3145 for Laravel
A discussion on commit 343c31e
(update: this technique is now implemented in Laravel 5.5)
This is what I've used for my latest app.
# redirect the main page to landing
##RedirectMatch 302 ^/$ /landing
# remove php ext from url
# https://stackoverflow.com/questions/4026021/remove-php-extension-with-htaccess
RewriteEngine on
# File exists but has a trailing slash
# https://stackoverflow.com/questions/21417263/htaccess-add-remove-trailing-slash-from-url
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?(.*)/+$ /$1 [R=302,L,QSA]
# ok. It will still find the file but relative assets won't load
# e.g. page: /landing/ -> assets/js/main.js/main
# that's we have the rules above.
RewriteCond %{REQUEST_FILENAME} !\.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^/?(.*?)/?$ $1.php
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
## hide .html extension
# To externally redirect /dir/foo.html to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+).html
RewriteRule ^ %1 [R=301,L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)/\s
RewriteRule ^ %1 [R=301,L]
## To internally redirect /dir/foo to /dir/foo.html
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^([^\.]+)$ $1.html [L]
<Files ~"^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</Files>
This removes html code or php if you supplement it. Allows you to add trailing slash and it come up as well as the url without the trailing slash all bypassing the 404 code. Plus a little added security.

.Htaccess - Remove trailing slash, whilst all pages still go to index.php

I've searched over previously asked questions but none have the same problem as me. I'm wanting to remove the trailing slash, whilst still sending all pages to index.php (or if the file actually exists, use that.)
I'd like a solution that I don't have to fiddle with between server and localhost.
So localhost/pages/to/file/ and http://example.com/pages/to/file/, go to ... /pages/to/file
My current htaccess file:
RewriteEngine on
# removes www.
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1%{REQUEST_URI} [R=301,QSA,NC,L]
# if file exists, ignore the index.php re-write
RewriteCond %{REQUEST_FILENAME} !-f
# send everything to index.php
RewriteRule . index.php
Give the following a try:
RewriteEngine on
# Remove the trailing slash, if not in a directory
# DirectorySlash off can be used instead.
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Remove www. (generic method with HTTPS support)
RewriteCond %{HTTP_HOST} ^www\.
RewriteCond %{HTTPS}s ^on(s)|off
RewriteCond http%1://%{HTTP_HOST} ^(https?://)(www\.)?(.+)$
RewriteRule ^ %1%3%{REQUEST_URI} [R,L]
# Send everything (except existing files) to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
If this works for you, change the R flag to R=301 to make the redirect permanent.
You can add an extra condition to your existing rule to remove www and remove any trailing slash in that rule too.
RewriteEngine on
# removes www. and trailing slash
RewriteCond %{REQUEST_URI} /$ [OR]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*?)/?$ http://%1/$1 [R=301,QSA,NC,L]
# if file exists, ignore the index.php re-write
RewriteCond %{REQUEST_FILENAME} !-f
# send everything to index.php
RewriteRule . index.php
See the documentation for clarification.
Have a separate rule for removal of trailing slash:
RewriteEngine on
# removes www.
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,NE,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} \s/+(.*?)[^/][?\s]
RewriteRule [^/]$ %{REQUEST_URI}/ [L,NE,R=301]
# if file/directory exists, ignore the index.php re-write
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# send everything to index.php
RewriteRule . index.php [L]

.htaccess - force www, trailing slash and remove extension

I've been playing about with my .htaccess file and so far, it's working, but there's a few bugs.
I'm trying to force the WWW prefix (just the root, not on subdomains) while removing the .php extension and adding a trailing slash.
Code
# Force WWW prefix
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Remove .php extension
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]
RewriteRule (.*)/$ $1.php [L]
# Force trailing slash
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]
It successfully force the WWW, even if I remove it, the .php extension is removed, even if I add it, and the the trailing slash is forced, even if I remove it. However, sometimes I get a 404 not found error saying that the requested URL (generally ending with the .php extension) was not found on the server, and often directories do not actually work.
Edit
often directories do not actually work
meaning the server throws a 404 error saying "/directory.php was not found on this server".
Can anyone lend me a hand?
You need to check that you're actually rewriting to a php file before you blindly attach the php extension. So this rule:
RewriteRule (.*)/$ $1.php [L]
Needs some conditions:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/(.+)/$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^(.*)/$ $1.php [L]
You can also avoid redirecting to include www in the hostname for subdomains if you check that there is at least 1 host before the TLD, try adding another condition to your prefix rule:
# Force WWW prefix
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} ^([^.]+)\.([a-z]{2,4})$ [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
EDIT:
Here's what the full file should look like:
RewriteBase /
# Force WWW prefix
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} ^([^.]+)\.([a-z]{2,4})$ [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Remove .php extension
RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php
RewriteRule (.*)\.php$ /$1/ [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/(.+)/$
RewriteCond %{DOCUMENT_ROOT}/%1.php -f
RewriteRule ^(.*)/$ $1.php [L]
# Force trailing slash
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule .*[^/]$ $0/ [L,R=301]

force remove .php extension in .htaccess

i know there are many questions like "How do i remove the .php extension, so that /test/ will be /test.php"
but if the user directly goes to test.php it doesnt replace the extension.
So I want to replace the .php it should be /.
here is the part of the .htacces I'm using:
RewriteEngine on
RewriteRule stuff\.php /other_stuff/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
You need to do the check against the actual request instead of the URI (which gets rewritten by other rules). The %{THE_REQUEST} variable doesn't change in the course of the rewrite engine. Try adding these rules right below the RewriteEngine directive:
RewriteCond %{THE_REQUEST} ^(GET|HEAD)\ /([^/]+)\.php(\?|\ |$)
RewriteRule ^ /%2/ [L,R=301]