ホームページ >バックエンド開発 >PHPチュートリアル >PHP 入力ストリーム php://input の概要_PHP チュートリアル

PHP 入力ストリーム php://input の概要_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-21 15:16:03812ブラウズ

php://input の概要については、PHP 公式マニュアル文書に明確に概要を説明した段落があります。

「php://input を使用すると、生の POST データを読み取ることができます。$HTTP_RAW_POST_DATA に代わるメモリ消費量が少なく、特別な php.ini ディレクティブは必要ありません。php://input は enctype=”multipart では使用できません。」 /form-data"。
翻訳すると、次のようになります。
"php://input は、未処理の POST データを読み取ることができます。 $HTTP_RAW_POST_DATA と比較すると、メモリへの負担が少なく、特別な php.ini 設定は必要ありません。 php://input は enctype=multipart/form-data には使用できません

この概要をどのように理解すればよいでしょうか?! 3 つの部分に分けて段階的に理解していきます
POST データを読む
multipart には使用できません。 /form-data type
php://input VS $HTTP_RAW_POST_DATA
POST データの読み取り

PHP を使用する人は、組み込み変数 $_POST についてよく知っている必要があります。$_POST と php://input の関係と違いは何ですか?さらに、POST に加えて、クライアントがサーバーとデータを交換するために最も一般的に使用されるメソッドは GET です。php://input は PHP 入力ストリームとして使用されるため、これら 2 つの質問はまさに私たちが考えているものです。
議論の主な内容は、テストと観察からの要約が非常に効果的な方法であることを示しています。

@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 リクエストの発行をシミュレートします。 192.168.0.8 :/phpinput_get.php は、GET メソッドを使用してフォーム番号の送信をシミュレートします
phpinput_server.php および 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";

; //@file phpinput_post.php
$http_entity_body = 'n=' .urldecode('7788'); -form-urlencoded';
$http_entity_length = strlen($http_entity_body);
$path = '/phpinput_server.php';ホスト、$ ポート、$error_no、$error_desc、30);
if ($fp) {
fputs($fp, "POST {$path} HTTP/1.1rn"); $host} rn");
fputs($fp, "Content-Type: {$http_entity_type}rn");
fputs($fp, "Content-Length: {$http_entity_length}rn");
fputs($fp , "接続: closenrn");
fputs($fp, $http_entity_body . "rnrn");

while (!feof($fp)) {
$d .= fgets($fp, 4096); fclose($ fp);
echo $d;
}
?> ツール ngrep を使用して http リクエスト パケットをキャプチャできます (検出する必要があるのは php://input であるため、http のみをキャプチャします)ここでパケットをリクエストしてください)。テスト スクリプト 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: charset=UTF-8
------$_POST------ -- ---------
配列(2) {
["n"]=> 文字列(9) "perfgeeks"
["p"]=> 文字列(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..
ホスト: 192.168.0.6..Content-Type: application/x-www-form-urlencoded..Co
ntent -長さ: 18..接続: close....n=perfgeeks&p=7788....
注意深く見ると、
1、$_POST データ、php://input データ、および httpd エンティティ本体データが "
2 と一致し、http リクエストの Content-Type は application/x-www-form-urlencoded です。これは、http リクエスト本文のデータが http の post メソッドを使用して送信されたフォーム データであり、によって処理されたことを意味します。 urlencode() 。
(注: 以下ではプロンプトが表示されない太字の部分に注意してください)

POST メソッドによって送信された xml-rpc リクエストをシミュレートするスクリプト phpinput_xmlrpc.php の元のファイルの内容を見てみましょう。



//@file phpinput_xmlrpc.php
$http_entity_body = "nn jt_userinfon";
$http_entity_type = 'text/html';
$http_entity_length = strlen($http_entity_body);
$ホスト = '192.168.0.6';
$ポート = 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}rn");
fputs($fp, "Content-Type: {$http_entity_type}rn");
fputs($fp, "コンテンツの長さ: {$http_entity_length}rn");
fputs($fp, "接続: より近いnrn");
fputs($fp, $http_entity_body . "rnrn");
while (!feof($fp)) {
$d .= fgets($fp, 4096);
}

fclose($fp);
エコー $d;
}
?>
同样地,让我们来执行这个测试

@php /phpinput_xmlrcp.php
HTTP/1.1 200 OK
Date: Thu, 08 Apr 2010 03:47:18 GMT
Server: Apache/2.2.3 (C entOS)
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..
ホスト: 192.168.0.6..Content-Type: text/html..Content-Length: 75..Connect
tion: close.. ...<メソッドコール>。 <名前>jt_userinfo<
/name>.....
同様に、私も次のように簡単に発行できます:
1、http 要求内の Content-Type は text/xml です。http 要求内の body データは次のとおりです。
2、サービス エンド $_POST は空数の集合であり、http エンティティ本体とは一致しません。この例では、この例の Content-Type は application/ ではなく text/xml です。 x-www-form-urlencoded
3 ですが、php://input データも http エンティティ本体データと一致します。つまり、php://input データと $_POST データは一致しません。表データの場合、php://input は GET メソッドの表データを取得できませんか? ここで、phpinput_server.php ファイルを追加して、$_POST を $_GET に変更します。
代码如下:


//@file phpinput_server.php $raw_post_data = file_get_contents('php://input', 'r'); エコー「----------$_GET---------------------n」; エコー var_dump($_GET) 。 「ん」; echo "----------php://input-------------n";

$raw_post_data をエコーし​​ます。 「ん」;
?>
//@file phpinput_get.php
$query_path = 'n=' 。 urldecode('perfgeeks') 。 '&p=' 。 urldecode('7788');
$ホスト = '192.168.0.6';
$ポート = 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}rn");
fputs($fp, "接続: より近いnrn");

