How to map all requests except existing files to a handler - apache

Need some help with htaccess rewrite rule I'm stuck with.
I have a handler index.html which is used to handle all requests except existing files.
I'm using this rule:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [L]
But I have some filenames similar to the requests to be handled. If there comes a request to /main it has to be handled by index.html but because of existing file with extension - main.asdfjaskldfjaskdfjasfd.js - I'm getting 404 error insted of handling.
This problem is super easily solved in nginx with one liner: "try_files $uri $uri/ /index.html;" but I don't have an opportunity to use nginx on production - only Apache.
So I need some help with those rules.
Tried (besides tens of other) this:
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
RewriteRule ^ /index.html
Full htaccess:
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_URI} ^/(demo-auth|api|oauth|password|login|logout|register|images)
RewriteRule ^ laravel.php [L]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule ^ /index.html
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Thanks in advance.

Add that, at the top of your htaccess, to disable MultiViews:
Options -MultiViews
The Apache docs on mod_negotiation, describes what the Multiviews Option does, when enabled:
If the
server receives a request for /some/dir/foo and /some/dir/foo does not
exist, then the server reads the directory looking for all files named
foo.*, and effectively fakes up a type map which names all those
files, assigning them the same media types and content-encodings it
would have if the client had asked for one of them by name. It then
chooses the best match to the client's requirements, and returns that
document.

Related

.htaccess redirect based on folder

I need help with .htaccess Rewrite rules.
I have a API which can be accessed over http://api.my.domain/products/all which is working fine and is returning result.
I would like to redirect users coming to http://api.my.domain/admin to admin folder.But it is not working with current rules.
I have added this to .htaccess but it is not working correctly for admin folder.
RewriteEngine On
RewriteCond %{Request_Filename} !-F
RewriteCond %{Request_Filename} !-d
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^admin admin/index.php [QSD,L]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ public/index.php [QSD,L]
This is the result I get when I enter http://api.my.domain/admin and is breaking all my php redirects:
http://api.drezga.hr/admin/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/index.php/admin/admin/checklogin.php
Can someone, please, tell me what I'm doing wrong? I have spent hours and I can't see it.
Aside: If /admin is a physical directory then you should be requesting /admin/ (with a trailing slash) to begin with, otherwise Apache/mod_dir will issue a 301 redirect to append the trailing slash.
RewriteCond %{Request_Filename} !-F
RewriteCond %{Request_Filename} !-d
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^admin admin/index.php [QSD,L]
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ public/index.php [QSD,L]
The first two conditions (RewriteCond directives) are being applied incorrectly to the first rule only. They need to apply to the last rule (the rewrite to public/index.php) then the rewrite to admin/index.php is not necessary (this should be handled by the DirectoryIndex).
There's no need for the QSD flag since you are checking that the query string is already empty - there is no query string to discard!
You should probably be using the -f operator on the condition, not -F (which uses subrequests and is consequently less efficient).
Try the following instead:
DirectoryIndex index.php
RewriteEngine On
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Optimisation (prevent additional filesystem check)
RewriteRule ^public/index\.php$ - [L]
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . public/index.php [L]
RewriteRule ^$ public/index.php [L]
The RewriteCond %{REQUEST_FILENAME} !-d directive prevents requests for /admin/ being passed to public/index.php.
The additional RewriteRule at the end is to rewrite requests for the root directory, which would otherwise be omitted because of the condition mentioned above. This could be avoided by extending the DirectoryIndex directive instead, although this could change the behaviour if you have other directories that need to be accessible (or should not be routed to public/index.php). For example:
DirectoryIndex index.php /public/index.php

.htaccess remove .html extension and add trailing slash and disallow .html files

