The Rewrite Rule [L] Flag

There is a minor difference in the way LiteSpeed Web Server and Apache treat the [L] flag in rewrite rules. The [L] flag (“L” stands for “Last”) causes mod_rewrite to stop processing the rule set. There are two ways to interpret this:

  1. In most contexts, including LiteSpeed Web Server, this means that if the rule matches, no further rules will be processed. LSWS exits from the rewrite completely to avoid looping.
  2. In Apache, [L] means that if the rule matches, no further rules will be processed in the current iteration. Apache does not exit from the rewrite rule completely, and so there is a possibility of looping.

TL;DR: The ruleset after an [L] flag may still be processed by Apache on a subsequent iteration, but that is not true with LSWS and most other contexts.

In Apache 2.4 and above, an alternative flag, [END], has been introduced to terminate not only the current round of rewrite processing, but to prevent any subsequent rewrite processing from occurring in .htaccess. In other words, the [L] flag in LSWS is equivalent to [END] in Apache 2.4.

You may need to tweak your Apache rule set to work with LiteSpeed.

Tips

Changing the ruleset order may resolve the issue.

Try using only one [L] in your ruleset instead of multiple [L]s.

Sometimes the situation may be more complicated. The user may have some rules inherited from an older Apache version, such as Apache 2.2, with a lot of [L]s. It may not be easy to make it work for both Apache and LiteSpeed at the same time by simply changing the rule order or removing some [L]s. You may try to make the ruleset work for LiteSpeed, but that may break it for Apache. In such cases, we would recommend leaving the Apache ruleset untouched, and enclose it with <IfModule !litespeed> … </IfModule>. Then create a new ruleset for LSWS enclosed with <IfModule litespeed> … </IfModule> as a workable alternative.

Writing rewrite rules may require a deep understanding of how the rewrite engine works and a talent for coding. The end user's rule may be complicated. They may have inherited a lengthy ruleset from a legacy Apache version, or maybe they are not following best practices, or perhaps they even involve some mistake. The final goal is to tweak the existing rules set to work with both LiteSpeed and Apache as quickly as possible, and not to worry about converting the ruleset into a piece of art.

Example 1: Change the Order of Rules

Let's say you have this for Apache:

RewriteEngine On
RewriteRule ^([^\.]+)$ $1.php [NC,L]                                                
RewriteRule plato-(.*)- plato_hizmet.php?plato=$1              
RewriteRule isik-(.*)- isik_hizmet.php?isik=$1               
RewriteRule hizmetler-(.*)- hizmetler.php?Git=$1             
RewriteRule ekipmanlar-(.*)- ekipmanlar.php?urun=$1

When the second line RewriteRule ^([^\.]+)$ $1.php [NC,L] is matched, LSWS will exit the rewrite and won't process any rules below, while Apache may continue to process the rest of the rules at the next iteration. Changing the rule order so the [L] is on the last line should cause both Apache and LSWS to treat this ruleset the same way.

RewriteEngine On
RewriteRule plato-(.*)- plato_hizmet.php?plato=$1              
RewriteRule isik-(.*)- isik_hizmet.php?isik=$1               
RewriteRule hizmetler-(.*)- hizmetler.php?Git=$1             
RewriteRule ekipmanlar-(.*)- ekipmanlar.php?urun=$1
RewriteRule ^([^\.]+)$ $1.php [NC,L]    

Example 2: Use Only One [L] Instead of Multiple

Let's say you have this ruleset:

RewriteEngine On
RewriteBase /
RewriteRule ^es/(.*)$ /$1 [L]
RewriteRule ^reservar\.html(.*)$ reservar.php [L]

Under Apache:

  1. A visitor hits the URL http://example.com/es/reservar.html .
  2. The web server recognizes the pattern ^es/(.*)$ from the first rewrite rule and the request is internally redirected to /reservar.html.
  3. /reservar.html also matches the rule ^reservar\.html(.*)$ and is redirected to reservar.php.
  4. The contents of this latest file (reservar.php) is sent to the visitor.

Under LiteSpeed Web Server:

  1. A visitor hits the URL http://example.com/es/reservar.html .
  2. The web server recognizes the pattern ^es/(.*)$ from the first rewrite rule and the request is internally redirected to /reservar.html.
  3. Processing stops at the first [L] (RewriteRule ^es/(.*)$ /$1 [L]) and never reaches the forth line at all.

If you want LSWS to process these rules with the same results as Apache, you can update them to use only one [L]:

RewriteEngine On
RewriteBase /
RewriteRule ^es/(.*)$ /es/$1 [NC]
RewriteRule ^/es/reservar.html(.*)$ reservar.php [L]

Example 3: Use "<IfModule litespeed> ... </IfModule>" for Different Rules

Change this:

