You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何GET请求下file_get_contents('php://input')返回NULL?

问题解答:CloudLinux + cPanel下GET请求无法读取php://input的问题

背景

服务器迁移至**CloudLinux v9.5.0(搭配cPanel 126.0.9)**后,使用Postman发送原始JSON数据时,仅GET请求的file_get_contents('php://input')返回NULL,POST、PUT、PATCH请求均正常。迁移前GET请求处理完全正常。

测试脚本:

<?php
echo strtoupper($_SERVER['REQUEST_METHOD']) . "\n\n\n";

$data = json_decode(file_get_contents('php://input'), true);

var_dump($data);
?>

1. CloudLinux v9.5.0是否存在阻止GET请求携带请求体的配置变更?

CloudLinux本身默认没有这类限制,但它搭配的cPanel(尤其是126版本的EasyApache 4)或默认的Apache/Nginx配置可能做了调整。HTTP规范并未强制禁止GET请求带请求体,但很多服务器默认会忽略或剥离GET的请求体,cPanel的EA4默认配置可能新增了这类处理逻辑。

2. 是否有mod_security规则或PHP设置会剥离GET请求的请求体?

mod_security

大概率是ModSecurity的规则拦截了GET请求的请求体。OWASP核心规则集(CRS)里有针对GET请求带请求体的异常检测规则,会直接截断请求体。可以通过以下方式排查:

  • 查看ModSecurity日志(路径通常为/var/log/apache2/modsec_audit.log,或在cPanel的「ModSecurity」模块中查看),搜索目标请求的ID,看是否有拦截记录。
  • 临时禁用ModSecurity测试,若请求正常,则确定是规则问题,可针对性禁用相关规则。

PHP设置

PHP本身的配置(如php.ini中的enable_post_data_reading)仅影响POST请求,GET请求的php://input不受该参数控制。但如果使用PHP-FPM,FastCGI的配置可能会丢弃GET请求体:

  • Apache环境:检查虚拟主机配置中是否有ProxyFCGISetEnvIf相关规则,导致请求体未传递给PHP-FPM。
  • Nginx环境:检查location配置中是否有fastcgi_pass_request_body off;这类禁用请求体传递的设置。

3. 是否应该用$_GET替代php://input处理GET请求?

不建议。$_GET解析的是URL中的查询参数,而php://input读取的是请求体内容,二者逻辑完全不同。强行用$_GET需要将JSON嵌入URL参数,会带来以下问题:

  • 违反REST语义规范,GET请求的查询参数应用于过滤、排序而非传递业务数据。
  • URL长度有限制(不同浏览器/服务器上限不同),无法传递较大的JSON数据。
  • 破坏你原本统一处理各请求方法请求体的逻辑。

4. 有没有办法让GET请求可以携带JSON请求体?

有以下几种可行方案:

方案1:调整服务器配置

  • ModSecurity:找到拦截GET请求体的规则,在cPanel的ModSecurity模块中添加规则例外,或直接禁用该规则。
  • Apache + PHP-FPM:在虚拟主机配置中添加以下配置,确保GET请求的请求体被传递:
    SetEnvIf Request_Method "GET" HTTP_CONTENT_LENGTH=$HTTP_CONTENT_LENGTH
    SetEnvIf Request_Method "GET" HTTP_CONTENT_TYPE=$HTTP_CONTENT_TYPE
    
    同时确保ProxyFCGI配置没有丢弃请求体。
  • Nginx + PHP-FPM:在处理PHP请求的location块中添加:
    fastcgi_pass_request_body on;
    fastcgi_pass_request_headers on;
    
    移除任何针对GET请求禁用请求体的配置。

方案2:调整请求方式

如果服务器配置修改困难,可将需要携带JSON体的GET请求改为POST或PUT(虽然不符合GET的语义,但能快速解决问题);或者使用POST请求并通过_method=GET参数模拟GET(需后端框架支持方法覆盖)。

方案3:原始请求数据读取(不推荐)

可以尝试读取原始HTTP请求数据来获取请求体,比如使用$GLOBALS['HTTP_RAW_POST_DATA'](但该变量已在PHP 7.0+废弃),或通过Apache的mod_cgi环境变量读取,但这种方式兼容性差,仅作为最后手段。


额外排查步骤

  1. 使用curl测试,排除Postman的问题:
    curl -X GET -H "Content-Type: application/json" -d '{"test": 123}' http://your-domain/test.php
    
  2. 查看服务器访问日志,确认请求的Content-Length头是否正确传递给了后端。
  3. 在cPanel的「EasyApache 4」模块中,检查是否启用了针对GET请求的特殊过滤组件。

内容的提问来源于stack exchange,提问作者zcool

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 18:46:11