.htaccess setting for handling index files, trailing slashes, and file extensions - apache

My website is pretty standard containing a bunch of index files inside folders. ie:
folder1
> index.php
> some-file.php
sub-folder1
> index.php
sub-folder2
> index.php
folder2
> some-file.html
index.html
I recently made some .htaccess changes that were supposed to allow a user to enter a file name without the .html extension but, still be directed to the correct file on the server. It was also supposed to remove trailing slashes. This is the code in my root .htaccess file:
DirectoryIndex index.html
RewriteEngine On
# remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s(.+?)/+[?\s]
#RewriteRule ^(.+?)/$ /$1 [R,L]
RewriteRule ^(.+?)/$ /$1 [R=301,L]
# To internally forward /dir/file to /dir/file.html
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.html -f [NC]
RewriteRule ^(.+?)/?$ /$1.html [L]
This seems to work fine with html files. such as including a link to:
folder2/some-file
However, when I link to folder1/ where the index file is a php file, I'm directed to a list of files and folders inside folder1. I would expect the behavior to pull up index.php not the file list.
If I include the entire path in a link such as: folder1/index.php it works just fine.
This behavior all changed when I added the .htaccess setting above. Before this I didn't even have a .htaccess file on my site. I'm assuming it had to do with the code inside the .htaccess file but, I have no idea how to fix it, as the code it something I found on a help forum.
I also noticed that before I changed my .htaccess setting I could link to my root index.html from any page and the browser would just display www.domain.com. now it always shows www.domain.com/index
Wondering if anyone knows the correct setting I should be using inside my .htaccess file?

You made DirectoryIndex index.html and if there is no index.html in directory ,listing will be done even there is index.php there .
Add it like this :
DirectoryIndex index.html index.php
So , if there is no index.html request to directory will go to index.php .

Related

.htaccess removing file extension is conflicting with folders of the same name

I'm removing file extensions (like .html) from the url with a .htaccess file. The code in the file is working fine, but as soon as there is a folder with the same name as the file without extension, it redirects to the folder instead of redirecting to the file. For example, if I have a demo.html file and a demo folder in the same directory, as soon as I type in the searchbar of the browser www.example.com/demo, it redirects to the folder, instead of the file. If I delete the folder and I type the same thing again, it works perfectly! Any help would be appreciated :)
Here's the code in the .htaccess file:
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R]
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]
This is caused by a conflict with mod_dir. When you request a directory without a trailing slash, mod_dir will "fix" the URL and append a trailing slash with a 301 redirect. After which it will attempt to serve a DirectoryIndex document. This takes priority over your internal rewrite.
To resolve this you need to disable this behaviour with DirectorySlash Off.
For example:
# Ensure that directory listings are disabled
Options -Indexes
# Prevent mod_dir appending a slash to physical directories
DirectorySlash Off
# Redirect to remove the ".html" extension
RewriteCond %{THE_REQUEST} /([^.?]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R=301]
# Rewrite request to append ".html" extension if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule (.*) $1.html [L]
Directory listings (mod_autoindex) need to be disabled when you disable DirectorySlash because if mod_autoindex is enabled then when you request the directory without a slash, a directory listing will be generated, regardless of whether you have a DirectoryIndex document (eg. index.html) in that directory that would ordinarily prevent the directory listing being generated.
Also, I've "fixed" your existing rules that remove and append the .html extension. The first rule that removes the .html extension could have potentially matched an instance of .html that appeared in the query string. And the second rule that appends the .html extension would have resulted in a rewrite-loop (500 error) if requesting /demo/<does-not-exist> - where demo is a directory and a file basename (as in your example).
See my answer to a related question on ServerFault for more information on this potential rewrite-loop:
https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error

htaccess redirect subdirectory (folder) to single page in same subdirectory

