Стандарт CGI (RFC 3875) не предусматривает ни SCRIPT_FILENAME, ни
DOCUMENT_ROOT; однако предусматривает переменные PATH_INFO,
SCRIPT_NAME и PATH_TRANSLATED:
The PATH_INFO variable specifies a path to be interpreted by the CGI
script. It identifies the resource or sub-resource to be returned
by
the CGI script, and is derived from the portion of the URI path
hierarchy following the part that identifies the script itself.
The PATH_TRANSLATED variable is derived by taking the PATH_INFO
value, parsing it as a local URI in its own right, and performing
any
virtual-to-physical translation appropriate to map it onto the
server's document repository structure.
[...]
For example, a request such as the following:
http://somehost.com/cgi-bin/somescript/this%2eis%2epath%3binfo
would result in a PATH_INFO value of
/this.is.the.path;info
An internal URI is constructed from the scheme, server location and
the URL-encoded PATH_INFO:
http://somehost.com/this.is.the.path%3binfo
This would then be translated to a location in the server's
document
repository, perhaps a filesystem path something like this:
/usr/local/www/htdocs/this.is.the.path;info
The value of PATH_TRANSLATED is the result of the translation.
Исходная ситуация, из которой это все зародилась, понятная - запуск
cgi-приложений с адресами вида /cgi-bin/mybinary/extra-data.
В контексте же php может быть два мнения о значениях
- На мой взгляд, соответствующее RFC и общепринятым практикам (см.
nginx fastcgi_split_path_info):
http://domain.tld/some/script.php/extra
=> PATH_INFO = /extra; SCRIPT_FILENAME = PATH_TRANSLATED = $root/
some/script.php
- PATH_TRANSLATED = /path/to/php-cgi, реальный относительный путь
целиком - в PATH_INFO (и тогда, не имея еще и нестандартного
DOCUMENT_ROOT, мало понятно, как получить полный путь к скрипту; судя
по всему, для этого в php.ini есть doc_root).
Оригинальный sapi/cgi/cgi_main.c содержит (при включенном
fix_pathinfo) жуткую с точки зрения производительности "угадайку" -
понятно, что это сделано для совместимости с различными веб-серверами,
у каждого из которых своя трактовка RFC 3875. В случае с fpm, такой
оверхед, мягко говоря, излишен.
Обычно fix_pathinfo с fpm-ом отключают; однако, там алгоритм совсем уж
примитивный, и стандартные fastcgi-конфиги, бывает, приходится
подправлять, добавляя SCRIPT_FILENAME или PATH_TRANSLATED = $root
$fastcgi_script_name.
В моем патче, который я публиковал в соседней ветке (про fpm в php
svn), помимо прочего, есть своя реализация init_request_info(), со
таким алгоритмом (псевдокод):
get_script_filename(env) {
if (defined(env.SCRIPT_FILENAME))
return env.SCRIPT_FILENAME;
else if (defined(env.SCRIPT_NAME, env.DOCUMENT_ROOT))
return env.DOCUMENT_ROOT + env.SCRIPT_NAME;
else if (defined(env.PATH_TRANSLATED))
return env.PATH_TRANSLATED;
else
return ERROR;
}
В случае с типичными конфигурациями nginx это будет работать (в
отличие, кстати, от оригинала с fix_pathinfo = false, будет работать
со стандартным etc/nginx/fastcgi_params без SCRIPT_FILENAME), но
сейчас подумал, что я, возможно, поспешил, проверив только на nginx-
е.
Хотелось бы услышать от использующих lighttpd/zeus/etc, подходит ли
такая схема.