Summary: | SCRIPT_NAME set incorrectly with mod_rewrite | ||
---|---|---|---|
Product: | Apache httpd-2 | Reporter: | Michael Minicki <martel> |
Component: | mod_rewrite | Assignee: | Apache HTTPD Bugs Mailing List <bugs> |
Status: | REOPENED --- | ||
Severity: | normal | CC: | arnaud.lb, julian, michael, taffy-tyler6464 |
Priority: | P2 | ||
Version: | 2.2-HEAD | ||
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | All |
Description
Michael Minicki
2006-07-24 11:08:23 UTC
It seems that if you place the rules under VirtualHost more things are mangled - ie. PATH_INFO. For example, for virtual host of test.nebula.intranet and root dir the variables are initialized as follows: $_SERVER['DOCUMENT_ROOT'] = '/var/www/localhost/htdocs/test' $_SERVER['SCRIPT_FILENAME'] = '/var/www/localhost/htdocs/test/index.php' $_SERVER['REQUEST_URI'] = '/' $_SERVER['SCRIPT_NAME'] = '' $_SERVER['PATH_INFO'] = '/index.html' // OMG! And now with deeper URL where PATH_INFO should be initialized - (SCRIPT_NAME is still wrong): $_SERVER['DOCUMENT_ROOT'] = '/var/www/localhost/htdocs/test' $_SERVER['SCRIPT_FILENAME'] = '/var/www/localhost/htdocs/test/index.php' $_SERVER['REQUEST_URI'] = '/archive/2006/05' $_SERVER['SCRIPT_NAME'] = '' $_SERVER['PATH_INFO'] = '/archive/2006/05' SCRIPT_NAME should be '/index.php' in both of those examples. It still doesn't work on apache 2.0.59. What happens if you run the PHP script as CGI? As a CGI script for URL of: http://test.nebula.intranet/archive/2006/05 values are set to: $_SERVER['DOCUMENT_ROOT'] = string(0) $_SERVER['SCRIPT_FILENAME'] = string(40) /var/www/localhost/htdocs/test/ index.cgi $_SERVER['REQUEST_URI'] = string(16) /archive/2006/05 $_SERVER['SCRIPT_NAME'] = string(40) /var/www/localhost/htdocs/test/index.cgi $_SERVER['PATH_INFO'] = string(16) /archive/2006/05 Should document root be empty? I don't have much experience with PHP working as a CGI script. I have added a handler to <VirtualHost> (AddHandler cgi-script .cgi), added ExecCGI to Options under <Directory> and changed RewriteRule to "RewriteRule ^(.*)$ /index.cgi/$1". The values are the same in every case when run as a CGI. It does not matter if the rule is placed under <VirtualHost>, <Directory> or in .htaccess file. It seems it's a SAPI problem. If CGI gets the expected SCRIPT_NAME, I infer the problem isn't in mod_rewrite, but somewhere within mod_php. That is not an apache product. Please report the bug to its maintainers. FWIW, if you want to tell the mod_php folks how to fix it, this is my guess: (1) SCRIPT_NAME is set by ap_add_cgi_vars in Apache's "util_script". (2) PHP presumably calls that somewhere - unless it's reinvented that wheel. (3) The bug *looks like* a case of PHP calling it too early - specifically *before* the rewrite happened - so of course there was no SCRIPT_NAME. (4) So a fix would be for mod_php to call it later. Or maybe even call it twice, if the early call is unavoidable. Thank you, Nick. I will post your remarks on PHP bug tracker. Here is the way it works: 1) ap_process_http_connection() is called when processing HTTP request; 2) ap_process_http_connection() calls ap_read_request() in order to create request struct; 3) ap_read_request() calls ap_getword_white(), which returns the original URI, not the file used to handle the request (this is how it works here, with PHP 5.2 and Apache 2.0.55); 4) ap_read_request() sets request->uri to the result of ap_getword_white(); 5) finally PHP request handler is called, which in turn calls ap_add_cgi_vars() to get the variables. The way it works is the very same in both cases and it doesn't depend on the place where mod_rewrite directives were set, so I don't see how PHP could call ap_add_cgi_vars() too early or too late. I can reproduce this bug with a simple shell script: ---------- #!/bin/sh cat <<HEADERS Status: 200 Ok Content-Type: text/plain HEADERS export ---------- I added the following the <VirtualHost> to test that: SetHandler cgi-script <Directory /var/www> Options +ExecCGI </Directory> And the rewrite rules: RewriteEngine On RewriteCond %{SCRIPT_FILENAME} !-f RewriteCond %{SCRIPT_FILENAME} !-d RewriteRule ^(.*)$ /test.sh/$1 When the script is executed "export" shows that SCRIPT_NAME is empty. This appends only when the URL is rewritten to a one which has a path info component: Triggers the bug: RewriteRule ^(.*)$ /test.sh/$1 Does not bug: RewriteRule ^(.*)$ /test.sh (In reply to comment #0) > SCRIPT_NAME is passed incorrectly to PHP depending on where you place > the mod_rewrite rule. If it is placed in .htaccess or under <Directory>, the > SCRIPT_NAME is initialized correctly but when you place the same rule under > <VirtualHost> it is an empty string (or any other bogus value). [...] > The rule I'm using is: > > RewriteEngine On > RewriteCond %{SCRIPT_FILENAME} !-f > RewriteCond %{SCRIPT_FILENAME} !-d > RewriteRule ^(.*)$ /index.php/$1 In per-server context, mod_rewrite acts by default as an URI-to-filename translator. If you add the [PT] flag, mod_rewrite will copy the rewrite result back to r->uri and does not map the request to the filesystem, i.e. another URI-to-filename translator will map the request to the filesystem. In that case (if you use the PT-flag) SCRIPT_NAME seems to be set correctly. BTW: I'm wondering how your conditions will work in per-server context since w/o a URI-to-filename translation SCRIPT_FILENAME cannot contain the physical path of the request, which is needed in oder to check for existing files or dirs. See the docs bug 16402. Using apache 2.2.10 (but I think this problem is in trunk, too): - If e.g. php is used as a module Original request_uri /bar ; rewrite result /foo.php In that case (mod_php), and if there is no internal redirect, SCRIPT_NAME contains in my environment w/o the PT-flag the value of r->uri (/bar) and with the PT-flag /foo.php. ENV PATH_INFO - rewrite result /foo.php/path - is '/path' and works correct with and w/o the PT-flag. - If a directive is used which triggers an internal redirect - such as php cgi setup via the Action directive, SCRIPT_NAME will contain the value of the cgi prog. Original request_uri /bar ; rewrite result /foo.php ; the result of the Action directive is r->uri /php-script/php with path_info /bar: ScriptAlias /php-script/ "/path/to/php/" AddHandler cgi-php .php Action cgi-php /php-script/php --> SCRIPT_NAME=/php-script/php (correct with and w/o PT-flag) W/o the PT-Flag, PATH_INFO contains /bar (a subrequest for /bar will pass /foo.php to the cgi prog), REDIRECT_URL contains the original request_uri /bar, too (IMHO correct, because mod_rewrite doesn't change r->uri w/o the PT-flag, the only way Aliases can work). But that means that there is no ENV which points to the result of mod_rewrite (/foo.php). With the PT-flag set, PATH_INFO and REDIRECT_URL both contain /foo.php, which is correct. - Directly executed CGIs such as /cgi/printenv.pl with a config like (not Alias'd nor ScriptAlias'd in another way) <Directory "/var/www/cgi"> Options +ExecCGI AddHandler cgi-script .pl </Directory> r->uri: /bar ; rewrite result /cgi/printenv.pl W/o the PT-flag: regardless if PATH_INFO was specified, SCRIPT_NAME contained /bar. With the PT-flag: regardless if PATH_INFO was specified, SCRIPT_NAME contained /cgi/printenv.pl I tried to reproduce an empty SCRIPT_NAME with a rule in per-servr context, but that seems to fail in my environment, I don't know why. Instead, SCRIPT_NAME contained the unchanged r->uri of the initial request if there was no internal redirect or the PT-flag was not set. I think this is correct because mod_rewrite acts in per-server context w/o specifying the PT-flag like an Alias. To my understanding, SCRIPT_NAME represents the physical web view and if it's Alias'd it seems to me complicated if not impossible to get a physical web view. Hi, this is still a problem 15 years later. |