For an introduction to php://input, the PHP official manual document has a paragraph that clearly outlines it.
“php://input allows you to read raw POST data. It is a less memory intensive alternative to $HTTP_RAW_POST_DATA and does not need any special php.ini directives. php://input is not available with enctype="multipart/form-data".
Translated, this is:
"php://input can read unprocessed POST data. Compared to $HTTP_RAW_POST_DATA, it puts less pressure on memory and does not require special php.ini settings. php://input cannot be used for enctype=multipart/form-data”
How should we understand this overview?! I divided it into three parts and understand it step by step.
Read POST data
cannot be used for multipart/form-data type
php://input VS $HTTP_RAW_POST_DATA
Read POST data
PHPers must be familiar with the built-in variable $_POST $. What are the relationships and differences between _POST and php://input? In addition, the most commonly used method for the client to interact with the server is GET, in addition to POST. Since php://input is a PHP input stream, it can be used. Read GET data? These two issues are the main content we need to discuss in this section.
Experience tells us that it will be a very effective method to summarize from testing and observation. Here, I wrote a few. A script to help us test.
@file 192.168.0.6:/phpinput_server.php prints out the received data
@file 192.168.0.8:/phpinput_post.php simulates submitting form data using the POST method
@file 192.168.0.8:/phpinput_xmlrpc.php simulates issuing an xmlrpc request using the POST method.
@file 192.168.0.8:/phpinput_get.php simulates submitting a form using the GET method
phpinput_server.php and phpinput_post. php
//@file phpinput_server.php
$raw_post_data = file_get_contents('php://input', 'r');
echo "-------$_POST------------------n";
echo var_dump($_POST) . "n";
echo "-------php://input-------------n";
echo $raw_post_data . "n";
?>
//@file phpinput_post.php
$http_entity_body = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788');
$http_entity_type = 'application/x-www-form-urlencoded';
$http_entity_length = strlen($http_entity_body);
$host = '192.168.0.6';
$port = 80;
$path = '/phpinput_server.php';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
fputs($fp, "POST {$path} HTTP/1.1rn");
fputs($fp, "Host: {$host}rn");
fputs($fp, "Content-Type: {$http_entity_type}rn ");
fputs($fp, "Content-Length: {$http_entity_length}rn");
fputs($fp, "Connection: closernrn");
fputs($fp, $http_entity_body . "rnrn");
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
fclose($fp);
echo $d;
}
?>
We can grab the http request packet by using the tool ngrep (because what we need to detect is php://input, so we only grab http here Request packet). Let's execute the test script phpinput_post.php
@php /phpinput_post.php
HTTP/1.1 200 OK
Date: Thu, 08 Apr 2010 03:23:36 GMT
Server: Apache /2.2.3 (CentOS)
X-Powered-By: PHP/5.1.6
Content-Length: 160
Connection: close
Content-Type: text/html; charset=UTF- 8
-------$_POST------------------
array(2) {
["n"]=> string(9) "perfgeeks"
["p"]=> string(4) "7788"
}
-------php://input------ -------
n=perfgeeks&p=7788
The http request packet captured through ngrep is as follows:
T 192.168.0.8:57846 -> 192.168.0.6:80 [AP ]
POST /phpinput_server.php HTTP/1.1..
Host: 192.168.0.6..Content-Type: application/x-www-form-urlencoded..Co
ntent-Length: 18.. Connection: close....n=perfgeeks&p=7788....
Looking carefully, we can easily find that
1, $_POST data, php://input data and httpd entity body data are "consistent"
2. The Content-Type in the http request is application/x-www-form-urlencoded, which means that the data in the http request body is the form data submitted using the post method of http, and has been processed by urlencode() .
(Note: Pay attention to the bolded part, which will not be prompted below).
Let’s take a look at the original file content of the script phpinput_xmlrpc.php, which simulates an xml-rpc request submitted by the POST method.
//@file phpinput_xmlrpc.php
$http_entity_body = "nn jt_userinfon";
$http_entity_type = 'text/html';
$http_entity_length = strlen($http_entity_body);
$host = '192.168.0.6';
$port = 80;
$path = '/phpinput_server.php';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
fputs($fp, "POST {$path} HTTP/1.1rn");
fputs($fp, "Host: {$host}rn");
fputs($fp, "Content-Type: {$http_entity_type}rn");
fputs($fp, "Content-Length: {$http_entity_length}rn");
fputs($fp, "Connection: closernrn");
fputs($fp, $http_entity_body . "rnrn");
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
fclose($fp);
echo $d;
}
?>
同样地,让我们来执行这个测试脚本
@php /phpinput_xmlrcp.php
HTTP/1.1 200 OK
Date: Thu, 08 Apr 2010 03:47:18 GMT
Server: Apache/2.2.3 (CentOS)
X-Powered-By: PHP/5.1.6
Content-Length: 154
Connection: close
Content-Type: text/html; charset=UTF-8
-------$_POST------------------
array(0) {
}
-------php://input-------------
jt_userinfo
执行这个脚本的时候,我们通过ngrep抓取的http请求数据包如下
T 192.168.0.8:45570 -> 192.168.0.6:80 [AP]
POST /phpinput_server.php HTTP/1.1..
Host: 192.168.0.6..Content-Type: text/html..Content-Length: 75..Connec
tion: close...... jt_userinfo<
/name>.....
同样,我样也可以很容易地发现:
1,http请求中的Content-Type是text/xml。它表示http请求中的body数据是xml数据格式。
2,服务端$_POST打印出来的是一个空数组,即与http entity body不一致了。这跟上个例子不一样了,这里的Content-Type是text/xml,而不是application/x-www-form-urlencoded
3,而php://input数据还是跟http entity body数据一致。也就是php://input数据和$_POST数据不一致了。
我们再来看看通过GET方法提交表单数据的情况,php://input能不能读取到GET方法的表单数据?在这里,我们稍加改动一下phpinput_server.php文件,将$_POST改成$_GET。
复制代码 代码如下:
//@file phpinput_server.php
$raw_post_data = file_get_contents('php://input', 'r');
echo "-------$_GET------------------n";
echo var_dump($_GET) . "n";
echo "-------php://input-------------n";
echo $raw_post_data . "n";
?>
//@file phpinput_get.php
$query_path = 'n=' . urldecode('perfgeeks') . '&p=' . urldecode('7788');
$host = '192.168.0.6';
$port = 80;
$path = '/phpinput_server.php';
$d = '';
$fp = fsockopen($host, $port, $error_no, $error_desc, 30);
if ($fp) {
fputs($fp, "GET {$path}?{$query_path} HTTP/1.1rn");
fputs($fp, "Host: {$host}rn");
fputs($fp, "Connection: closernrn");
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
fclose($fp);
echo $d;
}
?>
Similarly, we execute the next phpinput_get.php test script, which simulates a normal GET method to submit form data.
@php /phpinput_get.php
HTTP/1.1 200 OK
Date: Thu, 08 Apr 2010 07:38:15 GMT
Server: Apache/2.2.3 (CentOS)
X-Powered-By: PHP/5.1.6
Content-Length: 141
Connection: close
Content-Type: text/html; charset=UTF-8
- ------$_GET------------------
array(2) {
["n"]=>
string( 9) "perfgeeks"
["p"]=>
string(4) "7788"
}
-------php://input-- -----------
At this time, using the ngrep tool, the corresponding http request packet captured is as follows
T 192.168.0.8:36775 -> 192.168.0.6: 80 [AP]
GET /phpinput_server.php?n=perfgeeks&p=7788 HTTP/1.1..
Host: 192.168.0.6..Connection: close....
Compare the http request submitted by the POST method , usually in the request submitted by the GET method, the entity body is empty. At the same time, Content-Type and Content-Length will not be specified. However, if you force the data http entity body and specify the correct Content-Type and Content-Length, then php://input can still read the http entity body data, but not the $_GET data.
Based on the above detections, we can make the following summary:
1. When the Content-Type value is application/x-www-form-urlencoded, php will request the corresponding data of the http request body It will be filled in the array $_POST. The data filled in the $_POST array is the result of urldecode() parsing. (In fact, in addition to the Content-Type, there is also multipart/form-data to indicate that the data is form data, which we will introduce later)
2, php://input data, as long as the Content-Type is not multipart/form-data (This condition will be introduced later). Then the php://input data is consistent with the http entity body part of the data. The length of this partially consistent data is specified by Content-Length.
3. Only when the Content-Type is application/x-www-form-urlencoded and the submission method is the POST method, the $_POST data and the php://input data are "consistent" (with quotes to indicate their formats) Inconsistent, consistent content). Otherwise, they are inconsistent.
4, php://input cannot read $_GET data. This is because the $_GET data is written as query_path in the PATH field of the http request header (header), rather than in the body part of the http request.
This also helps us understand why the xml_rpc server reads data through file_get_contents(‘php://input’, ‘r’). Instead of reading from $_POST, it is precisely because the data specification of xml_rpc is xml and its Content-Type is text/xml.
php://input encountered multipart/form-data
When uploading a file, the form is written like this
Copy code The code is as follows:
Then, the meaning of enctype=multipart/form-data here is to set the Content-Type in the header of the http request to multipart/form-data. Please check RFC1867 for its description. multipart/form-data also means submitting form data using the POST method. It is also accompanied by file upload, so it will be different from the application/x- www-form-urlencoded data format. It will be passed to the server in a more reasonable and efficient data format. We submit the form data and print out the response result, as follows:
-------$_POST------------------
array(1) { ["n"]=> string(9) "perfgeeks" }
-------php://input-------------
At the same time, the corresponding http request packets we captured through ngrep are as follows:
########
T 192.168.0.8:3981 -> 192.168.0.6:80 [ AP]
POST /phpinput_server.php HTTP/1.1..Host: 192.168.0.6..Connection: kee
p-alive..User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en -US) A
ppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.3 Safari/533.2..Re
ferer: http://192.168.0.6/phpinput_server.php..Content-Length: 306 ..Ca
che-Control: max-age=0..Origin: http://192.168.0.6..Content-Type: mult
ipart/form-data; boundary=----WebKitFormBoundarybLQwkp4opIEZn1fA. .Acce
pt: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q
=0.8,image/png,*/*;q=0.5..Accept -Encoding: gzip,deflate,sdch..Accept-L
anguage: zh-CN,zh;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3.. Cook
ie: SESS3b0e658f87cf58240de13ab43a399df6=lju6o5bg8u04lv1ojugm2ccic6...
.
##
T 192.168.0.8:3981 -> 192.168.0.6:80 [ AP]
------ WebKitFormBoundarybLQwkp4opIEZn1fA..Content-Disposition: form-da
ta; name="n"....perfgeeks..------WebKitFormBoundarybLQwkp4opIEZn1fA..C
ontent-Disposition: form-data; name= "f"; filename="test.txt"..Content-
Type: text/plain....i am file..multipart/form-data..------WebKitFormBo
undarybLQwkp4opIEZn1fA --..
##
Comparing the response output, the $_POST data is consistent with the request submission data, that is, $_POST = array('n' => 'perfgeeks'). This also echoes the data in the http request body, and also shows that PHP fills the corresponding data into the $_POST global variable. The output of php://input is empty and nothing is output, although the body in the http request packet is not empty. This means that when Content-Type is multipart/form-data, even if there is data in the http request body, php://input is empty. At this time, PHP will not fill in the data into the php://input stream. Therefore, it is certain: php://input cannot be used to read enctype=multipart/form-data data.
Let’s compare the http request packets captured through ngrep this time. We will find that the biggest difference is that Content-Type is followed by boundary to define the delimiter of the data, and boundary is randomly generated. Another big difference is that the data organization structure in the http entity body is different.
In the previous section, we outlined that when the Content-Type is application/x-www-form-urlencoded, the php://input and $_POST data are "consistent", and for other Content-Type When php: //input and $_POST data are inconsistent. Because only when the Content-Type is application/x-www-form-urlencoded or multipart/form-data, PHP will fill in the corresponding part of the body data in the http request packet into the $_POST global variable. In other cases, PHP ignores both. Except for php://input, which is empty when the data type is multipart/form-data, it may not be empty in other situations. Through this section, we have a better understanding of the differences and connections between php://input and $_POST. So, confirm again that php://input cannot read enctype=multipart/form-data data. When php://input encounters it, it will always be empty, even if the http entity body has data.
php://input VS $http_raw_post_data
I believe everyone already has a certain in-depth understanding of php://input. So what is $http_raw_post_data? $http_raw_post_data is a global variable built into PHP. It is used by PHP to fill the POST data into the variable $http_raw_post_data as it is when the Content-Type cannot be recognized. It also cannot read POST data whose Content-Type is multipart/form-data. You need to set the always_populate_raw_post_data value in php.ini to On so that PHP will always fill in the POST data into the variable $http_raw_post_data.
Change the script phpinput_server.php to verify the above content
Copy the code The code is as follows:
$raw_post_data = file_get_contents('php://input', 'r');
$rtn = ($raw_post_data == $HTTP_RAW_POST_DATA) ? 1 : 0;
echo $rtn;
?>
Execute the test script
@php phpinput_post.php
@php phpinput_get.php
@php phpinput_xmlrpc.php
The result output is the same, that is Both are 1, indicating that php://input and $HTTP_RAW_POST_DATA are the same. As for the pressure on memory, we will not do detailed testing here. If you are interested, you can test and observe through xhprof.
With this, we can summarize this section as follows:
1, php://input can read the value of the specified length in the http entity body, and the length is specified by Content-Length, whether it is POST method or The data submitted by the GET method. However, generally when the GET method submits data, the http request entity body part is empty.
2. The data read by php://input and $HTTP_RAW_POST_DATA are the same. They only read data whose Content-Type is not multipart/form-data.
Study Notes
1. Coentent-Type will only include the http request data packet when the value is application/x-www-data-urlencoded and multipart/form-data. The corresponding data is filled in the global variable $_POST
2. When PHP cannot recognize the Content-Type type, the corresponding data in the http request package will be filled in the variable $HTTP_RAW_POST_DATA
3. Only the Coentent-Type is not When using multipart/form-data, PHP will not fill in the corresponding data in the http request packet into php://input, otherwise it will be the same in other situations. The length of the padding, specified by Coentent-Length.
4. Only when the Content-Type is application/x-www-data-urlencoded, the php://input data is consistent with the $_POST data.
5. php://input data is always the same as $HTTP_RAW_POST_DATA, but php://input is more efficient than $HTTP_RAW_POST_DATA and does not require special settings for php.ini
6. PHP will change the PATH field For the query_path part, fill in the global variable $_GET. Normally, the body of an http request submitted by the GET method is empty.
http://www.bkjia.com/PHPjc/325975.htmlwww.bkjia.comtruehttp: //www.bkjia.com/PHPjc/325975.htmlTechArticleIntroducing php://input, the PHP official manual document has a paragraph that clearly outlines it . “php://input allows you to read raw POST data. It is a less memory intensive altern...