Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mod_rewrite exception for a specific file

My page is not redirecting as it should due to my .htaccess file which is set as:

RewriteEngine on  
RewriteCond $1 !^(index\.php|resources|robots\.txt)  
RewriteCond %{REQUEST_FILENAME} !-f  
RewriteCond %{REQUEST_FILENAME} !-d  
RewriteRule ^(.*)$ index.php/$1 [L,QSA]   

I use this setup for my MVC Framework so i get urls like /controller/method/argument however when I redirect to /forum/login.php it cuts to /forum/.

How can I add this as an exception so that i will be able to redirect to /forum/login.php

I found another .htaccess in my /forum/ directory could this be causing the problem as well?

# BEGIN PunBB

<IfModule mod_rewrite.c>
    # MultiViews interfers with proper rewriting
    Options -MultiViews

    RewriteEngine On

    # Uncomment and properly set the RewriteBase if the rewrite rules are not working properly
    #RewriteBase /

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . rewrite.php [L]
</IfModule>
like image 235
Sterling Duchess Avatar asked Oct 12 '12 19:10

Sterling Duchess


People also ask

What does IfModule mod_rewrite C mean?

The <IfModule mod_rewrite. c>... </IfModule> block ensures that everything contained within that block is taken only into account if the mod_rewrite module is loaded. Otherwise you will either face a server error or all requests for URL rewriting will be ignored.

What is mod_rewrite used for?

mod_rewrite provides a flexible and powerful way to manipulate URLs using an unlimited number of rules. Each rule can have an unlimited number of attached rule conditions, to allow you to rewrite URL based on server variables, environment variables, HTTP headers, or time stamps.

What is rewrite cond in htaccess?

htaccess rewrite rules can be used to direct requests for one subdirectory to a different location, such as an alternative subdirectory or even the domain root. In this example, requests to http://mydomain.com/folder1/ will be automatically redirected to http://mydomain.com/folder2/.

What is mod_rewrite Apache?

mod_rewrite is an Apache module that allows for server-side manipulation of requested URLs. mod_rewrite is an Apache module that allows for server-side manipulation of requested URLs. Incoming URLs are checked against a series of rules. The rules contain a regular expression to detect a particular pattern.


Video Answer


1 Answers

First I'll tell you how to read your RewriteRule:

You start with the first (or next) RewriteRule entry:

RewriteRule ^(.*)$ index.php/$1 [L,QSA]

The first parameter is a regular expression that can match your requested URL. ^(.*)$ matches everything, and stores this "everything" inside a variable that can be used later.

Only if there are preceding RewriteCond entries, they are evaluated next:

RewriteCond $1 !^(index\.php|resources|robots\.txt)

$1 is a reference to the content matched inside the first parentheses of RewriteRule. This is compared to the second parameter, which is a regular expression stating several explicit names, and the ! negates the expression, e.g. this rule allows execution of the RewriteRule only if the regex does not match. If this condition returns true, the next condition will be looked at.

RewriteCond %{REQUEST_FILENAME} !-f

If the requested filename is no real file on the harddisk, this condition is true.

RewriteCond %{REQUEST_FILENAME} !-d

If the requested filename is no real directory, this condition is true.

Only if all these conditions are true (they are chained together with AND), we come back to the rewrite rule:

RewriteRule ^(.*)$ index.php/$1 [L,QSA]

The result of this rewrite step is defined as the second and third parameter. $1 is used again as with the content of the match, and the parameters define that this rule, if initially matched, will be the last rule (L), and that any query string defined in the rewrite target will be appended to any query string in the original URL (QSA).

Critique:

The usual rewriting for MVC frameworks try to be as performant as possible. Your rewrite conditions all have to be evaluated for a successful rewrite. The will stop only if any of the RewriteCond return false. Every request that gets rewritten is subject to plenty of cpu intensive tests. First the RewriteRule regex, then the regex in the first RewriteCond, followed by two harddisk tests on the filesystem for file existance.

On the other hand, the first RewriteCond seems to be unnecessary. It tests for certain names, and if found, aborts the rewriting. "index.php" should be detected by the second RewriteCond, because it is an existing file (how would the rewriting work if not). Anything starting with "resources" will also be matched, but probably shouldn't for the same reasons: Existing resources will be found by the second RewriteCond. Last the "robots.txt" file. It is always a good idea to have one, possibly emtpy if you want to avoid 404 when robots fetch your site.

As you are not changing anything in the query string, the [QSA] directive is not needed.

Improvements:

RewriteEngine on  
RewriteCond %{REQUEST_FILENAME} -f [OR] 
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [L]  
RewriteRule ^.*$ index.php [L]

The first RewriteRule will match the whole requested path. The two RewriteCond are connected with [OR], so the first RewriteCond that returns true will cancel further evaluation. The first RewriteCond tests if the requested file exists. If it exists, it returns true, and the processing returns to the first RewriteRule. The target expression is "-", which means "do not rewrite". The [L] stops further processing of rewrite rules. So in the end, for an existing file we only have one regex and one filesystem test, and after that, this existing file will be sent to the browser.

If no file was found, the first RewriteRule and RewriteCond will not trigger, so the [L] there will not stop the process. So the second RewriteRule is executed. This one is unconditional, and the regex is the same as before, matching everything, and rewriting it to "index.php".

This rewriting will not call your index.php if any file exists, including /forum/login.php.

You can change the second to RewriteRule ^.*$ index.php/$0 [L] if you do want to continue parsing $_SERVER['PATH_INFO'] instead of $_SERVER['REQUEST_URI'].

like image 110
Sven Avatar answered Sep 28 '22 18:09

Sven