Skip to content

fix $_SERVER['SCRIPT_NAME'], 'PHP_SELF', and 'PATH_INFO' #2317

Open
henderkes wants to merge 8 commits intomainfrom
fix/script_name
Open

fix $_SERVER['SCRIPT_NAME'], 'PHP_SELF', and 'PATH_INFO' #2317
henderkes wants to merge 8 commits intomainfrom
fix/script_name

Conversation

@henderkes
Copy link
Copy Markdown
Contributor

@henderkes henderkes commented Mar 27, 2026

fixes #2274 (comment)

apache/nginx/caddy pass PHP_SELF as SCRIPT_NAME + PATH_INFO, but our PATH_INFO wasn't working because our matcher stripped the rest of the path.

request url: localhost/index.php/en

# was non-worker:
SCRIPT_NAME: /index.php
PATH_INFO: 
PHP_SELF: /index.php
REQUEST_URL: /en

# was fastcgi:
SCRIPT_NAME: /index.php
PATH_INFO:  /en
PHP_SELF: /index.php/en
REQUEST_URL: /en

# was php_server worker
SCRIPT_NAME:
PATH_INFO:
PHP_SELF: /en
REQUEST_URL: /en

# now is always:
SCRIPT_NAME: /index.php
PATH_INFO: /en
PHP_SELF: /index.php/en
REQUEST_URL: /en

…rkers

apache passes PHP_SELF as SCRIPT_NAME + REQUEST_URL, but the docs say it's the same as SCRIPT_NAME and that's how Caddy+fpm behave too
@henderkes henderkes requested a review from AlliBalliBaba March 27, 2026 15:49
@henderkes henderkes marked this pull request as ready for review March 27, 2026 15:49
@henderkes henderkes marked this pull request as draft March 27, 2026 16:26
@henderkes henderkes changed the title fix $_SERVER['SCRIPT_NAME'] and $_SERVER['PHP_SELF'] in php_server workers fix $_SERVER['SCRIPT_NAME'], 'PHP_SELF', and 'PATH_INFO' Mar 27, 2026
@henderkes henderkes marked this pull request as ready for review March 27, 2026 17:05
cgi.go Outdated
// If a worker is already assigned explicitly, derive SCRIPT_NAME from its filename
if fc.worker != nil {
fc.scriptFilename = fc.worker.fileName
fc.scriptName = strings.TrimPrefix(fc.worker.fileName, fc.documentRoot)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm probably would be better to leave scriptName empty if the worker is in the public path:

root /some/path
worker /other/path {
  match *
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about that. Shouldn't it show /other/path/index.php then?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure either TBH. In CGI spec it's the path relative to the root, so /other/path/index.php might be misleading.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically that's a path relative to the root, haha.

I don't see a better solution. Emptying it out would be even more of a violation.

cgi.go Outdated
// If a worker is already assigned explicitly, derive SCRIPT_NAME from its filename
if fc.worker != nil {
fc.scriptFilename = fc.worker.fileName
fc.scriptName = filepath.ToSlash(strings.TrimPrefix(fc.worker.fileName, fc.documentRoot))
Copy link
Copy Markdown
Contributor

@AlliBalliBaba AlliBalliBaba Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also add a test for when the worker is outside of the public path (match)? Thinking about it again, scriptname should be empty since forwarding an absoule path when expecting a relative one is probably worse than forwarding nothing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to add the test, but I'm not sure if I agree with passing nothing being the correct choice. We should probably agree on what the correct behaviour is first.

'SCRIPT_NAME'
Contains the current script's path. This is useful for pages which need to point to themselves. The FILE constant contains the full path and filename of the current (i.e. included) file.

If anything, "This is useful for pages which need to point to themselves." would mean that we should perhaps just give the current request uri. But on the other hand, "Contains the current script's path." would mean it should be the absolute path, rather than a uri.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still expected to be a relative path, so I'd rather prevent potential redirects like this (and just leave it empty):

/path-the-user-visits -> /app/vendor/some-framework/worker.php

Realistically, most worker mode implementations probably just ignore SCRIPT_NAME.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know, that doesn't feel right to me. I've changed it to what you suggested either way. Nobody should be using these server vars anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

$_SERVER['SCRIPT_NAME'] is empty in worker mode

2 participants