Apache .htaccess retry other directory if file not found - apache

i need a htaccess rewrite rule for my apache webserver that searches in other directories if a file has not been found.
if
http://domain.com/x.jpg
is not found, look in
http://domain.com/bla/x.jpg
if not there then look in
http://domain.com/foo/x.jpg
and so on.
i am trying the following but it doesnt work. still gives me 404s
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*\.(gif|png|jpg|jpeg|apk|bmp|webp))$ /foo/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]*\.(gif|png|jpg|jpeg|apk|bmp|webp))$ /bla/$1 [L]

The problem with you're current config, is that it always does the first rewrite if the file doesn't exist and the second rewrite never get's executed. You will need to check for existence of the file before doing the redirection such as below
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^(.*)(/.+\.(gif|png|jpg|jpeg|apk|bmp|webp))$
RewriteCond %{DOCUMENT_ROOT}%1/bla%2 -f
RewriteRule . %1/bla%2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} ^(.*)(/.+\.(gif|png|jpg|jpeg|apk|bmp|webp))$
RewriteCond %{DOCUMENT_ROOT}%1/foo%2 -f
RewriteRule . %1/foo%2 [L]

Related

.htaccess rewrite rule with existing directory

I have the following .htaccess file on my website root
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)/?$ /index.php?t=$1 [L]
It means that, for some links like
www.website.com/foo
www.website.com/bar
it will be internally replaced by
www.website.com/index.php?t=foo
www.website.com/index.php?t=bar
Problem is: one of this directories (say, bar) exists, and I want to be able to use the link www.website.com/bar/file.pdf, so I had to modify .htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?([^/]+)/?$ /index.php?t=$1 [L]
I removed the line ending in !-d, which means “if the directory doesn’t exist”. But now I see
www.website.com/bar/index.php?t=bar
So how can I have both
www.website.com/bar
www.website.com/bar/file.pdf
with the first redirecting (internally) to www.website.com/index.php?t=bar and the second pointing to the right file?
You could try this if /bar/index.php exists:
RewriteEngine On
#
# rule 1
#
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . %{REQUEST_FILENAME}/index.php [QSA,L]
#
# rule 2
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)/?$ /index.php?t=$1 [L]
This way if directory /bar/ exists, it's rewritten definitively by the first rule 1 to /bar/index.php. At the same time, /bar/file.pdf will not be touched as the file exists.

My Apache rewrite code (provided) in .htaccess works, but also re-writes favicon.ico. How fix?

I have always used this simple code to have all requests use one index.php file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? index.php [L]
However, I have just found that it's also re-writing the favicon.ico file.
My understanding is that the code above should rewrite only index.php and no other file or directory. Am I wrong? How would I fix this?
Just add an exception for it in your rules.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/favicon.ico [NC]
RewriteRule .? index.php [L]

Use specific PHP file for specific directories

I am trying to create mod_rewrite rules that rewrite based on the first level directory name plus a failover to rewrite to a standard file in case none of the directory names are matched.
Example:
I have units.php, models.php and other.php. The other.php file should handle all non-assigned requests.
http://www.mydomain.com/units/4435
Should redirect to /units.php?id=4435
http://www.mydomain.com/models/594
Should redirect to /models.php?id=594
http://www.mydomain.com/anything
Should redirect to /other.php?id=anything
http://www.mydomain.com/anything/893
Should redirect to /other.php?id=anything/893
Let me know if this makes sense. I am unsure of how to structure the rules and conditions to achieve what I want.
This is what I have tried to sfar. It works for URLs starting with 'units' or 'models' but I get a 500 Error if I try any other URL:
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(units)/(.+)$ /units.php?id=$2 [L,NC]
RewriteRule ^(models)/(.+)$ /models.php?id=$2 [L,NC]
RewriteRule ^(.+)$ /other.php?id=$2 [L,NC]
I would suggest this:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(units|models)/([0-9]+)/?$ /$1.php?id=$2 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/(units|models)/[0-9]+/?$
RewriteRule ^/[^/]+/([0-9]+)/?$ /other.php?id=$1 [L,QSA]

mod_rewrite rules in .htaccess

I want to do change my document root using rewrite rules in my .htaccess file, and also redirect all requests to index.php except static resources
In other words:
if a file with the path prepended with www exists (i.e. www/{%request_uri}):
http://domain.com/css/main.css should be rewritten to http://domain.com/www/css/main.css
if that file does not exist, redirect to the app main entry point www/index.php:
e.g.
http://domain.com should be rewritten to http://domain.com/www/index.php
http://domain.com/hello should be rewritten to http://domain.com/www/index.php/hello
http://domain.com/hello?a=1 should be rewritten to http://domain.com/www/index.php/hello?a=1
I tried variations, however either it gives us 500 internal server error, or infinite loop. Here is one that gives 500 internal server error:
# try to find it in www/
RewriteCond {%DOCUMENT_ROOT}/www%{REQUEST_URI} -f
RewriteCond {%DOCUMENT_ROOT}/www%{REQUEST_URI} -d
RewriteRule ^(.+) www/$1 [L]
RewriteRule ^(.*) www/index.php/$1 [L]
This one also:
RewriteCond %{REQUEST_URI} !www/
RewriteRule (.*) /www/$1
RewriteCond {%REQUEST_FILENAME} !-f
RewriteCond {%REQUEST_FILENAME} !-d
RewriteRule www/(.*) /www/index.php/$1 [PT,L]
Can anyone help?
I think that's impossible with a single .htaccess but it's possible with two.
You need one in your root directory, /.htaccess:
RewriteEngine on
RewriteBase /
# We don't want infinite rewriting.
RewriteCond %{REQUEST_URI} !www/.*$
RewriteRule ^(.*)$ www/$1 [L]
And another in your www directory, /www/.htaccess:
RewriteEngine on
RewriteBase /www
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
Well actually I made a stupid mistake! The % sign should be outside of the {} bracket!
This can be done in one .htaccess in root dir:
RewriteEngine on
RewriteCond %{REQUEST_URI} !www/
RewriteRule ^(.*)$ www/$1
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^www/(.*)$ www/index.php/$1 [L]

Apache URL Rewriting issue

i've set the rules,
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)/?$ user.php?userid=$1
it redirects http://localhost/username to http://localhost/user.php?id=username works fine,
but for other existing folder page still redirects to user.php page; not that existing folder, ex http://localhost/folder it still redirects to http://localhost/folder/?userid=folder,
how can it make it to work for existing directories, ex when i type http://localhost/folder then page should shown of /folder/ directory ???
Replace your .htaccess code with this:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
RewriteRule ^(messages)/?$ index.php?page=$1 [L,NC,QSA]
RewriteRule ^(A-Z0-9_-]+)/?$ user.php?userid=$1 [L,NC,QSA]
If it still doesn't work please post matching long entries from access.log and enable RewriteLog in your httpd.conf and post logs from there in your question.
The problem is that your second RewriteRule has no RewriteConds. Your two RewriteConds only apply for the first rule, then they stop. The second rule therefore applies unconditionally to every request URI.
So this part of your .htaccess should look like this instead:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^messages/?$ index.php?page=messages [L,NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9_-]+)/?$ user.php?userid=$1 [L,NC,QSA]