php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #55208 setting correct SCRIPT_NAME vs PHP_SELF is impossible in certain circumstances
Submitted: 2011-07-14 15:55 UTC Modified: 2018-06-24 04:22 UTC
Votes:13
Avg. Score:4.2 ± 1.0
Reproduced:8 of 10 (80.0%)
Same Version:0 (0.0%)
Same OS:1 (12.5%)
From: loco at andrews dot lv Assigned: cmb (profile)
Status: No Feedback Package: FPM related
PHP Version: 5.3.6 OS: Gentoo Linux (2.6.39-gentoo-r3)
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: loco at andrews dot lv
New email:
PHP Version: OS:

 

 [2011-07-14 15:55 UTC] loco at andrews dot lv
Description:
------------
I am running nginx 1.0.4 with php-fpm and php 5.3.6.

It seems that PHP_SELF has strong dependency on the setting of SCRIPT_NAME.  
When setting SCRIPT_NAME to something, $_SERVER['PHP_SELF'] will contain 
PHP_SELF environment value concatenated with environment value of SCRIPT_NAME.  
If SCRIPT_NAME is not set to anything, then $_SERVER['PHP_SELF'] contains what 
is passed to the environment, however, since SCRIPT_NAME is not set, PHP scripts 
that rely on SCRIPT_NAME will not work. 


Example #1:

accessing URL:  /index.php/some/url

setting server variables:
SCRIPT_NAME /some/url
PHP_SELF /some/url

result:

print $_SERVER['SCRIPT_NAME']; // outputs: "/some/url"  - OK
print $_SERVER['PHP_SELF']; // outputs: "/some/url//some/url" - NOT OK!

Example #2:

SCRIPT_NAME (unset)
PHP_SELF /some/url

result:

print $_SERVER['SCRIPT_NAME'];  // outputs: ""
print $_SERVER['PHP_SELF']; // outputs: "/some/url"

Example #3:

SCRIPT_NAME /some/url
PHP_SELF (unset)

result:

print $_SERVER['SCRIPT_NAME'];  // outputs: "/some/url"
print $_SERVER['PHP_SELF'];  // outputs: ""
---

Bottom line: if configured as demonstrated in the first example, scripts that 
rely on SCRIPT_NAME will work properly, but scripts that require PHP_SELF won't 
work, as it contains the invalid URL;  if configured as shown in the second 
example, scripts that rely on PHP_SELF work properly, but scripts that require 
SCRIPT_NAME, don't work at all;  lastly, if configured as in the third example, 
scripts that use SCRIPT_NAME will work properly, but scripts that use PHP_SELF 
won't work, as PHP_SELF is empty.


Any workaround for this issue?  

When using mod_php with apache, both SCRIPT_NAME and PHP_SELF can be set to the 
same value, and will be interpreted by PHP exactly like they are passed.  
However, in FCGI/PHP-FPM environment I cannot find a way to set them both to the 
same value! 

How is $_SERVER['PHP_SELF'] being constructed?  
Why should it rely on SCRIPT_NAME at all?  
How to set server environment correctly, so it is the same under FastCGI and 
under mod_php / apache 2.2?

Andrejs

Test script:
---------------
<?php

   print '<pre>';
   printf("SCRIPT_NAME: \"%s\"\n", $_SERVER['SCRIPT_NAME']);
   printf("PHP_SELF:    \"%s\"\n", $_SERVER['PHP_SELF']);
   print '</pre>';
?>


Expected result:
----------------
I'd thought PHP_SELF should be possible to define explicitly through the server 
environment, without other variables affecting it's value.  How come is it so that 
in the apache/mod_php mode both SCRIPT_NAME and PHP_SELF contain the same value?  
This does not seem to be possible in the FastCGI environment, at least when using 
php-fpm.  


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2011-07-14 15:57 UTC] fat@php.net
-Status: Open +Status: Assigned -Assigned To: +Assigned To: fat
 [2011-07-17 07:10 UTC] fat@php.net
-Status: Assigned +Status: Feedback
 [2011-07-17 07:10 UTC] fat@php.net
Not enough information was provided for us to be able
to handle this bug. Please re-read the instructions at
http://bugs.php.net/how-to-report.php

If you can provide more information, feel free to add it
to this bug and change the status back to "Open".

Thank you for your interest in PHP.


Hi,

I'm not able to reproduce the problem on my side. Can you please provide the 
following information:

1- nginx configuration (I need the doc_root and the fastcgi and location 
configuration):
  * server {
  *   ...
  *   root ...;
  *   ...
  *   location ~ \.php {
  *     fastcgi_pass 127.0.0.1:9000;
  *     fastcgi_split_path_info ^(.+\.php)(.*)$;
  *     fastcgi_param PATH_INFO $fastcgi_path_info;
  *     fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
  *     include fastcgi.conf;
  *   }
  * }