I have a static website with html files and I want to call them without the .html ending and a trailing slash.
For example:
www.test.com/test.html
Should be available under
www.test.com/test/
I managed this with the following .htaccess
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^([^\.]+)/$ $1.html
But both versions of the url lead to the same page. How can I redirect (without .html) or throw a 404 for the .html version?
www.test.com/test.html
This is the working solution with a trailing slash. Thank you #arkascha!
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.html$ /$1/ [R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^([^\.]+)/$ $1.html [END]
Well, add another rule that explicitly redirects requests to URLs with "file name extensions"...
Options -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.html$ /$1/ [R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^/?([^\.]+)/?$ /$1.html [END]
If the above rule set results in a http status 500 ("server internal error"), then chances are that you operate a very old version of the apache http server. In that case you have to use the L flag instead of the END flag and add an additional condition to the first block:
RewriteEngine On
RewriteCond %{REQUEST_URI} .html$
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^/?(.+)\.html$ /$1/ [R=301]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^/?([^\.]+)/?$ /$1.html [L]
And a general hint: you should always prefer to place such rules inside the http servers (virtual) host configuration instead of using dynamic configuration files (.htaccess style files). Those files are notoriously error prone, hard to debug and they really slow down the server. They are only supported as a last option for situations where you do not have control over the host configuration (read: really cheap hosting service providers) or if you have an application that relies on writing its own rewrite rules (which is an obvious security nightmare).

Hiding file extension and redirecting to https

First off, I know there are many questions similar to this one. I've read everything I can find, but the solutions I see elsewhere don't seem to work for me. I'm really hoping someone can give me some insight here.
I am trying to use Apache's .htaccess directives to force specific pages on my server to use ssl. In addition to those directives, I'm also using some rewrites to mask .php and .html extensions.
I created a page, https-test.html. I want that page specifically to always get redirected so it uses https and so that .html gets stripped off, like https://www.example.com/https-test
However, I seem to always end up with a loop. Reading the Apache docs for 6 hours got me closer, but I'm still missing something.
Below is my annotated htaccess file.
RewriteEngine on
# If port is insecure...
RewriteCond %{SERVER_PORT} ^80$
# And requested URI is /https-test...
RewriteCond %{REQUEST_URI} ^(.*/)https-test$ [NC]
# Then point the server to the secure url:
RewriteRule . "https://www.example.com/https-test" [L,R]
# The next few lines try matching extensionless requests to .php files
# If the requested file is not a directory...
RewriteCond %{REQUEST_FILENAME} !-d
# And we CAN find a .php file matching that name...
RewriteCond %{REQUEST_FILENAME}\.php -f
# Then point us to that .php file and append the query string.
RewriteRule ^(.+)$ $1.php [L,QSA]
# These next few lines were added by the previous project owner
# They're supposed to redirect requests like /foo.html to /foo,
# But I suspect these might be the culprit
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)/$ /$1 [R=301,NE,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ /$1.html [NE,L]
# Next few lines are legacy SEO stuff, some pages were linked to as
# php but now are html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} .php$
RewriteRule ^(.*).php$ /$1.html [L,NE]
So that's the code I have in my htaccess. And if I go to http://www.example.com/https-test in Chrome, I get www.mysite.com redirected you too many times.
You should probably just rewrite the code a bit. You are trying to match both extensionless files to php and html and doesn't look like you're accounting for each of the conditions. You should add a condition to make sure they are not tryiing to do the same things.
Backup your code, replace your code with this and give it a try. Clear all your cache before trying.
RewriteEngine on
# If port is insecure... redirect for a specific page
RewriteCond %{HTTPS} !^on [OR]
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^http-test/?$ https://www.example.com%{REQUEST_URI} [R=301,L]
# Next few lines are legacy SEO stuff, some pages were linked to as
# php but now are html
RewriteCond %{THE_REQUEST} ^GET\ /(.+)\.php
RewriteRule ^ /%1? [R=301,L]
# The next few lines try matching extensionless requests to .php files
# If the requested file is not a directory and php file exists
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.+)$ $1.php [L,QSA]
#remove trailing slash and is not a php file
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php !-f
RewriteRule ^([^\.]+)/$ /$1 [R=301,NE,L]
#finally redirect extensionless URI to html
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ /$1.html [NE,L]
Note I haven't tested this fully.

mod_rewrite redirect url if no file found to main page

I want to be able to Access my scripts without the .php, .html etc., so I already wrote
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.php -f
RewriteRule ^(.*)$ $1.php
##same for other extensions
in my .htaccess file (note: this file lies not in the root-path), but I also want to Redirect every incorrect request to my main page, so that www.mysite.com/dir/incorrect will be rewritten to www.mysite.com/dir/.
But my first try (RewriteRule ^ / [R] after RewriteCond) redirected me to www.mysite.com/, my experiments with RewriteBase (RewriteBase . and RewriteBase /) didnt work and I also noticed that many similar scriptredirect to www.mysite.com/dir/index.php (www.mysite.com/dir/index in my case), but I really want to Redirect to www.mysite.com/dir/. Is there any way to achieve this?
Have it this way:
RewriteEngine on
# see if .php is found
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}\.php -f
RewriteRule ^(.*)$ $1.php [L]
# determine DIR_BASE dynamically
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=DIR_BASE:%1]
# if not found redirect to %{ENV:DIR_BASE}
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ %{ENV:DIR_BASE} [L,R]

