根据documentation,php://input
并不总是包含HTTP请求正文。
我有一些代码在脚本启动时始终打开流,以使其可供用户应用程序使用:
$stream = fopen('php://input', 'rb');
如果用户应用程序尝试从空流中读取,则在Content-Length > 0
时,我希望我的库引发异常:
请求正文无法使用。
我的问题是:
feof()
会返回false
,而fread()
尚未被调用; fread()
1个字节,然后fseek()
,因为此流不支持搜索; php://input
并尝试事先阅读,因为我们不能依赖此流可用多次; php://input
复制到php://temp
,然后再将手提交给用户应用程序。因此,是否可以判断php://input
是否在fopen()
之后,但在任何fread()
之前包含数据?
答案 0 :(得分:1)
我找到的解决方案是创建一个表示请求正文的类,并直接从此类而不是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
字节来隐藏这种复杂性。
答案 1 :(得分:0)
“使用php://输入打开的流只能读取一次;流不支持搜索操作。”
http://php.net/manual/en/wrappers.php.php
对我而言,这表明它是一种老式的只读流。你不能寻找和测试它是文件的结尾还是长度。