2- PHP-FPM [pool] configuration
3- ini settings cgi.fix_pathinfo

Thx
++ jerome
 [2011-07-17 08:02 UTC] loco at andrews dot lv
-Status: Feedback +Status: Open
 [2011-07-17 08:02 UTC] loco at andrews dot lv
Hi Jerome,

I hope the information is now sufficient:

### nginx.conf:


# http part with fastcgi configuration:

http {
       fastcgi_pass_request_headers on;
       fastcgi_intercept_errors on;
       fastcgi_buffer_size 4k;
       fastcgi_buffers 1024 4k;

       index index.html;
       
}

# virtual host definition

server {
                listen 80;
                server_name .mysite.com;

                access_log /var/log/nginx/mysite.access_log main;
                error_log /var/log/nginx/mysite.error_log warn;

                root /opt/www/mysite.com;

                location / {
                  index index.php;
                }


                # if the request file name contains one of the below extensions, 
                # serve it directly 
                if ($request_filename ~* \.(css|js|ico|gif|png|bmp|jpe?
g|tiff?)$) {
                  break;
                }

                # otherwise, /index.php handles the request
                rewrite ^(.*)$ /index.php$1 last; 

                location ~ ^(?<SCRIPT_FILENAME>.+\.php)(?<PATH_INFO>.*)$ {
                  include fastcgi_params;
                  fastcgi_param PATH_INFO $PATH_INFO;
                  fastcgi_param PATH_TRANSLATED $document_root$PATH_INFO;
                  fastcgi_param SCRIPT_FILENAME $document_root$SCRIPT_FILENAME;

                  # Attention!  Both PHP_SELF and SCRIPT_NAME must contain the 
same value,
                  # but they don't! 
                  fastcgi_param PHP_SELF $uri;
                  fastcgi_param SCRIPT_NAME $uri;

                  # set SCRIPT_URL/SCRIPT_URI for compatibility
                  fastcgi_param SCRIPT_URL $PATH_INFO;
                  fastcgi_param SCRIPT_URI $scheme://$http_host$PATH_INFO;

                  fastcgi_param PHP_VALUE 
"include_path=$document_root:$document_root/include";
  
                  try_files $SCRIPT_FILENAME =404;
                  fastcgi_pass unix:/var/run/fastcgi/php-fpm.sock;
                }
       }


### php-fpm.conf


;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/php-fpm.log
log_level = debug

emergency_restart_threshold = 7
emergency_restart_interval = 2

;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;

[www]
; pool www

listen = /var/run/fastcgi/php-fpm.sock
;listen.backlog = -1
listen.backlog = 4096
;listen.allowed_clients = 127.0.0.1
listen.owner = www
listen.group = www
;listen.mode = 0660

user = www
group = www

pm = dynamic
pm.max_children = 100
pm.start_servers = 2
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 500
pm.status_path = /fpm-status-1
request_terminate_timeout = 3605

request_slowlog_timeout = 30
slowlog = /var/log/php-fpm-slow.log
catch_workers_output = yes

env[HOSTNAME] = $HOSTNAME


### php.ini

# scripts simply don't work with cgi.fix_pathinfo=0
# nginx reporting "404 File not found" when set to 0
# I don't use cgi.fix_pathinfo actually, since
# I parse SCRIPT_FILENAME and PATH_INFO directly
# in the nginx location block (see nginx.conf)
# with PCRE capturing
cgi.fix_pathinfo=1


## test case: index.php

<?php
  # prints out $_SERVER environment variables
  # please check SCRIPT_NAME and PHP_SELF !
  print '<pre>';
  print_r($_SERVER);
  print '</pre>';
?>
 [2011-07-17 08:47 UTC] fat@php.net
-Status: Open +Status: Feedback
 [2011-07-17 08:47 UTC] fat@php.net
SCRIPT_NAME is already defined in the fastcgi_params file. PHP_SELF doesn't have to be set in nginx as it's made in FPM.

Can you try the following nginx configuration please ?

location ~ ^.+\.php {
  include fastcgi_params;
  fastcgi_split_path_info ^(.+\.php)(.*)$;
  fastcgi_param PATH_INFO $fastcgi_path_info;
  fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;

  vastcgi_param PHP_VALUE "include_path=$document_root:$document_root/include";
  fastcgi_pass unix:/var/run/fastcgi/php-fpm.sock;

  try_files fastcgi_script_name =404;
}

it should be exactly the same as your configuration and it sould work.

thx
++ jerome
 [2011-07-17 09:06 UTC] loco at andrews dot lv
-Status: Feedback +Status: Assigned
 [2011-07-17 09:06 UTC] loco at andrews dot lv
I tried your suggestion and it doesn't set PATH_INFO correctly:

Accessing "http://testsite.com/test/test%20test":

