php://input
只能读取一次的states文档。
在我的应用程序中,我需要读取它两次,一次用于身份验证,一次用于实际处理内容,两个功能都由不同的独立模块处理。疯狂的是:它有效。
我可以指望在任何地方工作,或者这是我的PHP版本(5.2.10)中的侥幸?我能找到的关于这个的唯一文档就是说它不应该工作,没有提到版本限制。
在丹尼斯的预感之后,我做了这个测试:
$in = fopen('php://input', 'r');
echo fread($in, 1024) . "\n";
fseek($in, 0);
echo fread($in, 1024) . "\n";
fclose($in);
echo file_get_contents('php://input') . "\n";
卷曲:
$ curl http://localhost:8888/tests/test.php -d "This is a test"
This is a test
This is a test
显然,每次打开手柄只读一次 。
稍微挖掘一下,确实php://input
确实只能读取一次,只能读取PUT请求。上面的示例使用了POST请求。
答案 0 :(得分:23)
对源代码进行一点检查即可得出答案。
首先,是的,由于底层流没有实现seek
处理程序,因此每个句柄限制为一次读取:
php_stream_ops php_stream_input_ops = {
php_stream_input_write,
/* ... */
"Input",
NULL, /* seek */
/* ... */
};
其次,读取处理程序有两种不同的行为,具体取决于“POST数据”是否已被读取并存储在SG(request_info).raw_post_data
中。
if (SG(request_info).raw_post_data) {
read_bytes = SG(request_info).raw_post_data_length - *position;
/* ...*/
if (read_bytes) {
memcpy(buf, SG(request_info).raw_post_data + *position, read_bytes);
}
} else if (sapi_module.read_post) {
read_bytes = sapi_module.read_post(buf, count TSRMLS_CC);
/* ... */
} else {
stream->eof = 1;
}
所以我们在这里有三种可能性:
SG(request_info).raw_post_data
中。在这种情况下,由于存储了数据,我们可以打开和读取php://input
的多个句柄。php://input
不能给我们任何东西。php://input
并只阅读一次。注意:以下是默认行为。不同的SAPI或其他扩展可能会改变此行为。
如果是POST请求,PHP会根据内容类型定义不同的POST阅读器和POST处理程序。
案例1。当我们收到POST请求时会发生这种情况:
application/x-www-form-encoded
。 sapi_activate
检测到具有内容类型的POST请求,并调用sapi_read_post_data
。这将检测内容类型并定义POST阅读器/处理程序对。 POST阅读器为sapi_read_standard_form_data
,会立即调用,只需将请求正文复制到SG(request_info).post_data
即可。然后调用默认的帖子阅读器php_default_post_reader
,如果设置了ini设置$HTTP_RAW_POST_DATA
,则填充always_populate_post_data
,然后将SG(request_info).post_data
复制到SG(request_info).raw_post_data
并清除第一个。{1}}。对处理程序的调用在这里并不重要,并且推迟到构建超级全局(这可能不会发生,以防JIT被激活并且不使用超全局)。php_default_post_reader
,没有任何数据读取。由于这是一个POST请求,并且没有读取器/处理程序对,因此将调用sapi_read_standard_form_data
。这与内容类型application/x-www-form-encoded
的读取处理程序功能相同,因此所有数据都被吞噬到SG(request_info).post_data
。与现在唯一的区别是$HTTP_RAW_POST_DATA
总是被填充(无论always_populate_post_data
的值),并且没有用于构建超全局的处理程序。 案例2。当我们的内容类型为“multipart / form-data”的表单请求时会发生这种情况。 POST阅读器为NULL
,因此处理程序rfc1867_post_handler
充当混合reader/handler
。在sapi_activate
阶段没有读取任何数据。函数sapi_handle_post
最终在稍后阶段调用,后者又调用POST处理程序。 rfc1867_post_handler
会读取请求数据,填充POST
和FILES
,但SG(request_info).raw_post_data
不会留下任何内容。
案例3。最后一种情况发生在与POST不同的请求(例如PUT)。直接调用php_default_post_reader
。由于请求不是POST请求,因此sapi_read_standard_form_data
会吞下数据。由于没有读取数据,因此没有任何事情要做。
答案 1 :(得分:3)
也许他们的意思是fseek()或rewind()不可用。 您是否在打开的php:// input?
上尝试了其中一个函数