Serve resource files bypassing a framework using .htaccess directives - apache

I'm using the Kohana framework. It has the following configuration of .htaccess file:
# Protect application and system files from being viewed
RewriteRule ^(?:application|modules|system)\b.* index.php/$0 [L]
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Rewrite all other URLs to index.php/URL
RewriteRule .* index.php [PT]
I'm particulary interested in the second part Allow any files or directories that exist to be displayed directly. Can someone please elaborate in details on how it's configured?

It is due to 2 condition lines using RewriteCond directive that acts like if condition
RewriteCond %{REQUEST_FILENAME} !-f
Means if request is NOT for a valid file
RewriteCond %{REQUEST_FILENAME} !-d
Means if request is NOT for a valid directory
Both combined with RewriteRule below mean that if request is not a valid file or directory then forward every request to index.php

Related

How to prevent the execution of php, even if the file is not found?

I have the following .htaccess:
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
There is a lot of requests to that url /static/tiles/z/x/y.png.
Now, if file was not found, index.php handles the request.
But i want to if the request matches /static/tiles/.* and there is no such file, apache is just stop execution.
Add the following condition to your .htaccess
RewriteCond %{REQUEST_URI} !^/static/tiles/.*
This will prevent your rule to be met when the requested uri starts with /static/tiles.

Apache 404 url not working

I have a few problems with our company website. My colleague left the .htaccess file inside the _control directory like this:
# Virtual site directory
#
# This script lets us make use of default
# versions of files used in a typical site.
# When a request on the site is made for a file
# that doesn't exist, instead of a 404 we rewrite
# the path to /_control/site/
#
# Any file in the directory this script is in will
# take precedence over this script, so this script
# only comes into play if the file does not exist.
# First, set up URL rewriting
Options +FollowSymLinks
RewriteEngine On
# Add trailing slash for directories
# TODO: fix if site not in root dir (e.g. DEV server)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !.+\.(php|js|css|gif|jpg|jpeg|png)$ [NC]
RewriteCond %{REQUEST_URI} !.*/$
RewriteRule ^(.*)$ /$1/ [L,R=301]
# This Apache mod_rewrite rule checks to see
# if the requested file exists, if it doesn't
# then we rewrite to the respective site location.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !^.*/_control/(admin|common).*$
RewriteCond %{REQUEST_FILENAME} !^.*/_control/site/.*$
RewriteRule ^(.*)$ site/$1 [L]
The structure of my application looks like:
Everything was working OK but about a week ago, our mysite.com/admin and 404 page started redirecting to the hosting company's website. DaveG has already answered first part of the problem here: https://stackoverflow.com/a/26013322/1933380 and I was able to get the virtual directories working. I am still having problems with the 404 page. Am I missing something or making a mistake?
What you are doing now, is telling the webserver to look for all non-existing pages and directories in another folder (_control). This does not give a solution for typo's, non-existing pages etc. If you want to solve this, you could use:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !^.*/_control/(admin|common).*$
RewriteCond %{REQUEST_FILENAME} !^.*/_control/site/.*$
RewriteRule ^(.*)$ site/errhandler.php?file=$1 [L]
and make a file called errhandler.php, which displays a custom 404-page and (for example) give possible alternatives based on a database search or whatever. You could then use $_GET['file'] to display the original filename.

htaccess rewrite rules to remove multiple subfolders from a URL

Due file system sub-directory constraints I will most likely reach I want to separate the /users folder into /users/a/username, /users/b/username, /users/c/username, etc.
So the data on the server for a user would be in:
www.domain.com/users/a/username/, www.domain.com/users/b/username/, etc
I want the URL to be:
www.domain.com/users/username/
Optionally to avoid duplicate content a 301 redirect from www.domain.com/users/a/username/ to www.domain.com/users/username/ would also be good.
Currently I have a rewrite for a single sub-directory (see below) but I'm confused how this can be done efficiently for all of the alphabetical sub-directories.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^users/(.*)$ users/a/$1 [L,NC]
I have checked this site and all seem to hide the first sub-directory e.g. domain.com/folder1/filename.html => domain.com/filename.html but nothing in more depth.
Put this code in your htaccess (which has to be in root folder)
Options -Indexes -MultiViews
RewriteMap lowercase int:tolower # this line in your apache file configuration
RewriteEngine On
RewriteCond %{THE_REQUEST} \s/users/[a-z]/([^/\s]+)\s
RewriteRule . /users/%1/? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^users/([A-Za-z])([^/]+)/$ /users/${lowercase:$1}/$1$2/ [L]

