The difference between PHP input stream php://input and Post/get

Source: Internet
Author: User
Tags http post http request mongodb php and postgresql redis centos firewall


PHP input Stream Php://input
When using XML-RPC, the server gets the client data, mainly through the PHP input stream, rather than the $_post array. So, here's the main discussion of PHP input stream php://input
For the 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 the outline? 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


@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.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:



$_post data, php://input data is "consistent" with httpd entity body data.
The Content-type in the 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 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.



//@file phpinput_xmlrpc.php
$http _entity_body = "\n\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;
}
Similarly, 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

HTTP request is text/xml. It indicates that the body data in an HTTP request is an XML data format. The
server-side $_post prints an empty array that is inconsistent with the HTTP entity body. This is different from the previous example, where the content-type is text/xml rather than application/x-www-form-urlencoded
and php://input data or HTTP entity The body data is consistent. 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 for the Got method? Here, we change the phpinput_server.php file slightly, change $_post to $_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"; The
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.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;
 }
Similarly, 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:



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 $_post array of data is for UrlDecode ( ) The result of the resolution. (In fact, in addition to the Content-type, there are multipart/form-data to represent the data is form data, later we introduce)
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.
When Content-type is application/x-www-form-urlencoded and the Submit method is a post method, the $_post data is "consistent" with the Php://input data (quotes to indicate that they are inconsistent in format, Content). In other cases, they are inconsistent.
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 uploading files, the form is written like this:



<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 is not the same as 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 is application/x-www-form-urlencoded, php://input and $_post data are "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.



To change the script phpinput_server.php, you can verify the above:



$raw _post_data = file_get_contents (' php://input ', ' R ');
$rtn = ($raw _post_data = = $HTTP _raw_post_data)? 1:0;
Echo $rtn;



To execute a 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:



Php://input can read the value of the specified length in the HTTP entity body, specifying the length by 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.
Php://input and $http_raw_post_data read the same data and read only Content-type data that is not multipart/form-data.
Summary



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



PHP does not recognize the type of Content-type, the HTTP request package will be filled with the corresponding data in the variable $http_raw_post_data
PHP does not populate the HTTP request packets with the corresponding data in the Php://input unless the coentent-type is multipart/form-data, otherwise it will. The length of the fill, specified by Coentent-length.



Only when Content-type is application/x-www-data-urlencoded, php://input data is consistent with $_post data.
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



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.


Alibaba Cloud Hot Products

Elastic Compute Service (ECS) Dedicated Host (DDH) ApsaraDB RDS for MySQL (RDS) ApsaraDB for PolarDB(PolarDB) AnalyticDB for PostgreSQL (ADB for PG)
AnalyticDB for MySQL(ADB for MySQL) Data Transmission Service (DTS) Server Load Balancer (SLB) Global Accelerator (GA) Cloud Enterprise Network (CEN)
Object Storage Service (OSS) Content Delivery Network (CDN) Short Message Service (SMS) Container Service for Kubernetes (ACK) Data Lake Analytics (DLA)

ApsaraDB for Redis (Redis)

ApsaraDB for MongoDB (MongoDB) NAT Gateway VPN Gateway Cloud Firewall
Anti-DDoS Web Application Firewall (WAF) Log Service DataWorks MaxCompute
Elastic MapReduce (EMR) Elasticsearch

Alibaba Cloud Free Trail

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.