htaccess remove index.php from url

I have a problem whereby google has indexed some pages with the wrong url.
The url they are indexing is:
http://www.example.com/index.php/section1/section2
I need it to redirect to:
http://www.example.com/section1/section2
.htaccess isn't my forte, so any help would be much appreciated.
The original answer is actually correct, but lacks explanation. I would like to add some explanations and modifications.
I suggest reading this short introduction https://httpd.apache.org/docs/2.4/rewrite/intro.html (15mins) and reference these 2 pages while reading.
https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html
https://httpd.apache.org/docs/2.4/rewrite/flags.html
This is the basic rule to hide index.php from the URL. Put this in your root .htaccess file.
mod_rewrite must be enabled with PHP and this will work for the PHP version higher than 5.2.6.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php/$1 [L]
Think %{REQUEST_FILENAME} as the the path after host.
E.g. https://www.example.com/index.html, %{REQUEST_FILENAME} is /index.html
So the last 3 lines means, if it's not a regular file !-f and not a directory !-d, then do the RewriteRule.
As for RewriteRule formats:
So RewriteRule (.*) /index.php/$1 [L] means, if the 2 RewriteCond are satisfied, it (.*) would match everything after the hostname. . matches any single character , .* matches any characters and (.*) makes this a variables can be references with $1, then replace with /index.php/$1. The final effect is to add a preceding index.php to the whole URL path.
E.g. for https://www.example.com/hello, it would produce, https://www.example.com/index.php/hello internally.
Another key problem is that this indeed solve the question. Internally, (I guess) it always need https://www.example.com/index.php/hello, but with rewriting, you could visit the site without index.php, apache adds that for you internally.
Btw, making an extra .htaccess file is not very recommended by the Apache doc.
Rewriting is typically configured in the main server configuration
setting (outside any <Directory> section) or inside <VirtualHost>
containers. This is the easiest way to do rewriting and is recommended
To remove index.php from the URL, and to redirect the visitor to the non-index.php version of the page:
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
This will cleanly redirect /index.php/myblog to simply /myblog.
Using a 301 redirect will preserve Google search engine rankings.
RewriteEngine On
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)index\.php($|\ |\?)
RewriteRule ^ /%1 [R=301,L]
Assuming the existent url is
http://example.com/index.php/foo/bar
and we want to convert it into
http://example.com/foo/bar
You can use the following rule :
RewriteEngine on
#1) redirect the client from "/index.php/foo/bar" to "/foo/bar"
RewriteCond %{THE_REQUEST} /index\.php/(.+)\sHTTP [NC]
RewriteRule ^ /%1 [NE,L,R]
#2)internally map "/foo/bar" to "/index.php/foo/bar"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ /index.php/$1 [L]
In the spep #1 we first match against the request string and capture everything after the /index.php/ and the captured value is saved in %1 var. We then send the browser to a new url.
The #2 processes the request internally. When the browser arrives at /foo/bar , #2rule rewrites the new url to the orignal location.
Steps to remove index.php from url for your wordpress website.
Check you should have mod_rewrite enabled at your server.
To check whether it's enabled or not - Create 1 file phpinfo.php at your root folder with below command.
<?php
phpinfo?();
?>
Now run this file - www.yoursite.com/phpinfo.php and it will show mod_rewrite at Load modules section.
If not enabled then perform below commands at your terminal.
sudo a2enmod rewrite
sudo service apache2 restart
Make sure your .htaccess is existing in your WordPress root folder, if not create one .htaccess file
Paste this code at your .htaccess file :-
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Further make permission of .htaccess to 666 so that it become writable and now you can do changes in your wordpress permalinks.
Now go to Settings -> permalinks -> and change to your needed url format.
Remove this code /index.php/%year%/%monthnum%/%day%/%postname%/
and insert this code on Custom Structure: /%postname%/
If still not succeeded then check your hosting, mine was digitalocean server, so I cleared it myself
Edited the file /etc/apache2/sites-enabled/000-default.conf
Added this line after DocumentRoot /var/www/html
<Directory /var/www/html>
AllowOverride All
</Directory>
Restart your apache server
Note: /var/www/html will be your document root
Do the following steps
1. Make sure that the hosting / your pc mod_rewrite module is active. if not active then try to activate in a way, open the httpd.conf file. You can check this in the phpinfo.php to find out.
change this setting :
#LoadModule rewrite_module modules/mod_rewrite.so
to be and restart wamp
LoadModule rewrite_module modules/mod_rewrite.so
2. Then go to .htaccess file, and try to modify to be:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)\?*$ index.php/$1 [L,QSA]
if above does not work try with this:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
3. Move .htaccess file to root directory, where is index.php there.
www OR root folder
- index.php
- .htaccess
Some may get a 403 with the method listed above using mod_rewrite. Another solution to rewite index.php out is as follows:
<IfModule mod_rewrite.c>
RewriteEngine On
# Put your installation directory here:
RewriteBase /
# Do not enable rewriting for files or directories that exist
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
I have used many codes from the above mentioned sections for removing index.php form the base url. But it was not working from my end. So, you can use this code which I have used and its working properly.
If you really need to remove index.php from the base URL then just put this code in your htaccess.
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
This will work, use the following code in .htaccess file
RewriteEngine On
# Send would-be 404 requests to Craft
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(favicon\.ico|apple-touch-icon.*\.png)$ [NC]
RewriteRule (.+) index.php?p=$1 [QSA,L]
I don't have to many bulky code to give out just a little snippet solved the issue for me.
i have https://example.com/entitlements/index.php rather i want anyone that types it to get error on request event if you type https://example.com/entitlements/index
you will still get error since there's this word "index" is contained there will always be an error thrown back though the content of index.php will still be displayed properly
cletus post on "https://stackoverflow.com/a/1055655/12192635" which
solved it
Edit your .htaccess file with the below
to redirect people visiting https://example.com/entitlements/index.php to 404 page
RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
to redirect people visiting https://example.com/entitlements/index to 404 page
RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
Not withstanding we have already known that the above code works with already existing codes on stack see where i applied the code above just below the all codes at it end.
# The following will allow you to use URLs such as the following:
#
# example.com/anything
# example.com/anything/
#
# Which will actually serve files such as the following:
#
# example.com/anything.html
# example.com/anything.php
#
# But *only if they exist*, otherwise it will report the usual 404 error.
Options +FollowSymLinks
RewriteEngine On
# Remove trailing slashes.
# e.g. example.com/foo/ will redirect to example.com/foo
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=permanent,QSA]
# Redirect to HTML if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^(.+)$ $1.html [L,QSA]
# Redirect to PHP if it exists.
# e.g. example.com/foo will display the contents of example.com/foo.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+)$ $1.php [L,QSA]
RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
RewriteCond %{THE_REQUEST} \index[\ /?].*HTTP/
RewriteRule ^.*$ - [R=404,L]
try this, it work for me
<IfModule mod_rewrite.c>
# Enable Rewrite Engine
# ------------------------------
RewriteEngine On
RewriteBase /
# Redirect index.php Requests
# ------------------------------
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteCond %{THE_REQUEST} !/system/.*
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,L]
# Standard ExpressionEngine Rewrite
# ------------------------------
RewriteCond $1 !\.(css|js|gif|jpe?g|png) [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
For more detail
create .htaccess file on project root directory and put below code for remove index.php
RewriteEngine on
RewriteCond $1 !^(index.php|resources|robots.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]