Forum Moderators: phranque

Message Too Old, No Replies

Redirection problem using .htacess file

         

swatej

7:08 am on Jul 3, 2007 (gmt 0)

10+ Year Member



Hi,

I have created .htaccess file on server with following Rules:

RewriteEngine On

RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^www.example.com
RewriteRule (.*) http://www.example.com/$1 [R=301,NC]

RewriteCond %{REQUEST_URI} ^/index.php$ [NC]
RewriteRule ^(.*)$ http://www.example.com [R=301,NC]

First rule redirect example.com to www.example.com.
Second rule is to redirect www.example.com/index.php to www.example.com
the rule works fine for every links. but when any information is posted in the site either through GET or POST method, The submit doesn't work as it needs to be. The submit page just gets refresh instead of taking to the action page.

[edited by: jdMorgan at 11:38 pm (utc) on July 6, 2007]
[edit reason] example.com [/edit]

jdMorgan

2:01 am on Jul 4, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm not sure about your POSTing problem, but the second rule needs to be changed to prevent an 'infinite' rewriting loop. ALso, you should escape literal periods in regular expressions patterns as shown below.
Try fixing this, and then see if you still have the problem with POSTs:

RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) http://www.example.com/$1 [R=301[b],L][/b]
#
RewriteCond [b]%{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php[/b] [NC]
RewriteRule [b]^index\.php$[/b] http://www.example.co[b]m/[/b] [NC,R=30[b]1,L][/b]

THE_REQUEST is the original browser request. Using it prevents index.php from being rewritten to "/" after DirectoryIndex has rewritten "/" to index.php. If you do not take steps to prevent it, then the RewriteRule and the DirectoryIndex directive will interact repeatedly, leading to a loop. Using THE_REQUEST prevents this 'infinite' rewriting loop because it looks at the original browser request, which is not affected by internal rewriting.

THE_REQUEST might look like this:

GET /index.php HTTP/1.1
-or-
POST /mailscript.php HTTP/1.0

Jim

swatej

12:36 pm on Jul 4, 2007 (gmt 0)

10+ Year Member



Hi Jim,

First of all Thank you for your quick reply.

Can you tell me how can i saw that "THE_REQUEST" variable what it carries? Is there any method or function to display that THE_REQUEST variable?

jdMorgan

3:56 pm on Jul 4, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There are several ways to display server variables using server-side includes; See Apache mod_includes. Another way to do it for a simple "quick look" is to use a redirect and put the value into a (fake) query string:

RewriteCond %{THE_REQUEST} (.+)
RewriteRule ^test_request\.html$ http://www.example.com/?THE_REQUEST=%1 [NC,R=301,L]

With this code in place, if you request "example.com/test_request.html" from your server, you will see your browser address bar change to "example.com/?THE_REQUEST=GET /test_request.html HTTP/1.1"

Jim

swatej

9:07 am on Jul 5, 2007 (gmt 0)

10+ Year Member



Hi Jim,

As per your explanation I have implemented following rule on my server but it does not filter "index.php" from the URL. So i feel that rule is not apply on URL.

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php [NC]
RewriteRule ^index\.php$ http://www.example.com/ [NC,R=301,L]

Can you help me out from this problem.

Thanks.

jdMorgan

3:44 pm on Jul 5, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Did you completely flush your browser cache before testing?

Also, as written, the rule will only apply to your "home page", and not to index files in subdirectories.

This code is well-tested, and is one of many variations that have been discussed here in the past. Perhaps one of the other variations [google.com] will be more suited to your needs.

Jim

sc112

6:43 pm on Jul 5, 2007 (gmt 0)

10+ Year Member




This will do it:

RewriteRule ^index\.php$ / [NC,R=301,L]

jdMorgan

7:15 pm on Jul 5, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If the DirectoryIndex directive specifies index.php as the index file to serve when the "/" URL-path is requested, you'll get an "infinite" redirect/rewrite loop with that simple rule; The rule redirects "/index.php" to "/", and then DirectoryIndex rewrites "/" back to /"index.php" -- which will then re-invoke the rule, looping until either the client or the server redirection limit is reached.

It is necessary to test the original client request, so that internal requests for index.php as a result of the DirectoryIndex rewriting function are not redirected.

Jim

sc112

9:02 pm on Jul 5, 2007 (gmt 0)

10+ Year Member



Thanks, Jim, but I'm afraid I don't understand how DirectoryIndex interacts with .htaccess.

It will modify the output of .htaccess and pass it back to .htaccess?

sc112

9:13 pm on Jul 5, 2007 (gmt 0)

10+ Year Member



Let me try again.

With this rule

RewriteRule ^index\.php$ / [NC,R=301,L]

the browser requests /, and DirectoryIndex will append index.php to it if that is the default index file name, resulting in a loop.

But what happens with

RewriteRule ^index\.php$ http://www.example.com/ [NC,R=301,L]

Does not the browser request / too?

I have the former rule going on my website, and it's working as I expect it. I have no idea what default index file is on DirectoryIndex though.

sc112

9:22 pm on Jul 5, 2007 (gmt 0)

10+ Year Member




To be more specific, I have this:

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.(.*)\ HTTP/ [NC]
RewriteRule ^index\.(.*)$ / [NC,R=301,L]

jdMorgan

10:11 pm on Jul 5, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



RewriteRule ^index\.php$ http://www.example.com/ [NC,R=301,L]

Does not the browser request / too?

Let's start with a request for example.com/ and assume that /index.php is in the DirectoryIndex list:
1) Browser requests example.com/
2) DirectoryIndex internally rewrites example.com/ to example.com/index.php
3) Mod_rewrite externally redirects example.com/index.php to example.com/
4) Back to step 1, this is a loop...

