.htaccess - Redirect all to index.php for root folder or subfolder - apache

I need an .htaccess file that will work whether it is put in the root folder or a subfolder without modification. The script below is the normal one that I've been trying to adapt without success. I tried the solution on htaccess rewrite index.php on root and subfolders and couldn't get it to work.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
Layout
.htaccess
index.php
subfolder1
- .htaccess
- index.php
The route /blah should go to /index.php and /subfolder1/whatever should go to /subfolder1/index.php. Currently, the above script will send /subfolder1/whatever to /index.php.
[Update]
This should also work for any path under subfolder1, like /subfolder1/1/2/3/idunno.

If you are using Apache 2.2.16 and later, you can just stop using mod_rewrite, which although extremely useful and powerful, can get messy as hell.
A new directive in mod_dir was introduced, FallbackResource which does just that, redirecting to the uri of your choice if there is no hit on the file system. It is available in .htaccess files as long as AllowOverride Indexes is specified for the directories in the configuration.
As .htaccess files are evaluated depth-first, you just have to have each .htaccess file describe your fallback resource in the current directory, and the one in the subdirectory subfolder1 will take precedence:
subfolder1/.htaccess:
FallbackResource index.php
.htaccess:
FallbackResource index.php
They're both the same, and work just right.
It seems this directive is not well known yet even though it's been around for a few years, and its goal is precisely to solve that problem in an elegant way.
There is only one limitation with that setup. Calling urls in non-existing sub-directories of the root dir or subfolder1 will yield subrequest recursion and subsequently an error 500, because the fallback resource is local to the given directory.
The best approach is to have absolute uris (beginning with '/') as parameter to FallbackResource, which is why it is true that the requirement in itself is kind of odd, and is probably not playing too well with the inner workings of Apache.

Related

Htaccess RewriteRule for maping urls to be served from one file

