For a php://input introduction, the PHP Official Handbook document has a very clear overview of it.
"Php://input allows to read raw POST data. It is a less memory intensive alternative to $HTTP _raw_post_data and does no need any special php.ini. Php://input is isn't available with enctype= "Multipart/form-data".
Translation over, is this:
"Php://input can read post data that has not been processed. Compared to $http_raw_post_data, it brings less pressure on memory and does not require special php.ini settings. Php://input cannot be used for Enctype=multipart/form-data "
What should we do to understand this overview?! I divided it into three parts, gradually to understand.
Reading post data
cannot be used for multipart/form-data types
Php://input VS $HTTP _raw_post_data
Reading post data
Phper must be familiar with the built-in variable $_post. What are the correlations and differences between $_post and php://input? In addition, the client interacts with the server side of the data, the most commonly used method in addition to post, there are get. Since Php://input is a PHP input stream, does it read get data? These two questions are the main elements that we need to explore in this section.
Experience tells us that it is a very effective way to summarize the tests and observations. Here, I wrote a few scripts to help us test.
@file 192.168.0.6:/phpinput_server.php to print out the received data
@file 192.168.0.8:/phpinput_post.php simulation submits form data by post method
@file 192.168.0.8:/phpinput_xmlrpc.php Impersonation to issue a XMLRPC request with a POST method.
@file 192.168.0.8:/phpinput_get.php simulate the number of forms submitted by a Get method
Phpinput_server.php and phpinput_post.php
<?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";
?>
<?php
@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.1\r\n");
Fputs ($FP, "Host: {$host}\r\n");
Fputs ($FP, "Content-type: {$http _entity_type}\r\n");
Fputs ($FP, "content-length: {$http _entity_length}\r\n");
Fputs ($fp, "connection:close\r\n\r\n");
Fputs ($fp, $http _entity_body. "\r\n\r\n");
while (!feof ($fp)) {
$d. = Fgets ($fp, 4096);
}
Fclose ($FP);
Echo $d;
}
?>
We can grab the HTTP request pack by using the tool Ngrep (because we need to be able to detect the php://input, so we only crawl the HTTP requests packet here). We're going to execute the test script phpinput_post.php
@php/phpinput_post.php
http/1.1 OK
Date:thu, APR 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 packets captured via Ngrep are 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 .....
Careful observation, we are not difficult to find
1,$_post data, php://input data is "consistent" with httpd entity body data
The Content-type in the 2,http request is application/x-www-form-urlencoded, which means that the data in the body of the HTTP request is the form data submitted using the HTTP POST method and is UrlEncode () processing.
(Note: Note The bold part of the content, no longer 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 a POST method.
<?php
@file phpinput_xmlrpc.php
$http _entity_body = "\ n \ jt_userinfo\n";
$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.1\r\n");
Fputs ($FP, "Host: {$host}\r\n");
Fputs ($FP, "Content-type: {$http _entity_type}\r\n");
Fputs ($FP, "content-length: {$http _entity_length}\r\n");
Fputs ($fp, "connection:close\r\n\r\n");
Fputs ($fp, $http _entity_body. "\r\n\r\n");
while (!feof ($fp)) {
$d. = Fgets ($fp, 4096);
}
Fclose ($FP);
Echo $d;
}
?>
Again, let's execute this test script
@php/phpinput_xmlrcp.php
http/1.1 OK
Date:thu, APR 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-------------
<?xml version= "1.0" >
<methodcall>
<name>jt_userinfo</name>
</methodcall>
When executing this script, the HTTP request packets we crawled through the ngrep are as follows
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....<?xml version= "1.0" >.<METHODCALL>. <name>jt_userinfo<
/name>.</methodcall>
Similarly, I can easily find the sample:
The Content-type in the 1,http request is text/xml. It indicates that the body data in an HTTP request is an XML data format.
2, the service-side $_post print out is an empty array, which is inconsistent with the HTTP entity body. This is not the same as the previous example, where the Content-type is text/xml, not application/x-www-form-urlencoded
3, and the Php://input data is consistent with the HTTP entity body data. That is, php://input data is inconsistent with $_post data.
Let's take a look at the case where the form data is submitted through the Get method, can php://input read the form data of the Got method? Here, we change the phpinput_server.php file slightly, change $_post to $_get.
Copy Code code as follows:
<?php
@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";
?>
<?php
@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.1\r\n ");
Fputs ($FP, "Host: {$host}\r\n");
Fputs ($fp, "connection:close\r\n\r\n");
while (!feof ($fp)) {
$d. = Fgets ($fp, 4096);
}
Fclose ($FP);
Echo $d;
}
?>
Again, we execute the next phpinput_get.php test script, which simulates a typically get method to submit the form data.
@php/phpinput_get.php
http/1.1 OK
Date:thu, APR 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 packets captured are 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 .....
Compares the HTTP request submitted by the Post method, in which the entity body is usually empty in the request submitted by the Get method. At the same time, Content-type and content-length are not specified. However, if the hard data HTTP entity body, and indicates that the correct content-type and content-length, then php://input also read the HTTP entity body data, but not $_get data.
Based on the above several probes, we can make the following summary:
1,content-type value is application/x-www-form-urlencoded, PHP will fill the HTTP request body corresponding data into the array $_post, fill in the $_ The data in the post array is the result of UrlDecode () parsing. (In fact, in addition to the Content-type, there are multipart/form-data to represent the data is form data, later we introduce)
2,php://input data, as long as the Content-type is not multipart/form-data (this condition is described later). Then the php://input data is consistent with the HTTP entity body part data. The length of the consistent data in this section is specified by Content-length.
3, the $_post data is "consistent" with the Php://input data only when Content-type is application/x-www-form-urlencoded and the Submit method is a post method (quotes, indicating that they are inconsistent in format, Content). In other cases, they are inconsistent.
4,php://input cannot read $_get data. This is because the $_get data is written in the path field of the HTTP request header (header) as Query_path, rather than in the body portion 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 because the XML_RPC data specification is XML and its content-type is text/xml.
Php://input met Multipart/form-data.
When you upload a file, the form is written like this.
Copy Code code as follows:
<form enctype= "Multipart/form-data" action= "phpinput_server.php" method= "POST" >
<input type= "text" name= "n"/>
<input type= "file" name= "F"/>
<input type= "Submit" value= "Upload Now"/>
</form>
So, the enctype=multipart/form-data here is to set the Content-type in the head of the HTTP request to Multipart/form-data. Please refer to RFC1867 's description of it. Multipart/form-data also indicates that the form data is submitted by post and is accompanied by a file upload, so it will be different from the application/x-www-form-urlencoded data format. It will be delivered to the server in a more reasonable, more efficient data format. We submit the form data and print out the results of the response as follows:
-------$_post------------------
Array (1) {["n"]=> string (9) "Perfgeeks"}
-------Php://input-------------
At the same time, the corresponding HTTP request packets we crawled through the 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--..
##
From the response output, the $_post data matches the request submission data, i.e. $_post = Array (' n ' => ' Perfgeeks '). This also echoes the data in the body of the HTTP request, and it shows that PHP fills the corresponding data into the $_post global variable. The php://input output is empty and nothing is exported, although the body is not empty in the HTTP request packet. This means that when Content-type is multipart/form-data, even if there is data in the body of the HTTP request, Php://input is empty, PHP will not fill the data into the Php://input stream at this time. Therefore, you can determine that: Php://input cannot be used to read enctype=multipart/form-data data.
Let's compare this HTTP request packet through Ngrep crawl, and we'll find that the biggest difference is that Content-type follows the boundary that defines the data, Bounday is randomly generated. Another big difference is that the data structure in the HTTP entity body is different.
In the previous section, we outlined that when Content-type for application/x-www-form-urlencoded, Php://input and $_post data were "consistent" for other Content-type, PHP:/ /input and $_post data data are inconsistent. Because only when Content-type is application/x-www-form-urlencoded or Multipart/form-data, PHP fills in the corresponding part of the body data in the HTTP request packet $_ In the post global variable, PHP is ignored in other cases. Php://input, in addition to being empty except when the data type is multipart/form-data, may not be empty. Through this section, we understand the difference and connection between Php://input and $_post. So, again confirm, Php://input can't read enctype=multipart/form-data data, when Php://input encounters it, always be empty, even if the HTTP entity body has data.
Php://input VS $http _raw_post_data
I believe we have a certain depth of understanding of the php://input. So what is $http_raw_post_data? $http _raw_post_data is a global variable built into PHP. It is used for PHP, in the case of unrecognized content-type, to fill the post data into the variable $http_raw_post_data. It also fails to read post data that Content-type is multipart/form-data. You need to set the Always_populate_raw_post_data value in php.ini to on,php to always fill in the post data into the variable $http_raw_post_data.
Change the script phpinput_server.php to verify the above
Copy Code code as follows:
<?php
$raw _post_data = file_get_contents (' php://input ', ' R ');
$rtn = ($raw _post_data = = $HTTP _raw_post_data)? 1:0;
Echo $rtn;
?>
Execute test Script
@php phpinput_post.php
@php phpinput_get.php
@php phpinput_xmlrpc.php
The resulting output is the same, that is, 1, which means that php://input and $http_raw_post_data are the same. As for the pressure on the memory, we do not do a careful test here. Interested, can be tested and observed through XHPROF.
In this case, we can conclude this section as follows:
1, Php://input can read the value of the specified length in the HTTP entity body, by specifying the length of the content-length, either by post or by the data submitted by the Get method. However, when the general get method submits the data, the HTTP request Entity body section is empty.
2,php://input and $http_raw_post_data read the same data and read only Content-type data that is not multipart/form-data.
Learn notes
1,coentent-type only if the value is application/x-www-data-urlencoded and Multipart/form-data two, PHP will fill the HTTP request packet with the corresponding data in the global variable $_ POST
2,php Unrecognized content-type type, the corresponding data in the HTTP request package is filled into the variable $http_raw_post_data
3, PHP will not fill in the HTTP request packets of the corresponding data in the Php://input, otherwise, only when Coentent-type is not multipart/form-data. The length of the fill, specified by Coentent-length.
4, php://input data is consistent with $_post data only when Content-type is application/x-www-data-urlencoded.
5,php://input data is always the same as $http_raw_post_data, but php://input is more effective than $http_raw_post_data and does not require special settings php.ini
6,php fills the query_path portion of the path field into the global variable $_get. Normally, the body is empty for the HTTP request submitted by the Get method.