Enabling Multiviews
MultiViews is an Apache per-directory option, which is not natively supported by LiteSpeed Web Server at the time of this writing. However, it can be achieved through the rewrite rules.
How Apache Multiviews Works
The effect of MultiViews is as follows: if the server receives a request for /some/dir/foo
, if some/dir
has MultiViews enabled, and /some/dir/foo
does not exist, then the server reads the directory looking for files named foo.*
, and effectively fakes up a type map which names all of those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client's requirements.
MultiViews may sometimes cause a very strange rewrite problem. When you turn on the rewrite log, you might see something like the following, which indicates “MultiViews” is enabled:
[perdir /var/www/] add path info postfix: /var/www/product.php -> /var/www/product.php/Test__Test.php [perdir /var/www/] strip per-dir prefix: /var/www/product.php/Test__Test.php -> product.php/Test__Test.php [perdir /var/www/] applying pattern '^([0-9]+)/([^/]+)\.php$' to uri 'product.php/Test__Test.php' [perdir /var/www/] add path info postfix: /var/www/product.php -> /var/www/product.php/Test__Test.php [perdir /var/www/] strip per-dir prefix: /var/www/product.php/Test__Test.php -> product.php/Test__Test.php [perdir /var/www/] applying pattern '^prodotto/([^/]+)\.php$' to uri 'product.php/Test__Test.php' [perdir /var/www/] add path info postfix: /var/www/product.php -> /var/www/product.php/Test__Test.php [perdir /var/www/] strip per-dir prefix: /var/www/product.php/Test__Test.php -> product.php/Test__Test.php [perdir /var/www/] applying pattern '^prodotto/([^/]+)\.php?id=([0-9]+)$' to uri 'product.php/Test__Test.php' [perdir /var/www/] add path info postfix: /var/www/product.php -> /var/www/product.php/Test__Test.php [perdir /var/www/] strip per-dir prefix: /var/www/product.php/Test__Test.php -> product.php/Test__Test.php [perdir /var/www/] applying pattern '^c/([^/]+)/([^/]+)\.php$' to uri 'product.php/Test__Test.php' [perdir /var/www/] pass through /var/www/product.php
The problem here is that the request is being modified by MultiViews, substituting /product/
with /product.php
and never triggering the mod_rewrite rule.
Generally, to avoid such confusion, we don't recommend using the MultiViews function.
Real Life Example Using pathinfo
Our customer is using an old jshop which works on Apache. After switching to LSWS, it always redirects to the homepage. There is a very very long rewrite in .htaccess, hence it is not easy to identify what is wrong.
We enable the rewrite log for Apache and LSWS, but it still is not easy to identify the problem.
The following is from the Apache rewrite log:
[Wed Sep 12 05:46:58.807252 2018] [rewrite:trace3] [pid 679517:tid 140344885401344] mod_rewrite.c(483): [client 175.156.215.157:58596] 175.156.215.157 - - [www.example.com/sid#7fa4b3f8b5d8][rid#7fa460006a60/initial] [perdir /home/user1/public_html/] add path info postfix: /home/user1/public_html/s.php -> /home/user1/public_html/s.php/2/menus-reading-michelin-star-restaurant-berkshire, referer: https://www.example.com/ [Wed Sep 12 05:46:58.807300 2018] [rewrite:trace3] [pid 679517:tid 140344885401344] mod_rewrite.c(483): [client 175.156.215.157:58596] 175.156.215.157 - - [www.lortolan.com/sid#7fa4b3f8b5d8][rid#7fa460006a60/initial] [perdir /home/user1/public_html/] strip per-dir prefix: /home/user1/public_html/s.php/2/menus-reading-michelin-star-restaurant-berkshire -> s.php/2/menus-reading-michelin-star-restaurant-berkshire, referer: https://www.example.com/
We determine that MultiViews is the root cause for the rewrite problem.
If the following MultiViews option were to be disabled in .htaccess, Apache wouldn't work anymore:
Options +MultiViews
Why does Apache work but LSWS doesn't? Apache supports the above MultiViews while LSWS does not. So how do we make MultiViews work on LSWS?
If a site has a URI that uses pathinfo, here's how the redirection should work:
/topic/Office/Work ==> /topic.php/Office/Work /update/Office/Work ==> /update.php/Office/Work/topic-> /topic.php
The following is a code example to implement Multiviews that uses pathinfo through rewrite rules for LSWS:
# Multiviews example code...use this in an .htaccess file RewriteEngine On RewriteCond %{REQUEST_URI} !.+php* RewriteCond %{DOCUMENT_ROOT}/$1\.php -f RewriteRule ^([^/]+)/?(.*)$ $1.php/$2 [L]
We added the above code, and now LSWS works fine for this particular site.
Multiple Language Example
The following is how it's set up with Apache Multiviews:
Options +MultiViews AddLanguage de .de AddLanguage en .en
We can get the same effect with LSWS and the following rewrite rules:
AddType text/html .en AddType text/html .de SetEnvIf Accept-Language ^de LANG=.de SetEnvIf Accept-Language ^en LANG=.en SetEnvIf LANG ^$ LANG=.de RewriteEngine on RewriteCond %{REQUEST_URI} !%{ENV:LANG}$ RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-l RewriteRule ^(.*)$ $1%{ENV:LANG} [L,QSA]