對一php://input介紹,PHP官方手冊文檔有一段話對它進行了很明確地概述。
“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”.
翻譯過來,是這樣:
“php://input可以讀取沒有處理過的POST資料。相較於$HTTP_RAW_POST_DATA而言,它給記憶體帶來的壓力較小,並且不需要特殊的php.ini設定。php://input不能用於enctype=multipart/form-data”
我們應該怎麼去理解這段概述呢?!我把它劃分為三部分,逐步去理解。
讀取POST資料
不能用於multipart/form-data類型
php://input VS $HTTP_RAW_POST_DATA
讀取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與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.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; } ?> |
我們可以通過使用工具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]
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....
仔細觀察,我們不難發現
1,$_POST資料,php://input 資料與httpd entity body資料是“一致”的
2,http請求中的Content-Type是application/x-www-form-urlencoded ,它表示http請求body中的資料是使用http的post方法提交的表單資料,並且進行了urlencode()處理。
(注:注意加粗部分內容,下文不再提示).