while (!feof($fp)) {
$d .= fgets($fp, 4096);
}
fclose($fp);
エコー $d;
}
?>


同様に、次の phpinput_get.php テスト スクリプトを実行します。これは、フォーム データを送信するための通常の GET メソッドをシミュレートします。

@php /phpinput_get.php
HTTP/1.1 200 OK
日付: 木、08 Apr 2010 07:38:15 GMT
サーバー: 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-------------- ----
配列(2) {
["n"]=>
文字列(9) "perfgeeks"
["p"]=>
文字列(4) "7788"

-- -----php://input---------------
このとき、ngrep ツールを使用してキャプチャされた、対応する http リクエスト パケットは次のとおりです

T 192.168.0.8:36775 - > 192.168.0.6:80 [AP]
GET /phpinput_server.php?n=perfgeeks&p=7788 HTTP/1.1..
ホスト: 192.168.0.6..接続: close....
POST によって送信された http リクエストを比較通常、GET メソッドによって送信されたリクエストでは、エンティティ本文は空です。同時に、Content-Type と Content-Length は指定されません。ただし、データ http エンティティ本体を強制し、正しい Content-Type と Content-Length を指定した場合、php://input は引き続き http エンティティ本体データを読み取ることができますが、$_GET データは読み取ることができません。

上記の検出に基づいて、次の要約を作成できます:
1. Content-Type 値が application/x-www-form-urlencoded の場合、php は http リクエスト本文の対応するデータを配列に書き込みます。 $ _POST、$_POST 配列に入力されたデータは、urldecode() 解析の結果です。 (実際には、Content-Type に加えて、データがフォームデータであることを示す multipart/form-data もあります。これについては後ほど紹介します)
2, php://input データ、Content-タイプが multipart/form-data ではありません (条件付き制限は後で導入されます)。 php://input データは、データの http エンティティ本体部分と一致します。この部分的に一貫したデータの長さは、Content-Length によって指定されます。
3. Content-Type が application/x-www-form-urlencoded で、送信メソッドが POST メソッドである場合にのみ、$_POST データと php://input データが「一致」します (引用符で囲まれていることを示します)。形式は一貫していませんが、コンテンツは一貫しています)。そうでなければ、それらは矛盾します。
4、php://input は $_GET データを読み取ることができません。これは、$_GET データが http リクエストの本文部分ではなく、http リクエスト ヘッダーの PATH フィールドに query_path として書き込まれているためです。

これは、xml_rpc サーバーが file_get_contents(‘php://input’, ‘r’) を通じてデータを読み取る理由を理解するのにも役立ちます。 $_POST から読み取るのではなく、xml_rpc のデータ仕様が xml であり、その Content-Type が text/xml であるためです。
php://input は multipart/form-data と遭遇します

ファイルをアップロードするとき、フォームは次のように書かれます


コードをコピーします コードは次のとおりです:

gt;




そして、ここでの enctype=multipart/form-data の意味は、http リクエストのヘッダーの Content-Type を multipart/form-data に設定することです。説明については RFC1867 を確認してください。 multipart/form-data は、POST メソッドを使用してフォーム データを送信することを意味し、ファイルのアップロードも伴うため、application/x-www-form-urlencoded データ形式とは異なります。より合理的かつ効率的なデータ形式でサーバーに渡されます。次のように、フォーム データを送信し、応答結果を出力します。

------$_POST------
array(1) { [ "n"]=> string(9) "perfgeeks" }
----------php://input-------------
同時に、対応する http リクエスト パケットは次のとおりです:

########
T 192.168.0.8:3981 -> 192.168.0.6:80 [AP]
POST /phpinput_server.php HTTP/1.1。 .ホスト: 192.168 .0.6..接続: kee
p-alive..ユーザーエージェント: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) A
ppleWebKit/533.2 (Gecko のような KHTML) 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; border=----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 -文字セット: GBK ,utf-8;q=0.7,*;q=0.3..クック
ie: SESS3b0e658f87cf58240de13ab43a399df6=lju6o5bg8u04lv1ojugm2ccic6...
##
T 192.168.0.8:3 981 -> 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....私は file..multipart/form-data.. WebKitFormBo
undarybLQwkp4opIEZn1fA-- ..
##
応答出力と比較すると、$_POST データは要求送信データと一致しています。つまり、$_POST = array('n' => 'perfgeeks') です。これは、http リクエスト本文のデータもエコーし、PHP が対応するデータを $_POST グローバル変数に入力することも示します。 http リクエスト パケットの本文は空ではありませんが、php://input の出力は空で何も出力されません。これは、Content-Type が multipart/form-data の場合、HTTP リクエストボディにデータがあっても、php://input が空になることを意味します。このとき、PHP は php:// にデータを入力しません。入力ストリーム。したがって、php://input を使用して enctype=multipart/form-data データを読み取ることはできないことは確かです。

今回はngrepでキャプチャしたhttpリクエストパケットを比較してみましょう。最大の違いは、Content-Typeの後にデータの区切り文字を定義するboundaryがあり、boundaryがランダムに生成されることです。もう 1 つの大きな違いは、http エンティティ本体のデータ構成構造が異なることです。

前のセクションでは、Content-Type が application/x-www-form-urlencoded である場合、php://input と $_POST データは、他の Content-Type である php の場合に「一貫性がある」ことを説明しました。 //入力データと $_POST データが矛盾しています。 Content-Type が application/x-www-form-urlencoded または multipart/form-data の場合にのみ、PHP は http リクエスト パケット内の本文データの対応する部分を $_POST グローバル変数に埋め込むためです。 , PHP は両方を無視します。データ型が multipart/form-data の場合は php://input が空であることを除き、他の状況では空にならない場合があります。 このセクションを通じて、php://input と $_POST の違いと関係についてより深く理解できました。したがって、php://input が enctype=multipart/form-data データを読み取ることができないことを再度確認してください。php://input がそれに遭遇すると、http エンティティ本体にデータがある場合でも、常に空になります。
php://input VS $http_raw_post_data

誰もがすでに php://input についてある程度深く理解していると思います。では、$http_raw_post_data とは何でしょうか? $http_raw_post_data は、PHP に組み込まれているグローバル変数です。これは、Content-Type が認識できない場合に、POST データを変数 $http_raw_post_data にそのまま埋めるために PHP によって使用されます。また、Content-Type が multipart/form-data である POST データを読み取ることもできません。 PHP が常に POST データを変数 $http_raw_post_data に入力できるように、php.ini の always_populate_raw_post_data 値を On に設定する必要があります。

スクリプト phpinput_server.php を変更して上記の内容を確認します


コードをコピーします コードは次のとおりです:
$raw_post_data = file_get_contents('php://input', 'r' );
$rtn = ($raw_post_data == $HTTP_RAW_POST_DATA)
エコー $rtn;
テストスクリプトを実行します

@php phpinput_post.php
@php phpinput_get.php
@php phpinput_xmlrpc.php

結果の出力は同じです。つまり、両方とも 1、つまり php://input と $HTTP_RAW_POST_DATAは同一です。メモリへの負荷に関しては、ここでは詳細なテストは行いません。興味があれば、xhprof を通じてテストして観察することができます。

これで、このセクションは次のように要約できます:
1、php://input は、http エンティティ本体で指定された長さの値を読み取ることができます。長さは、送信されたデータであるかどうかにかかわらず、Content-Length によって指定されます。 POST メソッドまたは GET メソッドによって。ただし、通常、GET メソッドがデータを送信するとき、http リクエスト エンティティの本体部分は空です。
2. php://input と $HTTP_RAW_POST_DATA で読み取られるデータは、Content-Type が multipart/form-data ではないデータのみを読み取ります。
勉強メモ

1. Coentent-Type は、値が application/x-www-data-urlencoded および multipart/form-data 変数の場合にのみ、http リクエスト パケット内の対応するデータをグローバルに書き込みます
2。 Content-Type タイプが PHP によって認識されない場合、http リクエスト パッケージ内の対応するデータは変数 $HTTP_RAW_POST_DATA に入力されます
3. Coentent-Type が multipart/form-data でない場合にのみ、PHP はhttp リクエスト パケット内の対応するデータは php://input に入力されます。それ以外の場合は、他の状況でも同じになります。 Coentent-Length で指定されるパディングの長さ。
4. Content-Type が application/x-www-data-urlencoded の場合のみ、php://input データは $_POST データと一致します。
5. php://input データは常に $HTTP_RAW_POST_DATA と同じですが、php://input は $HTTP_RAW_POST_DATA よりも効率的であり、php.ini の特別な設定を必要としません。
6. PATH フィールドにグローバル変数 $_GET を入力します。通常、GET メソッドによって送信される http リクエストの本文は空です。

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/325975.html技術記事 php://input の概要については、PHP 公式マニュアル文書に明確に概要を説明した段落があります。 「php://input を使用すると、生の POST データを読み取ることができます。これはメモリ消費量が少ない代替手段です...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。