URL Rewrite + PHP LSAPI hate the $_SERVER array

#1
Long story short I installed LiteSpeed Web Server on one of my boxes for testing, evaluation, and benchmarking purposes. Some of my tests use a Drupal installation installed here: $DOC_ROOT/drupal.

The used rewrite rule is pretty straightforward:

RewriteCond %{REQUEST_URI} ^/drupal
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/drupal/(.+)$ /drupal/index.php?q=$1 [L,QSA]
At least this is what I though, but for 15 minutes I felt like a complete moron that isn't able to write a simple rewrite rule. Wait, actually the rewrite rule is fine, as the server log says: drupal/node/1 goes to drupal/index.php?q=node/1. Placing a small debug script that replaces Drupal's front controller confirms that $_GET['q']/$_REQUEST['q'] is indeed node/1. However, all the static content throws 404 errors. All the paths to the static content are brokenly generated by Drupal.

Instead of:
drupal/modules/node/node.css?3
I got:
drupal/node/modules/node/node.css?3
Since none of my previous setups have this issue, the reason was pretty obvious: the web server isn't setting properly some parameters that PHP receives. Educated guess: $_SERVER.

Instead of $_SERVER['SCRIPT_NAME'] = '/drupal/index.php' and $_SERVER['PHP_SELF'] = '/drupal/index.php', LSWS + Rewrite + PHP LSAPI insist on $_SERVER['SCRIPT_NAME'] = '/drupal/node/1'; and $_SERVER['PHP_SELF'] = '/drupal/node/1';. Actually the SCRIPT_NAME is the piece that actually breaks Drupal.

I could "fix" it with some ini settings wizardry (auto_prepend_file) which executes this script for every PHP request:

<?php
$proper_var = str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']);
$_SERVER['PHP_SELF'] = $proper_var;
$_SERVER['SCRIPT_NAME'] = $proper_var;
Configuration:
Ubuntu Server 10.04 LTS amd64
LiteSpeed Web Server 4.0.14 Standard (x86 + Ubuntu's ia32-libs)
PHP 5.3.2/Zend Server 5.0.1 + PHP LSAPI 5.3.1

Just to be clear (if you actually "try this at home"): Zend Server/Zend Server CE includes a source package that contains PHP patches not available into the upstream PHP 5.3.2 as Zend says. Creating a binary compatible SAPI (including LSAPI) is a trivial task (if you manually pick all the dependencies, not too many), but the Zend extensions (Data Cache, Optimizer+) may or may not work. Data Cache works only with mod_php (software switch, had some rough discussions with the Zend guys about the lack of support for FastCGI), while Optimizer+ doesn't work beyond mod_php, FastCGI. This obviously shouldn't break LSAPI in any way as the $_SERVER superglobal is set by the web server.

Later edit: the other PHP hog, besides Drupal (great for benchmarking), called Joomla also suffers because of this specific behavior of the web server.
 
Last edited:

mistwang

LiteSpeed Staff
#2
In order to exactly match Apache's behavior, those variables are set differently depends on how your rewrite rule was configured, at vhost level? or at context/directory/.htaccess level?

I think you set the rewrite rule at vhost level, you can try configuring the rules another way.
 
#3
The rewrite is configured at virtual host level. Indeed, the .htaccess and the virtual host configuration produces different results under Apache. As I am not into the .htaccess, since it adds server overhead plus the lack of using shared hosting at my company, I tried to use the virtual host configuration for this particular setup. Maybe LiteSpeed does a better job when using .htaccess, so far this is untested.

However, a plain old <Location> directive works as expected under Apache if I have to use a different rewrite set for a particular subdirectory, while the "RewriteCond %{REQUEST_URI} ^/something" hack for LiteSpeed produces this kind of dumb behavior. I understand that this comes from Apache, thus the resolution most probably is "won't fix". And yes, I already tried to use the configuration lines for rewrite from the Apache's virtual host file, but the <Location> isn't doing anything. Obviously, I could replicate the same issue under LiteSpeed Enterprise. Also, placing the above rewrite rule (with minor changes) within a <Directory> block, fixes the issue under Apache. Obviously, the <Directory> configuration isn't supported by LiteSpeed rewrite support.

FastCGI instead of LSAPI also works as expected. I tried with both a standard php-cgi spawned by LiteSpeed and the external daemon, php-fpm. I'll make an educated guess and say that spawn-fcgi+daemontools would work as expected as well.

Long story short: mod_rewrite / LSWS rewrite + mod_php / PHP LSAPI are affected by this bug. Apache's bug, but still a bug as SCRIPT_NAME and PHP_SELF should always point to a real php file, not to the location previous to the URL rewrite process. FastCGI works as expected, always, under both Apache+mod_fcgid and LiteSpeed + php-cgi / php-fpm. I guess I should bug the Apache guys to fix it in order to have a fix in LiteSpeed.
 

NiteWave

Administrator
#4
Obviously, the <Directory> configuration isn't supported by LiteSpeed rewrite support.
you can define a context under a vhost.

in this drupal case, define a static context:
Code:
URI: /drupal/
Location: drupal
Accessible:Yes
Rewrite Rules:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?q=$1 [L,QSA]
my simple test on a drupal 6.16 new installation, looks working.

in above testing .htaccess is disabled.

when enable .htaccess, the default drupal .htaccess under $docroot/drupal looks working well without any change.
 
Top