Laravel 8+Octane/Swoole下file_get_contents('php://input')为空怎么解决
问题原因
Swoole 服务启动后会在底层自主解析HTTP请求,请求体内容会被Swoole提前读取消费,原生PHP的file_get_contents('php://input')只能读取一次请求体内容,因此在业务代码中再次调用就会返回空值,这是Octane + Swoole环境的固有特性,并非代码错误。
解决方案
方案1:直接使用Laravel原生方法读取原始请求体(通用兼容)
Laravel 本身已经对不同运行环境的请求做了兼容性处理,无论在FPM还是Octane环境下,都可以直接通过请求实例的getContent()方法获取原始请求内容:
$rawInput = request()->getContent();
方案2:兼容AWS SNS Message Validator第三方依赖
不需要修改依赖包的源码,仅需要替换调用验证器的方法即可:
- 原依赖默认读取
php://input的调用方式:
// 原写法,会自动读php://input,Octane环境下失效 $message = \Aws\Sns\Message::fromRawPostData();
- 替换为手动传入原始请求内容的写法即可正常使用:
// 先通过Laravel请求实例拿到原始内容,再传给验证器 $rawMessage = request()->getContent(); $message = \Aws\Sns\Message::fromJsonString($rawMessage);
方案3:兼容无法修改的第三方老旧代码
如果项目依赖的第三方代码强制调用file_get_contents('php://input')且无法修改源码,可以在Laravel中间件中提前注入请求体内容,覆盖php://input的读取逻辑:
// 先创建中间件并注册到对应路由组 public function handle(Request $request, Closure $next) { // 仅在Octane Swoole环境下执行覆盖 if (env('LARAVEL_OCTANE') && str_contains(env('OCTANE_SERVER'), 'swoole')) { $rawContent = $request->getContent(); // 写入请求体到php://input,供后续第三方代码读取 file_put_contents('php://input', $rawContent); } return $next($request); }
验证测试
可以用以下代码替换原来的测试逻辑,验证兼容性:
echo "php://input: ". request()->getContent();
在Octane + Swoole环境下执行之前的curl请求,即可正常返回请求体内容dataaaa。
内容的提问来源于stack exchange,提问作者pablorsk
相关产品推荐
相关产品推荐