Array
(
    [SCRIPT_FILENAME] => /opt/www/testsite.com/index.php
    [REQUEST_URI] => /test/test%20test
    [PATH_INFO] => 
    [PATH_TRANSLATED] => /opt/www/testsite.com
    [PHP_SELF] => /index.php
    [SCRIPT_NAME] => /index.php
)

PATH_INFO should be set to "/test/test%20test/", i believe?

Andrejs
 [2011-07-17 09:11 UTC] loco at andrews dot lv
> SCRIPT_NAME is already defined in the fastcgi_params file. PHP_SELF doesn't have 
> to be set in nginx as it's made in FPM.

I know, but if I don't set PHP_SELF to $uri, then older PHP scripts that haven't 
been written for FastCGI mode and that require that PHP_SELF refers to the URI, as 
in mod_php/apache case, won't work!  So I *need* to set both SCRIPT_NAME and 
PHP_SELF to $uri actually.

Andrejs
 [2011-07-17 10:55 UTC] fat@php.net
As described in http://php.net/manual/en/reserved.variables.server.php

'PHP_SELF': The filename of the currently executing script, relative to the document root. For instance, $_SERVER['PHP_SELF'] in a script at 
the address http://example.com/test.php/foo.bar would be /test.php/foo.bar

whereas

'SCRIPT_NAME': Contains the current script's path.(without further details).

If we look into the code of differents SAPIs, here what's done:

apache2handler: PHP_SELF is set REQUEST_URI given by apache. So it should be /test.php/foo.bar

cgi/fpm (the code for this part is the same):
  PHP_SELF is set to REQUEST_URI if cgi.fix_pathinfo is 0.
  PHP_SELF is set to SCRIPT_NAME if cgi.fix_pathinfo is 1.

this cgi.fix_pathinfo is a real mess (see https://bugs.php.net/bug.php?id=51983).

I don't really know what to think about all this right now ...
 [2011-07-17 11:42 UTC] loco at andrews dot lv
Jerome, thanks for looking into this issue.


The main trouble is that sometimes, even for FCGI/FPM SAPI both SCRIPT_NAME and 
PHP_SELF must refer to the original URI, and *NOT* to SCRIPT_FILENAME!  This 
behaviour is desired, for example, in order to support older eZPublish or vTiger 
CRM code that relies on PHP_SELF and assumes it contains the original URI, not 
the SCRIPT_FILENAME, which would be /index.php.

So, I thought it would be as simple as this:

fastcgi_param PHP_SELF $uri;
fastcgi_param SCRIPT_NAME $uri;

Apparently, it isn't, and PHP-FPM adjusts these variables by itself, even though
they are submitted via server environment.  I've been experiencing situations 
when PHP_SELF would contain a double path, or that PHP_SELF would contain 
/index.php/, but all I need both to contain is the original URI without 
arguments.  

In addition, when cgi.fix_pathinfo is set to 0, I am not able to access any PHP 
scripts as I get "No input file specified" response in the browser.

 
Please additionally notice that your suggestion with fastgi_split_path_info 
doesn't work, no matter which value cgi.fix_pathinfo is set to, as 
PATH_INFO/PATH_TRANSLATED remain empty.
 [2011-07-17 11:57 UTC] loco at andrews dot lv
>If we look into the code of differents SAPIs, here what's done:
>
>apache2handler: PHP_SELF is set REQUEST_URI given by apache. 
>So it should be /test.php/foo.bar

...unless the URI never contains .php but instead is handled by PHP interpreter 
via Apache rewrite rule:

RewriteRule ^(.*)$ /index.php$1 [L]

And in this case, when accessing URL /foo/bar, both PHP_SELF and SCRIPT_NAME are 
set to "/foo/bar".  This is exactly what I want to achieve in cgi/fpm SAPI in 
nginx, but cannot find any way so far. Best I could come up with is not to 
submit SCRIPT_NAME and submit PHP_SELF equal to $uri.

Andrejs
 [2014-01-07 11:04 UTC] JBlond at gmail dot com
with my last WAMP installations I had to use this getting it working

in apache
	
FcgidFixPathinfo 0


and in php.ini

cgi.fix_pathinfo = 1
 [2016-06-04 01:00 UTC] anrdaemon at yandex dot ru
Should presumable be fixed with https://bugs.php.net/bug.php?id=65641
 [2017-10-24 07:43 UTC] kalle@php.net
-Status: Assigned +Status: Open -Assigned To: fat +Assigned To:
 [2018-06-16 13:44 UTC] cmb@php.net
-Status: Open +Status: Feedback -Assigned To: +Assigned To: cmb
 [2018-06-16 13:44 UTC] cmb@php.net
> Should presumable be fixed with
> https://bugs.php.net/bug.php?id=65641

Is it?
 [2018-06-24 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun Dec 22 01:01:30 2024 UTC