I had htaccess which worked for many years with a command like this:
RewriteRule ^products/(.*).php product.php?page=$1&%{QUERY_STRING}
Mapping all items under products folder to be served with product.php file
Today, suddenly all URLs started giving 404. After many hours of digging, I found that the command now works only if there is an actual file (even empty file - it doesn't matter) under the products folder. For example, products/p1.php would work only if p1.php resides under the products folder.
I also run a test and added:
RewriteRule ^tests/(.*).php tests/index.php
and an index.php file under tests folder with hello world. It will only work for files that actually in tests folder. tests/testing.php will show index.php content only if there is a file testing.php in tests folder.
Does anybody have an idea what could have changed at the server configuration to cause this or if there is a way to fix my command to work without an actual file in the location of the URL?
Edited 1st of November 2018:
I found this in the httpd.conf:
<IfModule proxy_fcgi_module>
<FilesMatch \.(phtml|php[0-9]*)$>
SetHandler proxy:unix:/opt/cpanel/ea-php70/root/usr/var/run/php-fpm/.sock|fcgi://mydomain.com
</FilesMatch>
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
RewriteRule (.*) - [H=text/html]
</IfModule>
Could that be the reason?
Another Update:
So this line
RewriteRule ^tests/(.*) tests/index.php
Will work for existing files and also for non-existing directory.
so tests/dir1/ will redirect fine. But test/file.php will only redirect if file.php actually exist.
One more update (sorry I'm debugging it and finding our more stuff):
The redirect will fail only for PHP files! all other files will work correctly.
Final Solution:
These three lines in httpd.conf need to be commented.
RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
RewriteRule (.*) - [H=text/html]
I suspect they are auto-generated by some Cpanel updated and will try to report this to them.
Thank you
yshaool I have the exact same problem with you. My search for a solution lead me also to the httpd.conf.
I commented out the 3 Rewrite lines and restarted Apache. Now it works OK. I'm afraid that this is auto generated file and it will overwritten some time.
At first you need to make life more clearer and stop further rules execution by [L] option:
RewriteRule ^products/(.*).php product.php?page=$1&%{QUERY_STRING} [L]
If doesn't help - there will be rules before yours quoted one executed with a priority.
Something with
RewriteCond %{REQUEST_FILENAME} !-f
condition.
Check your .htaccess if you have those rules.
If you control /etc/apache2/ or /etc/httpd/ folder - check root webserver configs for those.
Otherwise you need to contact your hosting provider.

htaccess for laravel without affecting subdomains

I'm trying to get htaccess working for laravel 5.4, but without it affecting the sub-domains that are created.
My current htaccess
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
What I've tried is setting an htaccess in the sub-domain folders with the follwing:
RewriteEngine On
As I read elsewhere this should stop the top domain htaccess, yet when for example I have a sub-domain like dev.example.com, it will redirect to dev.example.com/dev
Anyway of getting rid of the /dev at the end?
Folder structure:
app
bootstrap
config
database
public
storage
resources
routes
dev --> subdomain
Upfront, I don't see how this /dev is related to the directives, you have shown. None of them do anything to add a /dev anywhere. Maybe it's just the subdirectory applied somehow.
The claim "this should stop the top domain htaccess" is not entirely true. From Apache - How directives are applied
The configuration directives found in a .htaccess file are applied to the directory in which the .htaccess file is found, and to all subdirectories thereof.
However, it is important to also remember that there may have been .htaccess files in directories higher up. Directives are applied in the order that they are found.
Therefore, a .htaccess file in a particular directory may override directives found in .htaccess files found higher up in the directory tree. And those, in turn, may have overridden directives found yet higher up, or in the main server configuration file itself.
So an .htaccess doesn't stop another .htaccess, but a directive overrides a directive. This means, you may have some directive from one .htaccess and another unrelated directive from the top level .htaccess.
In your case, RewriteEngine on just overrides RewriteEngine on from the main .htaccess file.
If you want to prevent any RewriteRule from the top .htaccess, I would rather try
RewriteEngine off

Is it possible to force apache server to read root htaccess before going into subdirectory?

I have a subdirectory in root (let's call it /sub) and .htaccess in root. If I call the following URL: mywebsite.com/sub, I get directly into subdirectory omitting .htaccess in root, so I wanted to ask whether it is possible to force server to read root .htaccess first before going to subdirectory (and make corresponding redirection if needed)?
Thanks in advance
EDIT: I have discovered that my redirection explicitly excluded directories which was unwanted (and seemed to be the root of my problem):
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) http://redirectwebsite.com/$1 [R=301,L]
I removed the second line, but unfortunately I still get into my folder.
So to make it clear:
when I go to http://mywebsite.com/not-a-folder-in-root, I am redirected to the new site correctly
when I fo to http://mywebsite.com/a-folder-in-root, I don't get redirected and go instead to my subfolder's index.php
The latter is the behavior I want to eliminate.
It depends on what you need to do. First .htaccess files are read in the order in which they are found.
How directives are read
The configuration directives found in a .htaccess file are applied to
the directory in which the .htaccess file is found, and to all
subdirectories thereof. However, it is important to also remember that
there may have been .htaccess files in directories higher up.
Directives are applied in the order that they are found. Therefore, a
.htaccess file in a particular directory may override directives found
in .htaccess files found higher up in the directory tree. And those,
in turn, may have overridden directives found yet higher up, or in the
main server configuration file itself.
So the htaccess file will always override the file in the root directory. However you can manipulate the Apache config file and specify directives in say a Location directive. You can specify certain rules and then it will take affect over .htaccess rule. See info below.
As discussed in the documentation on Configuration Sections, .htaccess
files can override the sections for the corresponding
directory, but will be overridden by other types of configuration
sections from the main configuration files. This fact can be used to
enforce certain configurations, even in the presence of a liberal
AllowOverride setting. For example, to prevent script execution while
allowing anything else to be set in .htaccess you can use:
<Directory "/www/htdocs">
AllowOverride All
</Directory>
<Location "/">
Options +IncludesNoExec -ExecCGI
</Location>
Otherwise if you can't do that change because you don't have access, you would have to do all the rules in the root .htaccess file that also pertains to the sub folder which you can do instead of putting an .htaccess in the sub folder.
Edit based on comment
#just use this for all requests
RewriteRule (.*) http://redirectwebsite.com/$1 [R=301,L]
#Or you can do all non-existent folders and that sub folder too
RewriteCond %{REQUEST_URI} ^/sub [NC]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) http://redirectwebsite.com/$1 [R=301,L]

How to fwd urls to existing paths AND one more path with apache's mod_rewrite?

My current .htaccess looks like this:
RewriteEngine On
# RewriteCond %{REQUEST_URI} !^/_project
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^.*$ index.php [QSA,L]
The uncommented lines are pretty straightforward:
The two Conds make sure the Rule isn't applied to existing files (!-f) and folders (!-d).
The Rule sends everyting else to index.php
The uncommented lines I took from somewhere. I believe it's the best way to do what I require: 'pretty urls'.
Basically it works. Existing files (e.g. /css/general.css) are requestable and non-existing paths (e.g. /admin/login) are routed to index.php. Existing and non-existing paths must be able to work 'amongst eachother': /css/all.css is sometimes a buffered existing css file and sometimes (when it doesn't exist) it's handled by PHP. /css/general.css is always a file. /css/club_N.css (N is a number) is always a PHP script.
/_project/ is an existing folder with Basic HTTP Auth protection. For instance /_project/phpinfo.php works as well. In the _project folder I have created a (valid) symlink to the backups folder: /_project/backups/. Somehow the (existing) files in the backups folder can't be reached. For instance /_project/backups/today.bz2 is routed to index.php =( The same happens with either or both commented lines uncommented.
What's wrong with the htaccess config? If I remove the Rewrite stuff entirely, I get a 403 Forbidden. Probably something with the .htaccess in the _project folder (?).
PS. Obviously I can't show you the actual website. People wouldn't like it if you could download their backups =)
.htaccess files are hierarchical in scope, any such files in parent directories apply to their children.
The Basic Auth in /_project/ will apply to subdirectories unless you switch it off in those directories, as will the RewriteRule declaration. Often it is wise to add RewriteEngine off in the .htaccess of the child directory structure to stop the rules applying there, or possibly add a conditional blocking that structure on the original rule set.

Why is my .htaccess file redirecting to full server path instead of relative path?

I've never had a problem with cakePHP before, but something's odd about this server and is causing the redirects in the .htaccess files to behave oddly.
CakePHP uses mod_rewrite in .htaccess files to redirect requests to its own webroot folder. The problem is that the redirects are listing the wrong path and causing a 404 error. My CakePHP application, which is stored in the listings directory, has a .htaccess file as follows:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ app/webroot/ [R=301,L]
RewriteRule (.*) app/webroot/$1 [R=301,L]
</IfModule>
(*note that the R=301 causes an external redirect so we can see what is going on from our end. It should really omit this flag and do the redirect internally, transparent to end-users)
This is supposed to redirect any request from http://hostname.com/~username/listings/ to http://hostname.com/~username/listings/app/webroot/
However, rather than simply adding “app/webroot/” to the end as it is supposed to, it is adding the full server path ( /home/username/public_html/listings/app/webroot/ ) resulting in the final URL http://hostname.com/home/username/public_html/listings/app/webroot/ which is obviously incorrect and triggers a 404 error.
The hosting is on a shared hosting account, so that limits what I can do with the settings. I've never seen this happen before, and I'm thinking it's something wrong from the hosting side of things, but if anyone has some helpful suggestions then I can put them to the hosting company as well.
The solution to your question can be found towards the bottom of this page in the cakephp book:
For many hosting services (GoDaddy, 1and1), your web server is actually being served from a user directory that already uses mod_rewrite. If you are installing CakePHP into a user directory (http://example.com/~username/cakephp/), or any other URL structure that already utilizes mod_rewrite, you'll need to add RewriteBase statements to the .htaccess files CakePHP uses (/.htaccess, /app/.htaccess, /app/webroot/.htaccess).
I've deployed CakePHP from my profile's public_html folder as well. I had to change 3 the same .htaccess files mentioned above. Just add RewriteBase /~username/ to the .htaccess files just after RewriteEngine on!
Try removing .htaccess from main file... It worked for me
It was quite simple (using uolhost shared host):
Edit both .htaccess files:
/webroot/.htaccess
/.htaccess
Add the following line:
RewriteBase /
Here is the whole /webroot/.htaccess file:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]