Modify URL with .htaccess [#Q2.] - apache

I want to modify the URL on my server using .htaccess but I'm facing some issues.
In my previous question I described all the modifications I wanted. I want add some new rules along side the previous rules.
RewriteEngine On
# matches /site/ or /site/index.php or
# /a/site/index.php or /b/site/index.php
# captures a/ or b/ or an empty string in %1
# redirects to /a/ or /b/ or /
RewriteCond %{THE_REQUEST} \s/+([ab]/|)site/(?:index\.php)?[?\s] [NC]
RewriteRule ^ /%1 [L,R=302,NE]
# matches a/ or b/ or empty (landing page)
# rewrites to a/site/index.php or b/site/index.php or site/index.php
RewriteRule ^([ab]/)?$ $1site/index.php [L,NC]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
New Rule #1:
https://example.com/site/index.php (already does)
https://example.com/site/index (does not)
https://example.com/site/ (already does)
should get converted to short url.
https://example.com/
New Rule #2:
https://example.com/a/site/index.php (already does)
https://example.com/a/site/index (does not)
https://example.com/a/site/ (already does)
should get converted to short url.
https://example.com/a/
New Rule #3:
https://example.com/site/any.php (does not)
https://example.com/site/any (does not)
should get converted to short url.
https://example.com/any/
New Rule #4:
https://example.com/any/ (does not)
should load full url without expanding.
https://example.com/site/any.php
Note that: The any.php is dynamic, means it's a ([\w]+).php and I don't know to write .htaccess, any help would be much appreciated.

You may try these rules in your site root .htaccess:
RewriteEngine On
# matches /site/ or /site/index.php or
# /a/site/index.php or /b/site/index.php
# captures a/ or b/ or an empty string in %1
# redirects to /a/ or /b/ or /
RewriteCond %{THE_REQUEST} \s/+([ab]/|)site/(?:index(?:\.php)?)?[?\s] [NC]
RewriteRule ^ /%1 [L,R=302,NE]
# removes site/ from URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{THE_REQUEST} \s/+site/(\S+?)(?:\.php)?/?\s [NC]
RewriteRule ^ /%1/ [L,R=302,NE]
# remove .php from all URLs
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1/ [R=302,NE,L]
# add trailing slash to all URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule [^/]$ %{REQUEST_URI}/ [L,R=302,NE]
# matches a/ or b/ or empty (landing page)
# rewrites to a/site/index.php or b/site/index.php or site/index.php
RewriteRule ^([ab]/)?$ $1site/index.php [L,NC]
# adds .php internally to /any
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ $1.php [L]
# adds .php internally to /site/any
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/site/$1.php -f
RewriteRule ^(.+?)/?$ site/$1.php [L]
There are comments before each rule to clarify what it does.

Related

mod_rewrite rewrites to directory twice?

My index page and links like /page work fine, however my rewrite rule to remove the php from the /page.php seems to be writing the url incorrectly.
Example: http://www.example.com/folder/page.php will redirect to http://www.example.com/folder/folder/page which does not exist
# Remove .php extention
RewriteCond %{THE_REQUEST} \s/(.+?)\.php(?:\s|\?) [NC]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ %1? [R=301]
# Rewrite to PHP file extension (if existing) without changing url
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ $1.php [L]
Your problem is that you put the above code in .htaccess file in this directory http://www.example.com/folder/ so when a page comes without .php it will be handled fine for example if you request http://www.example.com/folder/page it will give you this result http://www.example.com/folder/page , without .php because it will be handled by the second section of your given code
# Rewrite to PHP file extension (if existing) without changing url
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ $1.php [L]
it means when file comes without .php will result the same file , good.
but the problem when you write the same request along with .php so the request will be http://www.example.com/folder/page.php and this according to section one of your code
# Remove .php extention
RewriteCond %{THE_REQUEST} \s/(.+?)\.php(?:\s|\?) [NC]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ %1? [R=301]
will immediately remove the extension .php correctly but the problem is in line of code:
RewriteRule ^ %1? [R=301]
The path in a RewriteRule target is incorrect so you see it twice and you should add
RewriteBase /
line above
RewriteRule ^ %1? [R=301]
or just replace it with :
RewriteRule ^ /%1? [R=301]
and it will work fine . `
You can use these rules:
# remove .php extension
RewriteCond %{THE_REQUEST} ^GET\s(.+?)\.php[\s?/] [NC]
RewriteRule ^ %1? [R=301,L]
# Rewrite to PHP file extension (if existing) without changing url
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L]
Make sure to clear your browser cache before testing this.

How to rewrite URL paths to query strings

Here is my .htaccess file:
# 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 PHP file exists and 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]
Assume there is a file.php in the root directory and v1,v2,... are my query string inputs and the URL below is requested:
http://domain.tld/file/v1/v2...
I simply need to send v1,v2,... as HTTP GET to the file.php using .htaccess and it should work with any other PHP file names and in case of possibility any number of inputs, otherwise handling up to 3 inputs is enough.
I assume that file.php is just a template name, and is not limited to that particular name. You can try:
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^/]+)/(.+)$ $1.php?params=$2 [NC,L]
Now, in the file.php, you will get the passed query arguments as:
$_GET['params'] // which will be of the form v1/v2/v3...

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

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.

.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 rewrite cond and rule cannot firgure out extra slash at end

I've been googling around stack overflow trying to figure this out but have had no joy and keep getting errors no matter what I try.
i am currently using this code to rewrite the address to remove extensions, I got it from a SO post a while ago for simple websites:
RewriteEngine on
# To externally redirect /dir/foo.html to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.html [NC]
RewriteRule ^ %1 [R=301,L]
# To internally forward /dir/foo to /dir/foo.html
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [L]
# To externally redirect /dir/foo.html to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.phtml [NC]
RewriteRule ^ %1 [R=301,L]
# To internally forward /dir/foo to /dir/foo.html
RewriteCond %{REQUEST_FILENAME}.phtml -f
RewriteRule ^ %{REQUEST_URI}.phtml [L]
(i use phtml files as ui files and php for background files, hence the second block)
This works fine for me but now i am on a site where i would like to feed get variables to a page for bookmarking etc and do not want the address to be some thing like www.website.com/page?var=0
i have managed to get my testing site to load www.website.com/page/ using code from another SO post, but only if i enter that url, it will not rewrite if i go to page.html and will not load the attached files css, js (i understand this is because the files have a relative path) Edit: I now understand this is to do with -f || !-f;
code:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^([^/]+)/$ $1.html
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
I am fine with either having or not having a trailing slash, but I do want to add it when there are variables, like page?var=0 to page/var=0 without the images, js and css stopping. of course if it can all be with a slash then all the better.
Thanks
Edit: Also needs to work when the website and .htaccess are in a subfolder, like: mysite.com/example/websitedemonstration/page
This one seems to work fine for me, give it a try:
Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /
# To externally redirect /dir/foo.html to /dir/foo
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s([^.]+)\.(html|phtml) [NC]
RewriteRule ^ %1 [R=301,L]
# To internally forward /dir/foo to /dir/foo.html
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^([^/]*)/?$ $1.html [L]
# To internally forward /dir/foo to /dir/foo.phtml
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.phtml -f
RewriteRule ^([^/]*)/?$ $1.phtml [L]