mod_rewrite picking up directories that exist - apache

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.

Related

Redirecting all urls, including no path, to a file in subdirectory

I have checked a large amount of existing answers regarding .htaccess redirects. However none of them have helped me.
What I want to accomplish is redirecting all request urls to /api/init.php. However I've only gotten so far to where my index page www.example.com simply gives me a file listing because of the missing index.php file, while every url request with a path is working.
How can I accomplish this with .htaccess without ending up with a directory listing on my landing page?
This is as far as I got:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /api/init.php?path=$1 [NC,L,QSA]
Well your site root is a directory, so this rule you have excludes existing directories. What you could do is only exclude existing files, and allow existing directories to be handled by the PHP script. Like this:
RewriteEngine on
RewriteCond %{REQUEST_URI} !=/api/init.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /api/init.php?path=$1 [L,QSA]
I removed the NC flag as it's not needed. I added a condition to prevent an unnecessary file-system check.
You don't have to pass the path on in a URL parameter, as you could get it from $_SERVER['REQUEST_URI'] in PHP (not the same as REQUEST_URI in mod_rewrite, in PHP it always has the original URI). If you wanted to do that then your rule becomes nice and simple:
RewriteEngine on
RewriteCond %{REQUEST_URI} !=/api/init.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ /api/init.php [L]
Because the query string will just be passed on unaffected (so QSA is not needed).

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.

RewriteRule for unknown directory

So I'm trying to get a mod_rewrite rule to redirect requests to a php-script with an .htaccess file. The thing is, I want it to work regardless of where I put the project on a webserver (the .htaccess file and the php-script are always in the same folder).
The rewrite itself is very simple. If the script and the .htacess are in the directory /path/to/project and the user visits:
/path/to/project/somestring
it should be rewritten to:
/path/to/project/index.php?t=somestring
This should work for every subdirectory at any level in the webserver. So:
If the php-script and the .htaccess files are in the root:
/somestring2
should be rewritten to:
/index.php?t=somestring2
If the php-script and the .htaccess file are in /subdirectory:
/subdirectory/somestring3
should be rewritten to:
/subdirectory/index.php?t=somestring3
So the RewriteRule should perform the same rewrite action regardless of where the project lives within the server. The string that is to become a GET-parameter can consist of those characters: [a-zA-Z0-9]. If there are other GET-parameters in the requested URL, they should be appended as well (hence the QSA flag). This is what I've tried:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*/)([a-zA-Z0-9])/? $1index.php&t=$2 [L,QSA]
However, this results in a 404 error. How can I alter it to do what I want?
Try :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*/)?([A-Za-z0-9]+)/?$ /$1index.php?t=$2 [NC,L,QSA]
Note that a leading slash in rewrite pattern is not required in the RewriteRule context.

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]

Apache rewrite condition to fall back when css doesn't exist

I need a rule in Apache that redirects not-found CSS files to another location based on their names in another folder. Like this:
Request: localhost/css/nonexistent.css
Response: localhost/css/g/nonexistent.css
If the CSS exists, just serve it like normal:
Request: localhost/css/existent.css
Response: localhost/css/existent.css
My project is on CakePHP which comes with the following rules by default:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
I mention it because whatever the new rule is, it should not break Cake's rules.
Thanks for the help.
Edit: Forgot to mention that the css/g/ file is an alias for a script (inside the Cake MVC stack) that generates the new css file and echoes it. Answers so far seem to do the redirection fine, but then it doesn't find the css/g/file.css either because it really doesn't exist.
Here is a rewrite rule adapted from this SO question and the Apache mod_rewrite docs.
The gist is: If the request is for a path that starts with /css/,get the filesystem path of the requested file and check if it exists. If id doesn't, rewrite the URL for your deeper directory. This should be placed before the rules you posted in your question.
RewriteCond %{REQUEST_URI} ^/css/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/css/(.*) /css/g/$1
You can try first checking if the /css/g/ css file exists:
# Make sure it doesn't exist
RewriteCond %{REQUEST_FILENAME} !-f
# Make sure this is a request for a css file:
RewriteCond %{REQUEST_URI} ^/css/(.*)\.css$
# See if the /g/ version exists
RewriteCond %{DOCUMENT_ROOT}/css/g/%1.css -f
# rewrite if all conditions satisfied
RewriteRule ^css/(.*)$ /css/g/$1 [L]
The %1 in the 3rd condition backreferences the filename (sans .css extension) matched in the previous RewriteCond.
EDIT:
If the file css file is actually generated, then skip the checking of /g/ version and just pass it to the controller:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^/css/(.*)\.css$
RewriteRule ^css/(.*)$ index.php/css/g/$1 [L]