Using mod_rewrite only if a 404 would have occured - .htaccess

I am in the process of converting a static website into one using a cms.
I have the cms installed in a sub directory of the public directory. To avoid ending up with ugly domain names (http://example.com/cms/) is there an easy way using mod_rewrite to rewrite http://example.com/… to http://example.com/cms/… while ensuring that if the request wouldn't have ended in a 404, there is no redirect.
An example:
/
/cms/index.html
/cms/file.dat
/file.dat
If the user requests /index.html, they should get redirected to /cms/index.html, but if they request /file.dat, they shouldn't get redirected to /cms/file.dat because the file existed at the requested place
EDIT
Thanks for the answers.

You could use the RewriteCond Directive to check whether there is an existing file that correspond to the requested URL, and only rewrite to your CMS if there is none.
Here is a simple example :
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php
If there is no existing file that correspond to the requested URL, then that request is rewritten to index.php
You might also want to check for symbolic links and / or directories, btw...
For instance, here is a possibility that can be used when setting up a Zend Framework project :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
(Even though it links to ZF, it should be OK for quite many projects)

Try this rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !^cms/ cms%{REQUEST_URI} [L]

Related

.htaccess Rewrite Rule Understanding Problems

Site Structure
/articles/Employment/Companies.php
/articles/Employment/Companies/.htaccess
/articles/Employment/Companies/index.php
.htaccess file reads
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ index.php [L]
So when you go to
/articles/Employment/Companies/[company type]
It is displaying the index.php page.
The Problem
I'm trying to link to
/articles/Employment/Companies.php
without the .php being displayed, however if I link to
/articles/Employment/Companies
it is going to
/articles/Employment/Companies/
What i'm Ideally Looking For
Understand why I my site is adding the / when linking to folder/hello
to strip out all .php so if you go to /hello it'll display /hello.php apart from in certain directories such as my current .htaccess file is located where /this or /that will display /index.php.
Please try with below, use from rewritecond with your existing rule what I am doing if the request is actually for php file which is not index.php then serve the extension less code.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule !index.php$ $1.php [L]

How can I redirect my pages using .htaccess

I am in the process of completely rewriting my old site in PHP and need to redirect the old pages to the new.
The old site made heavy use of perl scripts; in particular /cgi-bin/browse.cgi and /cgi-bin/search.cgi . I need these to redirect to /browse.php and /search.php respectively.
All other pages on the old site were fixed html pages in a hierarchical structure e.g. domain/place1/place2/place3.html . I need these to redirect to /index.php where the request is processed and PHP redirects implemented.
Currently I have this code in the .htaccess file:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
#RewriteRule ^cgi-bin/browse\.cgi(.*)$ ./browse.php?$1 [L]
#RewriteRule ^cgi-bin/search\.cgi(.*)$ ./search.php?$1 [L]
RewriteCond %{REQUEST_URI} !^search\.php
RewriteCond %{REQUEST_URI} !^browse\.php
RewriteCond %{REQUEST_URI} !^index\.php
RewriteRule ^(.*)$ ./index.php?%1 [L]
This does not currently cater for requests to domain/cgi-bin/search.cgi or similar browse.cgi, and every time I remove the # for the RewriteRules I get a 500 scripting error.
Basically, I need cgi-bin/browse.cgi requests to go to browse.php; similar for search.cgi, and everything else to go to index.php
Any help will be greatly appreciated.

.htaccess doesn't rewrite relative to the root directory

I have tried to create an .htaccess file to do following:
Direct www.domain.com/name or www.domain.com/name/ to www.domain.com/page.php?id=name
and www.domain.com/name/2 or www.domain.com/name/2/ to www.domain.com/page.php?id=name&pg=2
my .htaccess looks like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# If the request is not for a valid directory
RewriteCond %{REQUEST_FILENAME} !-d
# If the request is not for a valid file
RewriteCond %{REQUEST_FILENAME} !-f
# If the request is not for a valid link
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^([a-z0-9-_\.]+)/?$ page.php?id=$1 [L]
RewriteRule ^([a-z0-9-_\.]+)/([a-z0-9]+)/?$ page.php?id=$1&pg=$2 [L]
</IfModule>
The problem is, that when I actually use a slash after name it thinks of it as a directory and looks for pages in www.domain.com/name/.. But I am still able to $_GET the variables based on id and pg.
Can anyone tell me what I have done wrong? I prefer that the URL in the address bar stays clean as www.domain.com/name/2/.
Also i have another question.. I have tried to rewrite the other URLS without luck.
If they write: www.domain.com/page.php?id=name&pg=2 and want to change the address bar URL to be be clean again, but that completely went wrong for me. Is there any specific way to do this by using what I have already made?
Thanks in advance for your help.
EDIT
The solution was based on PHP and not .htaccess. The answer was found based on this question: Stylesheet does not load after using RewriteRule and include . My problem was caused by PHP including relative to the public URL and directory. I have been forced to define a main URL variable to place before any foreign includes.
RewriteCond is only applicable to the very next RewriteRule.
Have your code this way:
RewriteEngine On
RewriteBase /
# If the request is for a valid directory
RewriteCond %{REQUEST_FILENAME} -d [OR]
# If the request is for a valid file
RewriteCond %{REQUEST_FILENAME} -f [OR]
# If the request is for a valid link
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^ - [L]
# external redirect from actual URL to pretty one
RewriteCond %{THE_REQUEST} \s/+page\.php\?id=([^\s&]+) [NC]
RewriteRule ^ %1? [R=302,L]
RewriteRule ^([\w.-]+)/?$ page.php?id=$1 [L,QSA]
RewriteRule ^([\w.-]+)/([\w.-]+)/?$ page.php?id=$1&pg=$2 [L,QSA]

Clean urls and https redirect conflict in .htaccess using YII

I have the following in my .htaccess - the clean url's declaration and the https redirect both work fine individually but put together are causing the continuous redirect error (this server is redirecting in a way which will never complete).
Here is my .htacess:
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
# force to use https
#RewriteCond %{HTTPS} !=on
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Any idea how i can resolve this?
Thank you
Hope I am not late as I stumbled through your same problem and figured out the conflict just a day ago.
Write the following in your .htaccess file:
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
The first rule will automatically redirect any HTTP requests to HTTPS and (through the crucial [L] tag) stop other substitutions which will mess up the page (specifically, images and CSS stylesheets would not be served).
The second one is the Yii suggested way to check whether a particular URL corresponds to a real file or directory and, if not, to forward the request to index.php (the bootstrap file for the Web application). (The rules in the application's configuration file should do the rest, then).

mod_rewrite and .htaccess - stop rewrite if script/file exists

This is my htaccess:
RewriteEngine On
# Stop if it's a request to an existing file.
RewriteCond %{REQUEST_FILENAME} -f [NC,OR]
RewriteCond %{REQUEST_FILENAME} -d [NC]
RewriteRule .* - [L]
# Redirect all requests to the index page
RewriteRule ^([^/]) /index.php [L]
Now this forwards everything to my index.php script! It dosen't stop if a script exists. Anyone have any idea why this isn't working? I've looked everywhere, but I don't really understand mod_rewrite (as much as I thought!).
The problem has come about because I've put in <script> tags which point to .js files in my web directory which are then forwarded to the index.php script. The web developer toolbar tells me this. :) And clicking links to the js files in firefox's view source window also shows the index.php output.
thank you.
This is because after processing a rewrite rule the whole process restarts with the new url. The processing of an url can go thru the rules over and over again each time with the changed URL, until there is no more change (no applying rules found).
You need this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php [L]
Don't think of the rules as a program, they are rules which can overlap and must be as specific as possible with each one.
I guess you should add [OR] after the first condition like this:
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule (.*) $1 [QSA,L]

Resources