Search code examples
phpnginxphp-7php-7.1

phpinfo() changes the status code of nginx response in a weird way


I have a php code that should always end up being "http 500 code" as I have a call to undefined func status_code("OK");

code:

<?
# phpinfo();
echo 'error_log = ' . ini_get('error_log') . "\n";
status_code("OK");
echo "OK";
?>

With example above:

➜ curl -I http://localhost:8080/kkk
HTTP/1.1 500 Internal Server Error
Server: nginx/1.20.1
Date: Sat, 29 Oct 2022 18:48:25 GMT
Content-Type: text/html
Content-Length: 5597
Connection: close
ETag: "635c9b20-15dd"

and in stdout output:

2022/10/29 18:50:32 [error] 29#29: *30 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function status_code() in /legacy/app/index.php:4
Stack trace:
#0 {main}
  thrown in /legacy/app/index.php on line 4" while reading response header from upstream, client: 172.17.0.1, server: localhost, request: "HEAD /kkk HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "localhost:8080"
172.17.0.1 - - [29/Oct/2022:18:50:32 +0000] 500 "HEAD /kkk HTTP/1.1" 0 "-" "curl/7.82.0" "-"

However if I uncomment #phpinfo(); line I get 200 OK:

➜ curl -I http://localhost:8080/kkk
HTTP/1.1 200 OK
Server: nginx/1.20.1
Date: Sat, 29 Oct 2022 18:52:25 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/7.1.33

and in stdout:

172.17.0.1 - - [29/Oct/2022:18:52:25 +0000] 200 "HEAD /kkk HTTP/1.1" 0 "-" "curl/7.82.0" "-"

I'm running nginx and it has the following configuration:

location ~ \.php$ {
    root /legacy/app;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_read_timeout 10s;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_index index.php;
    fastcgi_intercept_errors on;
    fastcgi_buffer_size 16k;
    fastcgi_buffers 4 16k;
}

location / {
    # make sure you have a custom html page placed in app folder
    # i.e. /legacy/app/app/50x.html
    try_files _ /index.php?$query_string;

}

Solution

  • You should use builtin function http_response_code() to change the response code.

    But, as well as header(), you must call http_response_code() before phpinfo() because any output produced in your response will imply header with 200 status code that you can't change anymore. (see Call header() after output is sent)

    Just tested with Apache (I don't think it makes a difference).

    This works (display php info with 500 status code):

    http_response_code(500);
    phpinfo();
    

    This doesn't works (display php info with 200 status code):

    phpinfo();
    http_response_code(500);
    

    This doesn't works (display php info with 200 status code):

    phpinfo();
    undefined_function(); // generates an error in error.log