setting in the .htaccess

RewriteEngine On
RewriteRule ^b\.html$ a.html [L]
RewriteRule ^a\.html$ b.html [L]

but got in dead-loop forever unless httpd stop.
the rewrite.log logged called eachother interval:

- - [07/Apr/2005:13:15:47 --0400] [][rid#81c3498/initial] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81caef8/initial/redir#1] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /a.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81cb750/initial/redir#2] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81cc650/initial/redir#3] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /a.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81cd488/initial/redir#4] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81ce438/initial/redir#5] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /a.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81cf228/initial/redir#6] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d0370/initial/redir#7] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /a.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d1278/initial/redir#8] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d24b8/initial/redir#9] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /a.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d3510/initial/redir#10] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d4878/initial/redir#11] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /a.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d5ad8/initial/redir#12] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d7010/initial/redir#13] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /a.html [INTERNAL REDIRECT]
- - [07/Apr/2005:13:15:47 --0400] [][rid#81d8778/initial/redir#14] (1) [per-dir /usr/local/apache/htdocs/app/] internal redirect with /b.html [INTERNAL REDIRECT]

what is my wrong, isn't [L] means the last one to match, then quick out of this request?

Frederick

Dani AI

Generated

As rightly discovered, the rules are looping because in per-directory context (.htaccess) a successful rewrite can cause an internal redirect and the rewritten URI is fed back into the rewrite engine. The [L] flag only stops the current pass; it does not prevent a new pass after an internal redirect. See the Apache rewrite flags and mod_rewrite overview for the engine/round behavior. (httpd.apache.org)

Practical ways to break this kind of loop (pick one that matches the intended UX):

  • Make the first change an external redirect so the client issues a new request, and guard that redirect so it only triggers on the original client request.
  • Match the original HTTP request line with %{THE_REQUEST} or check that %{ENV:REDIRECT_STATUS} is empty (only true for the initial pass).
  • If running Apache 2.4+, use the [END] flag to stop further per-directory processing after the rule.

Example (pattern only — adapt paths/flags for the actual intent):

# only trigger on the original client request
RewriteCond %{THE_REQUEST} "^[A-Z]+\ /b\.html\ HTTP/"
RewriteRule ^b\.html$ /a.html [R=302,L]

# internal rewrite for friendly URL
RewriteRule ^a/?$ a.html [L]

These techniques are documented in the mod_rewrite reference and in community examples showing REDIRECT_STATUS usage; [END] behavior is explained on the flags page. (documentation.help)

Debugging tips: enable rewrite tracing (for example LogLevel alert rewrite:trace3) and watch the error log to see each pass and internal redirect; this makes it easy to confirm which rule fired and why. If possible, put canonical redirects in the vhost/server config rather than .htaccess to avoid per-directory re-injection. (documentation.help)

Summary: the behavior is expected; the fix is to make the redirect conditional on the original request (or use [END] on modern Apache), or to change the flow so there is not a mutual A→B and B→A rewrite.

the infinit loop seems caused by the misunderstanding of rewriterules: as long as it rewrited, it will run through the chains again, not quit only

c
d

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.