I am having another issue with .htaccess where I can't seem to find the right solution for it. What I am trying to accomplish is to redirect from a subdirectory to a specific html document within that same directory when you copy/paste the url displayed below
For example:
http://example.com/staging/test/ to http://example.com/staging/test/page.html
My (almost) working method:
Options -Indexes -MultiViews
RewriteEngine on
RewriteRule ^test/(.*)$ test/page.html [L]
The problem with this code is that it does basically redirect to the correct page.html but if you want to click on any link on page.html it just redirects to page.html again instead of going to a particular link within subdirectory /test/ let's say /test/page-2.html
Important: This redirect should only affect the subdirectory "staging". All other sub-directories including root can not be affected.
Other info:
This code is also in my .htaccess file to remove the .html extension for the directory "staging"
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ $1.html [L]
The directory "staging" is not connected to any CMS and only consists of .html files.
I am on a shared hosting environment (Hostgator/cPanel).
Thank you.
Use below rule, you are using only L flag but I am modifying it for redirect as you mentioned.
Options -Indexes -MultiViews
RewriteEngine on
RewriteRule ^test/$ /staging/test/page.html [R=301,L]
You want to redirect only the directoy, but not the files in it. The pattern in the rule says match the directory test/ followed by anything .*, including any files.
To match the directory alone, the pattern must stop at test, which is accomplished by an end of string anchor
RewriteRule ^test/$ /staging/test/page.html [R,L]
Instead of an absolute path, you can keep the relative path and add a RewriteBase directive
RewriteBase /staging
RewriteRule ^test/$ test/page.html [R,L]
If you want to rewrite only, leave out the R flag.

htaccess - Redirect to subfolder without changing browser URL

I've a domain that contains a subfolder with the web app structure. I added a .htaccess on my root domain to point the public folder on my subfolder web app. It works fine, but when I type www.example.com the browser URL changes to www.example.com/subfolder/public, but I would like that it doesn't change.
This is my .htaccess:
RewriteEngine On
RewriteRule ^.*$ subfolder/public [NC,L]
EDIT
This first .htaccess is used to redirect on subfolder/public, where there is an other .htaccess that makes all the works.
Here the code of the second .htaccess located on www.example.com/subfolder/public/:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
Sorry, just realised what is happening. It has nothing to do with the second .htaccess file in the subdirectory, as mentioned in comments.
RewriteRule ^.*$ subfolder/public [NC,L]
Since public is a physical directory on the file system, you need to include a trailing slash when internally rewriting to that directory. Otherwise, mod_dir is going to try to "fix" the URL by appending a slash - that is where the external redirect is coming from. (mod_dir implicitly triggers an external redirect from subfolder/public to subfolder/public/.)
So, try the following instead in your root .htaccess file:
RewriteRule .* subfolder/public/ [L]
The important thing is the trailing slash. The anchors (^ and $) on the RewriteRule pattern are not required, since you are matching everything. And the NC flag is also not required for the same reason.
As always, make sure the browser cache is clear before testing.
UPDATE#1: The single directive above rewrites everything, including static resources, to the directory subfolder/public/ which then relies on the second .htaccess file in the subdirectory to correctly route the request. In order to allow static resources to be rewritten correctly (represented in the HTML as root-relative URL-paths, of the form "/js/myjs.js") then you will need additional directives in order to rewrite these.
For example, to specifically rewrite all .js and .css files to the real location in /subfolder/public/...
# Rewrite static resources
RewriteRule (.+\.(?:js|css))$ subfolder/public/$1 [L]
# Rewrite everything else to the "public" directory
RewriteRule .* subfolder/public/ [L]
UPDATE#2: To make the above more general, and to rewrite any static resource (images, PDFs, .txt, etc...) we can check for the existence of the file before rewriting, something like:
# Rewrite static resources
RewriteCond %{DOCUMENT_ROOT}/subfolder/public/$1 -f
RewriteRule (.+) subfolder/public/$1 [L]
# Rewrite everything else to the "public" directory
RewriteRule .* subfolder/public/ [L]
This will mean that if any .css does not exist it will be passed through to subfolder/public/.

How to set default home page in apache

I have several folders and pages on my site and it's working well while calling it directly (like mydomain.com/forum or mydomain/tmp/file.html).
But when calling just mydomain.com apache tries to find mydomain/index.html/ folder, while there is index.html file in the root directory and no index.html folder. As the result 404 error. Where to change apache settings? (only .htaccess available, it's virtual hosting)
Most likely there is some rule adding trailing slash. You can use this code in your DOCUMENT_ROOT/.htaccess file to remove a trailing slash:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=302,L,NE]

PHP Files/Directories - .htaccess

Alright so this is what the root of my site looks like:
assets
css
js
img
.htaccess
index.php
page1.php
page2.php
page3.php
style.css
My current .htaccess file works in the sense that it hides .php from the pages which is what i want. So i can access it from http://example.com/page2. But the problem is if i go to http://example.com/page2/ You can see the raw code without any CSS. I want to either redirect users to somewhere else OR have it show it correctly regardless of if there is a "/" or not.
Making it a directory is not an option. It has to be a PHP file in the root.
Current .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
Change your css links to absolute URLs (the start with a /) or add this to the header of your pages:
<base href="/">