How to get rid of Rewrite loop error in htaccess file ? Apache mod-rewite tutorial

RewriteLoop error in htaccess

RewriteLoop is when a file or URL path infinitely maps to itself using RewriteRule directive in htaccess. Your webserver returns one of the following 500 error status when this error happens :

HTTP Error 500

The request exceeded the maximum 10 internal redirects.

or

Too many redirects. The server is unable to complete the request.

If you check you error.log file you will see a 500 error message that looks something like :

[client 00.0.0.1:0000] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use ‘LimitInternalRecursion’ to increase the limit if necessary. Use ‘LogLevel debug’ to get a backtrace.

What causes RewriteLoop?

Generally it happens when you rewrite a file or URL path to itself or when there are unconditional rules in htaccess with (.*) pattern. Let’s see some code examples to better understand the loop behavior in mod-rewite.

The following RewriteRule will cause an infinite loop error if you use it in your htaccess:


RewriteEngine on

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

The rule above rewrites all requests to index.php but using this rule in htaccess you will get the infinite loop error if you visit any URL path on your server.

Why does the above rule result in RewriteLoop error?
Because the Rule runs unconditionally. The pattern ^(.*)$ in the above rule also matches the destination path /index.php and keeps rewriting the request in a never ending loop /foobar =>index.php =>index.php =>index.php…..
With the above rule if you visit

http://yoursite.com/foobar

The rule’s pattern ^(.*) will match the request /foobar and rewrite it to /index.php but since htaccess file is read by server on each request , to load the destination file index.php your server will again read the htaccess file and this time /index.php matches the pattern and rewrites to itself.
Unlike server.config, htaccess is read by server multiple times in order to complete the request. So for example with the above RewriteRule if you visit /anyURI the rule will rewrite your request to /index.php . The processing doesn’t end here. The server will again read the htaccess in order to serve the /index.php URI and the rewriting process keeps going on untill there is no matching pattern.

How to quick fix the Rewrite loop ?

We will take the above example here. To fix rewrite loop error on :


RewriteEngine on

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

You can either use a RewriteCond or END flag insted of L. Keep in mind that the END flag only works on apache versions 2.4 or later . On earlier versions you can use RewriteCond directive to solve the looping problem.
Using RewriteCond to fix the Rewrite loop


RewriteEngine on

RewriteCond %{REQUEST_URI} !index.php [NC]
RewriteRule ^(.*)$ /index.php [L]

The condition RewriteCond %{REQUEST_URI} !index.php [NC] prevents the destination path /index.php from matching the rule’s pattern.
You can also get rid of the loop using a regex pattern that excludes the destination path. The main point here is to exclude the path we are rewriting to. If you don’t want to use RewriteCond then you can simply use :


RewriteEngine on

RewriteRule ^((?!index.php).*)$ /index.php [L]

The pattern ^((?!index.php).*)$ will match all URIs except the destination index.php .

Using END flag to avoid the rewrite loop

As I alrealdy mentioned the END flag is supported only on Apache 2.4 and newer . If your apache version supports it you can use END flag in RewriteRule to terminate the loop. Replace all L flags you are using on RewriteRule with END.


RewriteEngine on

RewriteRule ^(.*)$ /index.php [END]

A global workaround for fixing Rewrite Loop

If your htaccess contains multiple rules then it can be a bit hard to find and fix the rule causing infinite loop error . In that case you can the following Anti loop protection rule at the top of your htaccess:


RewriteEngine on

RewriteCond %{ENV_REDIRECT_STATUS} ^200$
RewriteRule ^ - [L]

This will fix the Rewrite loop error in your htaccess file. The above rule will terminate all internal rewrite loop and redirections. It prevents other rules in your htaccess from executing when the second rewrite cycle starts on the server.
Now you can route all requests for your site to index.php without any errors :



RewriteEngine on
#anti loop protection
RewriteCond %{ENV_REDIRECT_STATUS} ^200$
RewriteRule ^ - [L]
#rewrite all to index.php
RewriteRule ^(.*)$ /index.php [L]

Hope this was helpful. Thanks for reading this.

Leave a Reply

Your email address will not be published. Required fields are marked *