当前位置:编程学习 > php >>

PHP输入流php://input

PHP输入流php://input
在使用xml-rpc的时候,server端获取client数据,主要是通过php输入流input,而不是$_POST数组。所以,这里主要探讨php输入流php://input
对一php://input介绍,PHP官方手册文档有一段话对它进行了很明确地概述。
“php://input allows you to read raw POST data. It is a less memoryintensive alternative to $HTTP_RAW_POST_DATA and does not need any specialphp.ini directives. php://input is not available withenctype=”multipart/form-data”.
翻译过来,是这样:
“php://input可以读取没有处理过的POST数据。相较于$HTTP_RAW_POST_DATA而言,它给内存带来的压力较小,并且不需要特殊的php.ini设置。php://input不能用于enctype=multipart/form-data”
我们应该怎么去理解这段概述呢?!
我把它划分为三部分,逐步去理解。
1) 读取POST数据
2) 不能用于multipart/form-data类型
3) php://input VS $HTTP_RAW_POST_DATA
1 . 读取POST数据
PHPer们一定很熟悉$_POST这个内置变量。$_POST与php://input存在哪些关联与区别呢?另外,客户端向服务端交互数据,最常用的方法除了POST之外,还有GET。既然php://input作为PHP输入流,它能读取GET数据吗?这二个问题正是我们这节需要探讨的主要内容。
经验告诉我们,从测试与观察中总结,会是一个很凑效的方法。这里,我写了几个脚本来帮助我们测试。
@file 192.168.0.6:/phpinput_server.php 打印出接收到的数据
@file 192.168.0.8:/phpinput_post.php  模拟以POST方法提交表单数据
@file 192.168.0.8:/phpinput_xmlrpc.php模拟以POST方法发出xmlrpc请求.
@file 192.168.0.8:/phpinput_get.php   模拟以GET方法提交表单表数
phpinput_server.php
1. <?php 
2. //@file phpinput_server.php 
3. $raw_post_data = file_get_contents('php://input', 'r'); 
4. echo "-------\$_POST------------------\n"; 
5. echo var_dump($_POST) . "\n"; 
6. echo "-------php://input-------------\n"; 
7. echo $raw_post_data . "\n"; 
8. ? 
 phpinput_post.php:
1. <?php 
2. //@file phpinput_post.php 
3. $http_entity_body = 'n=' .urldecode('perfgeeks') . '&p=' . urldecode('7788'); 
4. $http_entity_type ='application/x-www-form-urlencoded'; 
5. $http_entity_length =strlen($http_entity_body); 
6. $host = '192.168.0.6'; 
7. $port = 80; 
8. $path = '/phpinput_server.php'; 
9. $fp = fsockopen($host, $port, $error_no,$error_desc, 30); 
10. if ($fp) { 
11.  fputs($fp, "POST {$path} HTTP/1.1\r\n"); 
12.  fputs($fp, "Host: {$host}\r\n"); 
13.   
14.  fputs($fp, "Content-Type: {$http_entity_type}\r\n"); 
15.  fputs($fp, "Content-Length: {$http_entity_length}\r\n"); 
16.  fputs($fp, "Connection: close\r\n\r\n"); 
17.  fputs($fp, $http_entity_body . "\r\n\r\n"); 
18.   
19.  while (!feof($fp)) { 
20.    $d .= fgets($fp, 4096); 
21.   } 
22.  fclose($fp); 
23.  echo $d; 
24. } 
25. ?> 
我们可以通过使用工具ngrep抓取http请求包(因为我们需要探知的是php://input,所以我们这里只抓取http Request数据包)。我们来执行测试脚本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
通过ngrep抓到的http请求包如下:
T 192.168.0.8:57846 -> 192.168.0.6:80[AP]
  Host: 192.168.0.6
Content-Type: application/x-www-form-urlencoded
Content-Length: 18
Connection: close
 
n=perfgeeks&p=7788
 
仔细观察,我们不难发现
1,$_POST数据,php://input数据与httpd entity body数据是“一致”的
2,http请求中的Content-Type是application/x-www-form-urlencoded ,它表示http请求body中的数据是使用http的post方法提交的表单数据,并且进行了urlencode()处理。
我们再来看看脚本phpinput_xmlrpc.php的原文件内容,它模拟了一个POST方法提交的xml-rpc请求。
1. <?php 
2. //@file phpinput_xmlrpc.php 
3.   
4. $http_entity_body = "\n\n   jt_userinfo\n"; 
5. $http_entity_type= 'text/html'; 
6. $http_entity_length =strlen($http_entity_body); 
7.   
8. $host = '192.168.0.6'; 
9. $port = 80; 
10. $path = '/phpinput_server.php'; 
11. $fp = fsockopen($host, $port, $error_no,$error_desc, 30); 
12. if ($fp) { 
13.  fputs($fp, "POST {$path} HTTP/1.1\r\n"); 
14.  fputs($fp, "Host: {$host}\r\n"); 
15.   
16.  fputs($fp, "Content-Type: {$http_entity_type}\r\n"); 
17.  fputs($fp, "Content-Length: {$http_entity_length}\r\n"); 
18.  fputs($fp, "Connection: close\r\n\r\n"); 
19.  fputs($fp, $http_entity_body . "\r\n\r\n"); 
20.  while (!feof($fp)) { 
21.    $d .= fgets($fp, 4096); 
22.   } 
23.   
24.  fclose($fp); 
25.  echo $d; 
26. } 
27. ?> 
同样地,让我们来执行这个测试脚本
@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-------------
<?xml version="1.0">
<methodcall>
   <name>jt_userinfo</name>
</methodcall>
 
执行这个脚本的时候,我们通过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
Connection: close
1. <?xml version="1.0">.<methodcall>.   <name>jt_userinfo< 
2.  /name>.</methodcall>.... 
同样,我样也可以很容易地发现:
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数据还是跟httpentity body数据一致。也就是php://input数据和$_POST数据不一致了。
我们再来看看通过GET方法提交表单数据的情况,php://input能不能读取到GET方法的表单数据?在这里,我们稍加改动一下phpinput_server.php文件,将$_POST改成$_GET。
1. <?php 
2. //@file phpinput_server.php 
3. $raw_post_data =file_get_contents('php://input', 'r'); 
4. echo"-------\$_GET------------------\n"; 
5. echo var_dump($_GET) . "\n"; 
6. echo"--

补充:Web开发 , php ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,