Forum Moderators: phranque

Message Too Old, No Replies

RewriteRule: redirect to index.php when not matching

rewriterule, redirect, index.php, not matching

         

Cequiel

6:33 pm on Jan 24, 2012 (gmt 0)

10+ Year Member



Hi Everyone,
What I want to do is quite simple, but I don't know how to achieve it. And I have spend too many hours thinking about it.

This's the problem. My .htaccess file is as follows:

Options +FollowSymlinks
RewriteEngine on
RewriteRule ^.*login/?$ login.php
RewriteRule ^.*comment/?$ comment.php
RewriteRule ^.*blah/?$ blah.php

This allows me to redirect to the appropiate php file. For example, when the user enters the following url:
mycustomdomain.com/section1/section2/section3/../login

Apache redirects to the login.php file, no matter "section1/section2/section3/.." is.

What I want to do is redirect to index.php when my request doesn't match any of the above rules. For example, when the user enters the following url:

mycustomdomain.com/section1/section2/section3/../tralariquetevi

I would like to redirect the request to index.php, because "tralariquetevi" is not listed in the above rules.

How could I achieve that?
Thank you very much and sorry for my English :)

g1smd

7:49 pm on Jan 24, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



None of your rules "redirect" anything. They are all internal rewrites. Be sure you know the difference.

Add [L] to every rule. This stops further mod_rewrite procesing when a rule matches a request.

Add a catch-all rule that rewrites all remaining requests to the index.php file. This rule will be last. You'll need at least one preceding RewriteCond on this rule otherwise you'll end up rewriting requests for images and stylesheets too.

Do NOT use the .* pattern at the beginning of a pattern or in the middle of a pattern. The .* is greedy, promiscuous and ambiguous. It's the wrong way. Use a more specific pattern such as ^(([^/]+/)*) here.

The question mark after the slash promotes duplicate content. It allows multiple URL requests to resolve to the same content. Pick one, either "with slash" or "without slash" to deliver the content and redirect requests for the other format to that URL form. The URL format "without slash" is the preferred form for a page.

Your php file must validate the requested URL as the VERY FIRST ACTION and return the correct 404 response when there is no content to return for this request. This is VITAL. Returning 200 OK for any and all requests is asking for trouble, and lots of it.

Cequiel

11:10 pm on Jan 24, 2012 (gmt 0)

10+ Year Member



Thank you very much!

This is what I did, just in case someone has the same problem as me:

.haccess file:
--------------
# Rewrite mapping rules
RewriteRule ^(([^/]+/)*)login/$ login.php?path=$1 [L]
RewriteRule ^(([^/]+/)*)comment/$ comment.php?path=$1 [L]
RewriteRule ^(([^/]+/)*)page1/$ page1.php?path=$1 [L]
RewriteRule ^(([^/]+/)*)page2/$ page2.php?path=$1 [L]
RewriteRule ^(([^/]+/)*)page3/$ page3.php?path=$1 [L]

# Rewrite all requests to index.php
# except directories and files
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]


index.php file:
---------------
/*
* If '/' is missing at the end of the url request and it has no parameters,
* add it and redirect.
*/
$info = parse_url($_SERVER["REQUEST_URI"]);
$path = $info["path"];
if (!array_key_exists("query", $info) && !preg_match("#/$#", $info["path"])) {
header("Location: $path/");
die();
}

page.php file:
--------------
/*
* If the request is not a valid url, print a 404 error
*/
$path = array_key_exists("path", $_REQUEST)? $_REQUEST["path"]: NULL;
if (!is_valid_path($path)) {
header('HTTP/1.0 404 Not Found');
echo file_get_contents("templates/page_not_found.html");
die();
}

g1smd

11:30 pm on Jan 24, 2012 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That's pretty good, but according to the HTTP specs URLs for "pages" do not end with a slash. URLs ending with a slash are for "folders".

I would either redirect to remove slash when the URL is not for a folder, or else just allow extensionless URL requests without a final slash to be rewritten and therefore URL requests with slash will simply return 404 if they are not for "real" folders. I prefer this latter method.

One minor technicality is that your usage of capturing the path in $1 isn't quite correct. The reason isn't obvious, but slashes are not valid in parameter values according to the HTTP specs. You might get away with it for now, but another server might reject that usage and the code fail. Be sure to document that as a comment in your code.

If your pages really are called page1, page2 and page3, you can simplify three rewites to one:
...page1/$ page1.php...
becomes
...page([123])/$ /page$2.php...


Make sure you add the standard non-www to www redirect (using a RewriteRule) before these rewrites.

Finally, your PHP redirect generates a 302 redirect. Be sure to alter the code to generate a 301 redirect instead.

Code that "almost works" can kill a site faster than code that doesn't work at all. The devil is in the details, and there's lots of them that can be gleaned only from a thorough read of the relevant documentation: HTTP specs, Apache mod_rewrite manual and previous threads in the WebmasterWorld Apache forum. :)

Cequiel

1:12 am on Jan 25, 2012 (gmt 0)

10+ Year Member



Uff, configuring Apache is insane :D Actually the project is a small application and it is working fine now, and I have spent to much time thinking in this "insignificant" problem. In any case, I'll keep in mind your suggestions. Thanks :)