.htaccess rewrite rule with existing directory - apache

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.

Related

Apache rewrite /product/ to /products/ and index.php

I've been asked to help on an ExpressionEngine site that's been developed. There is an existing .htaccess file that rewrites anything that isn't a file or directory so that it goes via index.php:
RewriteEngine On
RewriteBase /
# Not a file or directory (also catches index.php)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]
This works fine, and an example URL might be:
www.mysite.com/products/foo (plural 'products')
However, It also needs to deal with old URLs which will be in the form:
www.mysite.com/product/foo (singular 'product')
I've tried the following:
RewriteEngine On
RewriteBase /
# Not a file or directory (also catches index.php)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^product/(.+) /index.php/products/$1 [L]
RewriteRule ^(.*)$ /index.php?$1 [L]
Hoping that if it finds 'product' then it rewrites to 'products' via index.php and then quits, but it's not working.
At the same time, I need any incoming URL that starts:
/department/foo
to be rewritten to:
/departments/category/foo
Any help greatefully received.
You can use add a rule above your existing rule to for mapping product -> products:
RewriteEngine On
RewriteBase /
RewriteRule ^product(/.*)?$ products$1 [L,NC]
# Not a file or directory (also catches index.php)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?$1 [L]

Apache .htaccess retry other directory if file not found

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]

Cannot properly merge two .htaccess

There are 2 .htaccess files, one in / and the second in /web folders.
In a root folder (/), .htaccess looks like
RewriteEngine on
RewriteRule ^$ web/ [L]
RewriteRule (.*) web/$1 [L]
In /web folder, .htaccess looks like
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,L]
It works perfectly.
All I want is to merge those conditions and put them inside a single .htaccess that would be in root directory (/).
1 - I've tried to add RewriteBase, like
RewriteBase /web
2 - I've tried to replace conditions that aware of web folder
RewriteRule ^(.*)$ web/index.php/$1 [QSA,L]
3 - I've tried to simply append a config from one file to another with slight alterations.
But none of this works - It gives internal 500 server error.
How a proper merging should be done in this case?
This .htaccess (in the root folder) should match to your needs :
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ web/index.php/$1 [QSA,L]
If you're putting all the rules in your document root (/) then try:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /web/index.php/$1 [QSA,L]

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]

How to exclude all files and directories except one directory, RewriteCond

I would like to redirect all non-files, non-directories to index.php, so everything that exists is directly accessible - except for one directory (which should also go to index.php)
What I have is:
# Files
RewriteCond %{REQUEST_FILENAME} !-f
# Directories except /orderfiles/*
RewriteCond %{REQUEST_FILENAME} ^/(orderfiles/)* [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php [L,QSA]
This works for directories inside /orderfiles, but a files inside of /orderfiles still goes to that file. I tried adding
RewriteCond %{REQUEST_FILENAME} ^/(orderfiles/)* [OR]
RewriteCond %{REQUEST_FILENAME} !-f
But this breaks and sends every file to index.php.
You're close, you want something like this:
# Files
RewriteCond %{REQUEST_FILENAME} !-f
# Directories
RewriteCond %{REQUEST_FILENAME} !-d
# except /orderfiles
RewriteRule !^/?orderfiles index.php [L,QSA]
I realized I mistyped what I was trying to do, I meant "but send one directory to index.php" (I edited my question to be more accurate). I do want /orderfiles to be routed to index.php
Then what you have is correct, but you need to change this line:
RewriteCond %{REQUEST_FILENAME} ^/(orderfiles/)* [OR]
to:
RewriteCond %{REQUEST_URI} ^/orderfiles/ [OR]