In .htaccess, the code must be thought of as being recursive -- Any change to the URL-path will restart processing in order to check for access restrictions and further rewrites that apply to the newly-rewritten URL. Therefore the RewriteRule for /index.php will be invoked and applied to the URL rewritten by DirectoryIndex, unless you put a stop to it by making the redirect conditional upon the /index.php having been directly-requested by the client.

If you have just that RewriteRule with no RewriteCond in your .htaccess file, then you can be sure that your DirectoryIndex list does not include index.php, otherwise you'd be sure to have a loop.

Jim

g1smd

11:08 pm on Jul 6, 2007 (gmt 0)

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



Additionally you should do the "index file on www or non-www" to "non-index on www" redirect first, so that you avoid a redirection chain.

As you have it now, "non-www index" is redirected to "www index" and then your next rule redirects "www index" to "www non-index". That is a "chain". You need to avoid "chained redirects". They will cause you problems.

Change the order so that the first rule picks up all "index files" (whether www or non-www) and redirects them all to "www without the index file filename".

Next, have a second rule that picks up all "non-www" URLs and redirects them to "www". This rule will never see an "index file" URL because the previous rule already redirected them all to "www" (while stripping off the index file filename) and *this* rule is testing only for *non-www* URLs.

sc112

3:38 am on Jul 7, 2007 (gmt 0)

10+ Year Member



So both these rules may result in a loop:

RewriteRule ^index\.php$ / [NC,R=301,L]

RewriteRule ^index\.php$ http://www.example.com/ [NC,R=301,L]

not just the first one?

So if I have the appropriate rewrite condition in place, the first rule will achieve what the OP wants -
filter "index.php" from the URL. Correct?

Thanks Jim for so patiently explaining what happens with the second rule. Do the exact same things happen with the first rule - browser requests /, DirectoryIndex appends index.php...?

The lessons I am getting here are invaluable. I appreciate it very much. It's a fun ride down the slippery slope. :)

Sally

jdMorgan

4:21 am on Jul 7, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



For practical purposes, these two rules are identical:
RewriteRule ^index\.php$ / [NC,R=301,L]
RewriteRule ^index\.php$ http://www.example.com/ [NC,R=301,L]

The only difference is that the first rule relies upon ServerName and UseCanonicalName configuration settings to derive the hostname, because it is not specified in the rule. The second form is preferred, because it is specific and does not rely on these other server settings. But either way, the server will send a redirect response with a full redirection URL, and the client will use that (fully-expanded) URL to re-request what it was looking for.

So to be clear: A redirect is a response to the client that says, "What you are asking for has moved, so ask for it again using this URL." The server then provides the new URL, and this response closes the current HTTP transaction.

The client may or may not then re-request what it wanted to fetch the first time, using the URL provided in the server's redirect response. But this will be an entirely-new HTTP transaction, and the server will have no "memory" whatsoever of the previous HTTP transaction.

(If you are wondering why people use session cookies and session-tracking query strings, that's the reason: HTTP is a stateless protocol, and at the HTTP level, the server has no memory of any past requests. If current or future behaviour is to vary based on past history, then the cookie or query string method must be used to 'remember' that history, and pass it to scripts on the server... Apache itself is unconcerned with the past.)

With a given "index file" named in DirectoryIndex, any attempt in .htaccess to redirect that named index file to "/" will loop unless that redirect is made conditionally-dependent on the client request by using THE_REQUEST in a RewriteCond. I think I explained why this is so in a fairly clear manner above: The value of REQUEST_URI and the URL matched to the RewriteRule pattern will be updated internally by the actions of mod_rewrite and DirectoryIndex; The value of THE_REQUEST can only be changed by the client.

Jim