为什么在 PHP 中的函数 header() 之后调用的函数 http_response_code() 表现得很奇怪?
Why is function http_response_code() acting strange that was called after function header() in PHP?
嗯。我对 http_response_code()
有疑问,我找不到解释。
如果我在 http_response_code()
之前使用 header()
,PHP returns 由 header()
设置的 HTTP 状态并忽略任何 http_response_code()
.
比如我有一个文件:
<?php
header('HTTP/1.1 404 Not Found');
file_put_contents('./log',http_response_code(501).PHP_EOL,FILE_APPEND);
file_put_contents('./log',http_response_code(502).PHP_EOL,FILE_APPEND);
file_put_contents('./log',http_response_code(503).PHP_EOL,FILE_APPEND);
(我使用 file_put_contents()
来防止任何输出,因为有人会说,这就是这个问题的答案)
我使用默认的 php-server(但问题可以用 NGINX 重现):
php -S localhost:9985
有需求:
curl -D - http://localhost:9985
有回复:
HTTP/1.1 404 Not Found
Host: localhost:9958
Date: Wed, 15 Sep 2021 17:20:05 GMT
Connection: close
X-Powered-By: PHP/8.0.10
Content-type: text/html; charset=UTF-8
还有日志:
404
501
502
响应包括第一行:
HTTP/1.1 404 Not Found
但我一直在等待 HTTP/1.1 503 Service Unavailable
。
日志文件包含预期数据,它显示 http_response_code
正确返回状态。但它不影响 HTTP 响应代码。
我认为原因是一些数据可以发送到 OUTPUT,因为我使用了 header()
。
但是如果我使用 header()
两次,它不会产生问题。
我更改了我的文件:
<?php
header('HTTP/1.1 404 Not Found');
header('HTTP/1.1 503 Service Unavailable');
并重复请求:
curl -I http://localhost:9958
有回复:
HTTP/1.1 503 Service Unavailable
Host: localhost:9958
Date: Wed, 15 Sep 2021 17:26:08 GMT
Connection: close
X-Powered-By: PHP/8.0.10
Content-type: text/html; charset=UTF-8
效果很好!
问题可以在 PHP 7.2、PHP 7.4、PHP 8 上重现。
我在它所在的位置找到了一条评论 https://www.php.net/manual/ru/function.http-response-code.php#125538。但是有阿帕奇。我应该说,如果我使用 Apache,这个问题对我来说是不可重现的。
请描述,为什么函数 (http_response_code) 无法正常工作。
请不要建议不要使用该函数,因为我想知道该函数行为的真正原因(神圣的含义)。
简短说明
这是因为在某些(全部?)PHP SAPI 实现中,传递给 header()
的状态行优先于 http_response_code()
。
技术说明(具体到PHP8.0.10)
PHP 在两个单独的变量中跟踪状态行和 HTTP 响应代码:SG(sapi_headers).http_status_line
和 SG(sapi_headers).http_response_code
.
header('HTTP/1.1 404 Not Found')
将 http_status_line
设置为“HTTP/1.1 404 未找到”here and updates SG(sapi_headers).http_response_code
a few lines earlier, while http_response_code(503)
only sets SG(sapi_headers).http_response_code
to 503 here.
PHP 的内置服务器用于发送 header 的代码可以在 sapi_cli_server_send_headers
函数中找到(php_cli_server.c). In that function, we see that SG(sapi_headers).http_response_code
is ignored when SG(sapi_headers).http_status_line
is set. The sapi_cgi_send_headers
function used by PHP-FPM shows a similar story. The apache2handler SAPI uses 两者http_status_line和http_response_code。理论上,它们可以指向不同的状态!
错误?
也许吧。但是 changing/fixing 这种行为在谁知道多少年后会破坏向后兼容性,所以它可能应该单独保留。最好坚持使用 header() 或 http_response_code().
来完全避免这种情况
嗯。我对 http_response_code()
有疑问,我找不到解释。
如果我在 http_response_code()
之前使用 header()
,PHP returns 由 header()
设置的 HTTP 状态并忽略任何 http_response_code()
.
比如我有一个文件:
<?php
header('HTTP/1.1 404 Not Found');
file_put_contents('./log',http_response_code(501).PHP_EOL,FILE_APPEND);
file_put_contents('./log',http_response_code(502).PHP_EOL,FILE_APPEND);
file_put_contents('./log',http_response_code(503).PHP_EOL,FILE_APPEND);
(我使用 file_put_contents()
来防止任何输出,因为有人会说,这就是这个问题的答案)
我使用默认的 php-server(但问题可以用 NGINX 重现):
php -S localhost:9985
有需求:
curl -D - http://localhost:9985
有回复:
HTTP/1.1 404 Not Found
Host: localhost:9958
Date: Wed, 15 Sep 2021 17:20:05 GMT
Connection: close
X-Powered-By: PHP/8.0.10
Content-type: text/html; charset=UTF-8
还有日志:
404
501
502
响应包括第一行:
HTTP/1.1 404 Not Found
但我一直在等待 HTTP/1.1 503 Service Unavailable
。
日志文件包含预期数据,它显示 http_response_code
正确返回状态。但它不影响 HTTP 响应代码。
我认为原因是一些数据可以发送到 OUTPUT,因为我使用了 header()
。
但是如果我使用 header()
两次,它不会产生问题。
我更改了我的文件:
<?php
header('HTTP/1.1 404 Not Found');
header('HTTP/1.1 503 Service Unavailable');
并重复请求:
curl -I http://localhost:9958
有回复:
HTTP/1.1 503 Service Unavailable
Host: localhost:9958
Date: Wed, 15 Sep 2021 17:26:08 GMT
Connection: close
X-Powered-By: PHP/8.0.10
Content-type: text/html; charset=UTF-8
效果很好!
问题可以在 PHP 7.2、PHP 7.4、PHP 8 上重现。 我在它所在的位置找到了一条评论 https://www.php.net/manual/ru/function.http-response-code.php#125538。但是有阿帕奇。我应该说,如果我使用 Apache,这个问题对我来说是不可重现的。
请描述,为什么函数 (http_response_code) 无法正常工作。
请不要建议不要使用该函数,因为我想知道该函数行为的真正原因(神圣的含义)。
简短说明
这是因为在某些(全部?)PHP SAPI 实现中,传递给 header()
的状态行优先于 http_response_code()
。
技术说明(具体到PHP8.0.10)
PHP 在两个单独的变量中跟踪状态行和 HTTP 响应代码:SG(sapi_headers).http_status_line
和 SG(sapi_headers).http_response_code
.
header('HTTP/1.1 404 Not Found')
将 http_status_line
设置为“HTTP/1.1 404 未找到”here and updates SG(sapi_headers).http_response_code
a few lines earlier, while http_response_code(503)
only sets SG(sapi_headers).http_response_code
to 503 here.
PHP 的内置服务器用于发送 header 的代码可以在 sapi_cli_server_send_headers
函数中找到(php_cli_server.c). In that function, we see that SG(sapi_headers).http_response_code
is ignored when SG(sapi_headers).http_status_line
is set. The sapi_cgi_send_headers
function used by PHP-FPM shows a similar story. The apache2handler SAPI uses 两者http_status_line和http_response_code。理论上,它们可以指向不同的状态!
错误?
也许吧。但是 changing/fixing 这种行为在谁知道多少年后会破坏向后兼容性,所以它可能应该单独保留。最好坚持使用 header() 或 http_response_code().
来完全避免这种情况