RewriteCond %{REQUEST_URI} !\..*
RewriteRule (.*)/+(.*) $1_$2 [L]
RewriteCond %{REQUEST_URI} !\..*
RewriteRule (.*)/+(.*)/+(.*) $1_$2_$3 [L]
RewriteCond %{REQUEST_URI} !\..*
RewriteRule general/(.*) general_$1 [L]
RewriteCond %{REQUEST_URI} !\..*
RewriteRule sitebuilder/(.*) sitebuilder_$1 [L,PT]
RewriteCond %{REQUEST_URI} !\..*
RewriteRule html-editor/(.*) html-editor_$1 [L]
RewriteCond %{REQUEST_URI} !\..*
RewriteRule presenter/(.*) presenter_$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !\..*
RewriteCond %{REQUEST_URI} !\/$
RewriteRule ^(.*)$ $1.php [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !\.php
RewriteCond %{REQUEST_URI} \..*
RewriteRule (.*) http://example.com/$1 [R=301,L]

To this:

RewriteCond %{REQUEST_URI} !\..*
<IfModule LiteSpeed>
RewriteRule (.*)/+(.*) $1_$2
</IfModule>
<IfModule !LiteSpeed>
RewriteRule (.*)/+(.*) $1_$2 [L]
</IfModule>
RewriteCond %{REQUEST_URI} !\..*
<IfModule LiteSpeed>
RewriteRule (.*)/+(.*)/+(.*) $1_$2_$3
</IfModule>
<IfModule !LiteSpeed>
RewriteRule (.*)/+(.*)/+(.*) $1_$2_$3 [L]
</IfModule>
RewriteCond %{REQUEST_URI} !\..*
<IfModule LiteSpeed>
RewriteRule general/(.*) general_$1
</IfModule>
<IfModule !LiteSpeed>
RewriteRule general/(.*) general_$1 [L]
</IfModule>
RewriteCond %{REQUEST_URI} !\..*
<IfModule LiteSpeed>
RewriteRule sitebuilder/(.*) sitebuilder_$1
</IfModule>
<IfModule !LiteSpeed>
RewriteRule sitebuilder/(.*) sitebuilder_$1 [L,PT]
</IfModule>
RewriteCond %{REQUEST_URI} !\..*
<IfModule LiteSpeed>
RewriteRule html-editor/(.*) html-editor_$1
</IfModule>
<IfModule !LiteSpeed>
RewriteRule html-editor/(.*) html-editor_$1 [L]
</IfModule>
RewriteCond %{REQUEST_URI} !\..*
<IfModule LiteSpeed>
RewriteRule presenter/(.*) presenter_$1
</IfModule>
<IfModule !LiteSpeed>
RewriteRule presenter/(.*) presenter_$1 [L]
</IfModule>

Example 4: Use "<IfModule litespeed> ... </IfModule>" for Different Blocks

Change this:

RewriteEngine On
RewriteCond	%{REQUEST_FILENAME}	-f
RewriteRule	^(.*)\.page$	page.php?__page=$1	[L,QSA]
RewriteCond	%{REQUEST_FILENAME}	-f
RewriteRule	^pics/(.*)	pic.php?name=$1		[L,QSA]
RewriteRule	^index\.(html|shtml|htm)$	index.php		[L,QSA]
RewriteRule	^products-(.*)\.html$	products.page?c=$1	[L,QSA]
RewriteRule	^product-(.*)\.html$	product.page?id=$1	[L,QSA]
RewriteRule	^(specials|about_us|links|order_complete|view_cart|checkout).html$	$1.page		[L,QSA]

To this:

<IfModule !litespeed>
RewriteEngine On
RewriteCond	%{REQUEST_FILENAME}	-f
RewriteRule	^(.*)\.page$	page.php?__page=$1	[L,QSA]
RewriteCond	%{REQUEST_FILENAME}	-f
RewriteRule	^pics/(.*)	pic.php?name=$1		[L,QSA]
RewriteRule	^index\.(html|shtml|htm)$	index.php		[L,QSA]
RewriteRule	^products-(.*)\.html$	products.page?c=$1	[L,QSA]
RewriteRule	^product-(.*)\.html$	product.page?id=$1	[L,QSA]
RewriteRule	^(specials|about_us|links|order_complete|view_cart|checkout).html$	$1.page		[L,QSA]
</IfModule>
<IfModule litespeed>
RewriteRule     ^index\.(html|shtml|htm)$       index.php
RewriteRule     ^products-(.*)\.html$   products.page?c=$1
RewriteRule     ^product-(.*)\.html$    product.page?id=$1
RewriteRule     ^(specials|about_us|links|order_complete|view
RewriteCond     %{REQUEST_FILENAME}     -f
RewriteRule     ^pics/(.*)      pic.php?name=$1         [L,QSA]
RewriteCond     %{REQUEST_FILENAME}     -f
RewriteRule     ^(.*)\.page$    page.php?__page=$1      [L,QSA] 
</IfModule>       
  • Admin
  • Last modified: 2019/03/19 15:32
  • by Lisa Clarke