[notice] 1229#1229 php message: PHP Fatal error: Unknown: Failed opening required '/var/www/web/debug.php/login' (include_path='.:/usr/share/php') in Unknown on line 0
nginx conf
location / {
try_files $uri @rewriteapp;
}
location @rewriteapp {
add_header X-Backend-Server $hostname;
proxy_pass http://unit_backend;
proxy_set_header Host $host;
}
location ~* \.php(/|$) {
try_files $uri =404;
add_header X-Backend-Server $hostname;
proxy_pass http://direct_php_upstream;
proxy_set_header Host $host;
}
{
"listeners": {
"127.0.0.1:8400": {
"application": "script_index_php"
},
"127.0.0.1:8091": {
"application": "direct_php"
}
},
"applications": {
"script_index_php": {
"type": "php",
"processes": 20,
"root": "/var/www/web/",
"user": "www-data",
"group": "www-data",
"script": "app.php"
},
"direct_php": {
"type": "php",
"processes": {
"max": 5,
"spare": 0
},
"user": "www-data",
"group": "www-data",
"root": "/var/www/web/",
"index": "app.php"
}
}
}
PHP interpreter failed to load file /var/www/web/debug.php/login. I guess there's no such file login inside /var/www/web/debug.php/ directory.
You can't handle such URI by your "direct_php" application. It expects a path to PHP files passed as URI. In order to call debug.php and pass /login as URI, you need to set script parameter to debug.php.
I understand this can be inconvenient. Unfortunately, the way how PHP works is true mess. For example, in order to handle such applications in Apache's mod_php there are used .htaccess files with complex rewrite rules.
We need something simple but yet powerful. For now it's just simple, simple and dumb.
@VBart Thank you for the quick response!
Bascially, the optional _script_ Option should be sufficient (for Symfony set it to app.php). The real problem here is, that the (HTTP/Proxy) API of Unit - in contrast to FastCGI - doesn't (allow to) set $_SERVER['REQUEST_URI'] - at least I've not found any way to do that. But Symfony, like other MVC-like Frameworks, requires this Variable to create the internal $request Object.
A workaround may be to pass $request_uri from nginx to unit:
proxy_set_header REQUEST_URI $request_uri;
This than becomes $_SERVER['HTTP_REQUEST_URI'] in PHP.
Then you'd have to patch Symfony's app.php to set $_SERVER['REQUEST_URI'] from that Variable as early as possible.
IMHO, Unit's PHP API should mimic (relevant parts of) the FastCGI API, so it becomes a (more or less) drop-in replacement for PHP's FastCGI-Process-Manager.
@bbak If you use script option, then $_SERVER['REQUEST_URI'] is automatically set to the actual request (not the script path) and usually nothing else is needed. The problem is relevant only when script option is not used.
@VBart
When using the Laravel framework I encountered the same problem - the value of the variable $_SERVER['REQUEST_URI'] is equal to the /index.php, even after the installation of the script. Unit version 1. My issue https://github.com/laravel/framework/issues/23968
@Hunternnm /index.php is added by your nginx configuration. The try_files directive makes an internal redirect to the last parameter. In order to avoid changing requested URI, you can use a redirect to named location.
No changes in PHP processing were made since 0.6.
@VBart Thank you, this option solved my problem. And do not tell me where you can read about this behavior?
@VBart That's the important bit of information! If the location Block that keeps the proxy_pass directive is a named location, than $_SERVER['REQUEST_URI'] is set as expected. If it's a (RegEx or Prefix)Match like in Example 1 of Integration with Nginx, it's set to the filename of the script.
Besides that, when using nginx' fcgi interface there are additional Variables like $_SERVER['REMOTE_ADDR'], which may (or may not) be important for the PHP Engine. Additionally it's quite easy to set additional $_SERVER/$_ENV Variables using fastcgi_param. We're using this (e.g.) to tell the backend that the initial request was done using https like this:
# in http{} scope
map $http_x_forwarded_proto $fe_https {
default "off";
https "on";
}
...
# in location{} block for PHP
fastcgi_param HTTPS $fe_https;
Use case: If the PHP-App has to create URL's including scheme, it need to distinguish between http and https.
Other Use case: Setting SYMFONY_ENV to either dev, test, prod.
Obviously with unit, this has to be accomplished using http-headers, right?
Still can't understand how to resolve this issue for Laravel. In case of named location in nginx the right URI passing to unit, but unit can't find this URI and return 500 as I've see in unit's access log:
10.0.62.4 - - [03/Feb/2019:03:21:35 +0000] "OPTIONS /api/v1/auth/login HTTP/1.0" 500 0 "-" "user-agent"
proxy_set_header REQUEST_URI $request_uri; also doesn't helps.
--- UPDATE:
Oh, man ... there is a 'script' option in unit config:
{
"listeners": {
"*:8300": {
"application": "laravel-demo"
}
},
"applications": {
"laravel-demo": {
"type": "php",
"workers": 20,
"user": "www-data",
"group": "www-data",
"root": "/www/laravel/public",
"script": "index.php",
"index": "index.php"
}
}
}
Sure docs should be updated.
@oneumyvakin Could you suggest what kind of update to the docs is needed? All PHP-related options are described here: https://unit.nginx.org/configuration/#php-application
cc: @artemkonev
@VBart @artemkonev It will be nice to add "script": "index.php" option into most of PHP application examples, because it's a really important piece of configuration and helps people to migrate their applications from PHP-FPM. As far as I know most of the PHP-FPM FastCGI configurations using SCRIPT_FILENAME and it's mandatory setting for them.
@oneumyvakin It's not the script option responsible to set SCRIPT_FILENAME. Unit always sets it in either way. There are two different ways of configuring PHP:
script option is set. In this case SCRIPT_FILENAME is constructed from a request URI (root directory + uri) and the URI must be a valid path to .php file, or to a directory (in this case the index option is utilized: root + uri + index). Many PHP applications still work this way.SCRIPT_FILENAME variable is overwritten by the script option and all the requests are passed to the same file. This is used by some PHP applications and frameworks to construct clean URLs.So the configuration is depending on particular application. Setting script works for some applications, but don't work for others, and vice versa.
Most helpful comment
Bascially, the optional _script_ Option should be sufficient (for Symfony set it to
app.php). The real problem here is, that the (HTTP/Proxy) API of Unit - in contrast to FastCGI - doesn't (allow to) set$_SERVER['REQUEST_URI']- at least I've not found any way to do that. But Symfony, like other MVC-like Frameworks, requires this Variable to create the internal$requestObject.A workaround may be to pass
$request_urifrom nginx to unit:proxy_set_header REQUEST_URI $request_uri;This than becomes
$_SERVER['HTTP_REQUEST_URI']in PHP.Then you'd have to patch Symfony's
app.phpto set$_SERVER['REQUEST_URI']from that Variable as early as possible.IMHO, Unit's PHP API should mimic (relevant parts of) the FastCGI API, so it becomes a (more or less) drop-in replacement for PHP's FastCGI-Process-Manager.