根据 documentation , php://input
并不总是包含 HTTP 请求正文。
我有一些代码总是在脚本启动时打开流,以使其可供用户应用程序使用:
$stream = fopen('php://input', 'rb');
如果用户应用程序尝试从空流中读取数据,则 Content-Length > 0
,我希望我的库抛出异常:
The request body is not available.
我的问题是:
- 如果流为空,
feof()
返回false
而fread()
尚未被调用; - 我不能
fread()
1 个字节则fseek()
,因为该流不支持查找; - 我无法打开另一个
php://input
并尝试事先读取它,因为我们不能依赖此流多次可用; - 我不想盲目复制
php://input
至php://temp
出于性能原因,在将手交给用户应用程序之前。
因此,是否可以判断 php://input
包含 fopen()
之后的数据,但在任何 fread()
之前?
最佳答案
我找到的解决方案是创建一个表示请求正文的类,并从该类读取而不是直接读取 php://input
:
class RequestBody
{
protected $firstByte;
protected $isEmpty;
public function __construct($stream)
{
$this->firstByte = fread($stream, 1);
$this->isEmpty = ($this->firstByte === '');
// ...
}
public function isEmpty()
{
return $this->isEmpty;
}
public function read($length)
{
// ...
}
}
$body = new RequestBody(fopen('php://input', 'rb'));
类构造函数读取流的第一个字节,将其存储以供以后使用,并立即知道流是否为空。
read()
通过在第一次调用时返回第一个字节 + $length - 1
字节来隐藏这种复杂性。
关于php - 是否可以知道 php 是否为 ://input contains data before starting reading it?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11298887/