PHP $_POST 数组为空,Apache 和 PHP 7.4 (CLI/CGI)

2023-12-14

我正在尝试测试访问 POST 参数的 php 脚本是否正常工作,但遇到了麻烦。访问 $_POST 数组返回零值(见下文)。

首先我在 bash 中运行curl:

curl -v -X POST http://example.com/test.php -H 'Content-Type: application/x-www-form-urlencoded' -d 'name=bob&id=5'

test.php 脚本是:

#!/usr/bin/php-cgi
<?php
errort_reporting(E_ALL);
ini_set('display_errors', 1);

echo $_SERVER['REQUEST_METHOD'] . "\n';
echo $_POST['name'] . "\n";
echo var_dump($_POST);

那么curl的输出是:

*  Trying 12.34.567.89:80
* TCP_NODELAY set
* Connected to 12.34.567.89 (12.34.567.89) port 80 (#0)
> POST /test.php HTTP/1.1
> Host: 12.34.567.89
> User-Agent: curl/7.68.0
> Accept: */*
> Content-Length: 16
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 16 out of 16 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sun, 23 Jul 2023 12:34:56 GMT
< Server: Apache/2.4.54 (Unix)
< Transfer-Encoding: chunked
<
POST

Notice: Undefined index: name in /test.php on line 11

array(0) {
}
* transfer closed with outstanding read data remaining
* closing connection 0
curl: (18) transfer closed with outstanding read data remaining

我在本地复制了这个问题。修剪我的 apache .config 文件后,问题仍然存在。配置文件是

LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule filter_module modules/mod_filter.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule cgid_module modules/mod_cgid.so
LoadModule dir_module modules/mod_dir.so
LoadModule alias_module modules/mod_alias.so

<IfModule unixd_module>
    User daemon
    Group daemon
</IfModule>

ServerAdmin [email protected]

ServerName www.example.com:80

<Directory />
    AllowOverride none
    Require all denied
</Directory>

DocumentRoot "/srv/apache/htdocs"

<Directory "/srv/apache/htdocs">
    AllowOverride None
    Require all granted
</Directory>

<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/srv/apache/cgi-bin/"
</IfModule>


<Directory "/srv/apache/cgi-bin">
    AllowOverride None    
    Options None 
    Require all granted
</Directory>

访问日志显示

12.34.567.89 - - [23/Jul/2023:17:35:47 +0000] "POST /cgi-bin/test.php HTTP/1.1" 200 846

错误日志显示

[Sun Jul 23 17:35:47.188923 2023] [core:error] [pid 3608972:tid 140226028996352] (104)Connection reset by peer: [client 12.34.567.89:34618] AH00574: ap_content_length_filter: apr_bucket_read() failed

我在 Apache 中将 PHP 作为 CGI 编译器运行。二进制信息是

/usr/bin/php --version
PHP 7.4.3-4ubuntu2.18 (cli) (built: Feb 23 2023 12:43:23) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0 copyright (c) Zend Technologies
    with Zend OPache v7.4.3-4ubuntu2.18, Copyright (c), by Zend Technologies

在我看来,请求已到达正确的终点,但主体尚未到达那里。基于此,我认为我的 apache 配置中的某些内容可能没有传递信息(也许mod_rewrite?).

我尝试过改变'Content-Type' to 'form-data'并改变'-d'选项值到 .json'{"name":"bob","id":5}'但这给出了与上面相同的结果。

我在 Linux 上运行 Apache。我在网上读到,可能是 Apache 的 mod_rewrite 导致了问题,所以我尝试直接访问 .php 脚本,但这给出了与上面相同的输出。

这是我第一次处理 POST 请求,我不确定问题出在哪里。任何指出解决方案的帮助将不胜感激。解释原因也会有所帮助。

EDIT

我注意到error_log以上特点[client 12.34.567.89:52546]我不确定端口52546应该参与。我已多次尝试在端口 80 上显式请求 - 每次端口号[client ip:port]变化。有谁知道这可能是什么,或者是否可能是问题所在?


一些好消息和一些坏消息。首先,在命令行上使用curl 测试POST 请求是一个很好的方法,但是要充分了解它,这样您就不会在那里而不是在服务器端寻找问题。

curl(1) 发送 POST 请求-d 'name=bob&id=5'和单独的 URL。你不必尝试-X ... or -H ...。这也是你注意到的,这没有任何区别。保持更简单,这样你就不需要猜测:

curl -d 'name=bob&id=5' http://example.com/test.php

(也可以把网址放在前面,这只是我的习惯,我把它放在后面-...选项及其参数,因为 URL 是一个位置参数 [您可以添加多个])

坏消息可能是您正在针对错误的服务器进行测试。

echo $_SERVER['REQUEST_METHOD'];
echo $_POST['name'];

永远无法生成

POST
array(0) {}

即使它实际上很相似,但使用 var_dump(),您所讨论的curl 命令行确实可以工作。

现在,这是在命令行上使用curl(1)来测试这些东西的好处:您可以轻松地inspect发生了什么,至少从客户端来看。开关是-v如果您将其添加到组合中,您将看到有关连接的详细信息(*), 数据发送到服务器>以及正在接收的数据<- 在响应本身旁边。

Example:

$ curl -v http://localhost:8080/ -d 'name=bob&id=5'
*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
> Content-Length: 13
> Content-Type: application/x-www-form-urlencoded
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Host: localhost:8080
< Date: Sat, 22 Jul 2023 11:35:53 GMT
< Connection: close
< X-Powered-By: PHP/8.2.8
< Content-type: text/html; charset=UTF-8
< 
POST
bob
array(0) {
}
* Closing connection 0

The index.php本例中使用的文件:

<?php

echo $_SERVER['REQUEST_METHOD'], "\n";
echo $_POST['name'], "\n";
var_dump($_POST);

以及如何在与index.php相同的目录中启动PHP开发服务器:

$ php8.2 -n -S localhost:8080
[Sat Jul 22 13:35:29 2023] PHP 8.2.8 Development Server (http://localhost:8080) started
[Sat Jul 22 13:35:53 2023] 127.0.0.1:35642 Accepted
[Sat Jul 22 13:35:53 2023] 127.0.0.1:35642 [200]: POST /
[Sat Jul 22 13:35:53 2023] 127.0.0.1:35642 Closing

(在不同的终端中打开它,然后你就可以跟踪curl和PHP)

开发网络服务器可以帮助您检查测试程序是否有效,因此您也可以排除某些部分。

但这不是必需的,我只是这样做来重现您的问题(并且失败了;))。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PHP $_POST 数组为空,Apache 和 PHP 7.4 (CLI/CGI) 的相关文章

随机推荐