PHP 中的 wget 错误 400,命令行中的 200

wget error 400 from PHP, 200 from command line

从命令行(通过我的服务器上的 SSH)这有效:

wget "https://www.example.com/script?paramA=1234&paramB=ABCD"

来自同一服务器上的 PHP:

$url = "https://www.example.com/script?paramA=1234&paramB=ABCD";
exec("/usr/bin/wget $url");

我得到:

HTTP request sent, awaiting response... 400 Bad Request
2018-11-07 15:01:21 ERROR 400: Bad Request.

这是怎么回事?

让我们看看,两者有什么不同?

wget "https://www.example.com/script?paramA=1234&paramB=ABCD"

VS

$url = "https://www.example.com/script?paramA=1234&paramB=ABCD";
exec("/usr/bin/wget $url");

让我们使用您的 PHP 代码: 如果你打印 echo $url 你会得到 :

https://www.example.com/script?paramA=1234&paramB=ABCD

从字面上看。

那么,您的 exec 调用中发生了什么? 如果你回显 "/usr/bin/wget $url" 你会得到 :

/usr/bin/wget https://www.example.com/script?paramA=1234&paramB=ABCD

从字面上看。 现在

有什么区别
wget "https://www.example.com/script?paramA=1234&paramB=ABCD"

/usr/bin/wget https://www.example.com/script?paramA=1234&paramB=ABCD

当然有路径:/usr/bin 但是...如果您尝试一下,您会发现这不是您的问题...

还有什么?引号。 shell 命令中的 url 包含在引号中,而在 PHP 代码生成的命令中则不是。

正如@ArtisticPhoenix 在评论中提到的,您可以在 $url 变量上使用 php 函数 escapeshellarg()。它会在你的 url 周围添加引号(并确保你的字符串保持字符串,例如防止注入)并且你的命令应该 运行 没问题。

如果你想知道这里发生了什么,那就是 url 中的 & 符号被执行两个命令而不是一个命令的控制台解析。您的 url 调用(缺少 paramB 和另一个在您的 shell 中创建变量的命令 paramB=ABCD。您可以通过键入 echo $paramB 来查看它,它将打印 ABCD在您的控制台中。您正在调用的 API 可能依赖于 paramB 存在,因此,返回 400 错误。

希望这对您有所帮助。祝你好运。