500 server error with hiding .htm and .html file extensions on non-existing files

Need to improve this rule.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*) /$1.htm [L]
Per my hosting company: The reason for 500 errors on non-existent pages is because of the the above rewrite rules used by your application, which are as follows:
the rules above mean that any request to a non-existent file or directory will be redirected to URI.htm where URI is the requested URI.
Continuing: In this example archives.hwg.org/thispagedoesnotexist is being rewritten to archives.hwg.org/thispagedoesnotexist.htm , which is a nonexistent page so the rewrite rules try to once again rewrite the request to archives.hwg.org/thispagedoesnotexist.htm.htm , which is also nonexistent. This continues to loop until the following error is generated.
Here are some of my actual site files using the above rewrite rule, but if you try to type in a non-existing file or directory you will see the 500 error.
This is link format to actual file:
archives.hwg.org/hwg-theory/01082413075904.02137#kira.pacbell.net
This is the actual file:
archives.hwg.org/hwg-theory/01082413075904.02137#kira.pacbell.net.htm
This is link format to actual file:
archives.hwg.org/hwg-theory/2001/07
This is the actual file:
archives.hwg.org/hwg-theory/2001/07.htm
Assuming that archives.hwg.org is the domain, then this should work. The rules have to be performed in order. In a different order the files will not be found initially and the server will loop multiple times until a match is found (making the interaction with the server slower for every page.)
We're checking if the file is a non-existent. If it's non-existent, then we try to go one "directory" down. Ultimately we get to any file and any directory that doesn't exist ends up going back to the homepage index.html.
Note if anything on the site changes or you're experiencing an error in a particular directory, the server is trying to redirect the user to a file ending specifically in .htm. According to the rules all files in folders have to end with .htm.
Remember that everything in Unix/Linux is case sensitive (unless purposely overridden). Additionally web servers look for the specific files they're queried for. Your specific main file is index.html, not index.htm.
The 500 error typically happens because a loop is created when you're looking for a file that is non-existent but being redirected back to that same file.
If you're responsible for maintaining the server you need to check out mod_rewrite in the event you accidentally create this sort of issue again.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)/([^/.]+)/?$ /$1/$2/$3.htm [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/.]+)/?$ /$1/$2.htm [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/.]+)/?$ /$1.htm [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.html [L]

mod_rewrite picking up directories that exist

I have the following .htaccess in the root folder of a web application:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^\.(.*) [NC]
RewriteRule ^(.*) http://%1/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?req=%{REQUEST_URI}&%{QUERY_STRING}
This works as I want with one exception: if the directory actually exists, that directory is served rather than the request being passed of to the PHP script.
So if directory /docs/ exists, the index.htm is sent to the browser whereas a request for the directory /doesnotexist/ which doesn't exist will be handed to the PHP script.
Any ideas how I can amend this so that ALL requests are handed off to PHP regardless of whether the location exists or not?
Your second set of conditions constrain matching requests to not point to an existing file nor an existing directory. That's why when you browse to /docs/ and the directory exists the rule won't fire.
All you need to do to fix this, is to get rid of the second rewrite condition. This let's the rule beneath it fire on any request that does not point to an existing file. If, indeed, what you want is to redirect every request to the PHP script, then the first rewrite condition needs to be eliminated as well.
RewriteCond %{REQUEST_FILENAME} !-f
# RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ index.php?req=%{REQUEST_URI}&%{QUERY_STRING}
Note that the # uncomments the line so it won't get picked up by mod_rewrite.