ホームページ > php教程 > php手册 > PHP 入力ストリームの概要 php://input

PHP 入力ストリームの概要 php://input

WBOY
リリース: 2016-06-13 11:58:07
オリジナル
1207 人が閲覧しました

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 設定は必要ありません。 enctype=multipart/form-data には php://input は使用できません。

この概要を 3 つの部分に分けて段階的に理解していきます。
POST データを読みます。
multipart/form-data タイプには使用できません
php://input VS $HTTP_RAW_POST_DATA
POST データの読み取り

PHP 使用者は、組み込み変数 $_POST $ に精通している必要があります。 _POST と php://input の関係と違いは何ですか? また、php://input は PHP 入力ストリームであるため、クライアントがサーバーと対話するために最も一般的に使用されるメソッドは GET です。 GET データを読む? これら 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 リクエストの発行をシミュレートします。
@file 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) "; ";
echo "----------php://input-------------n";
echo $raw_post_data . "n";
? >

//@file phpinput_post.php
$http_entity_body = 'n=' .urldecode('7788') );
$http_entity_type = 'application/x-www-form-urlencoded';
$http_entity_length = strlen($http_entity_body);
$host = '192.168.0.6'; 80;
$path = '/phpinput_server.php';
$fp = fsockopen($host, $port, $error_desc, 30);
if ($fp); fputs($fp, "POST {$path} HTTP/1.1rn");
fputs($fp, "ホスト: {$host}rn"); {$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: text/html- 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..
ホスト: 192.168.0.6..Content-Type: application/x-www-form-urlencoded..Co
ntent-Length: 18.接続: close....n=perfgeeks&p=7788....
注意深く見ると、
1、$_POST データ、php://input データ、および httpd エンティティ本体データが "これは、http リクエスト本文のデータが http の post メソッドを使用して送信されたフォーム データであることを意味します。 urlencode() によって処理されました。
(注: 以下ではプロンプトが表示されない太字の部分に注意してください)。

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



//@file phpinput_xmlrpc.php
$http_entity_body = "nn jt_userinfon";
$http_entity_type = 'text/html';
$http_entity_length = strlen($http_entity_body);
$host = '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, "Content-Length: {$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
サーバー: 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-------------


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
ション: 閉じる.....。 <名前>jt_userinfo<
/name>.
....
同様に、私も簡単に次のように発行できます:
1、http 要求中の Content-Type は text/xml です。http を示します。
2 では、サービス エンド $_POST が印刷されるが、http エンティティの本文とは一致しません。この例では、Content-Type がtext/xml は、application/x-www-form-urlencoded
3 ではなく、php://input データも、http エンティティ本体データと一致します。つまり、php://input データと $_POST データは一致しません。

我们稍加改一下phpinput_server.php文件,将$ _POST 変更 $_GET。

复制代 代以下:


// @file phpinput_server.php
$raw_post_data = file_get_contents('php://input', 'r');
エコー「------$_GET------n」;
エコー var_dump($_GET) 。 「ん」;
エコー "------php://input-------------n";
$raw_post_data をエコーし​​ます。 「ん」;
?>
//@file phpinput_get.php
$query_path = 'n=' 。 urldecode('perfgeeks') 。 '&p=' 。 urldecode('7788');
$host = '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-8

- -------$_GET------
array(2) {
["n"]=> 9) "perfgeeks"
["p"]=>
string(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....
によって送信された http リクエストを比較しますPOST メソッド (通常、GET メソッドによって送信されたリクエストでは、エンティティ本文は空です)。同時に、Content-Type と Content-Length は指定されません。ただし、データ http エンティティ本体を強制し、正しい Content-Type と Content-Length を指定した場合、php://input は引き続き http エンティティ本体データを読み取ることができますが、$_GET データは読み取ることができません。

上記の検出に基づいて、次のような要約を行うことができます:
1. Content-Type 値が application/x-www-form-urlencoded の場合、PHP は本文の対応するデータを要求します。 $_POST 配列に埋められるデータは、urldecode() の解析の結果です。 (実際には、Content-Type に加えて、データがフォーム データであることを示す multipart/form-data もあります。これについては後で紹介します)
2、php://input データ。 Content-Type が 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 に遭遇しました

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


コードをコピー コードは次のとおりです。

input type="text" name="n" />




そして、ここでの 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-------------
同時に、ngrep を通じてキャプチャした対応する http リクエスト パケットは次のとおりです。

######
T 192.168.0.8:3981 -> :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)
ppleWebKit/533.2 (KHTML、Gecko など) Chrome/5.0.342.3 Safari/533.2..Re
フェラー: http://192.168.0.6/phpinput_server..Content-長さ: 306 ..Ca
che-Control: max-age=0..Origin: http://192.168.0.6..Content-Type: mult
ipart/form-data; -WebKitFormBoundarybLQwkp4opIEZn1fA.Acce
pt: application/xml,application/xhtml xml,text/html;q=0.9,text/plain;q
=0.8,image/png,*/*;q=0.5。 .Accept-エンコーディング: gzip,deflate,sdch..Accept-L
anguage: zh-CN,zh;q=0.8..Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3 ..クック
すなわち: 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- -..
##
応答出力を比較すると、$_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 の後にデータの区切り文字を定義する境界があり、境界がランダムに生成されることです。もう 1 つの大きな違いは、http エンティティ本体のデータ構成構造が異なることです。

前のセクションでは、Content-Type が application/x-www-form-urlencoded の場合、php://input と $_POST データは「一貫性」があり、他の Content-Type の場合は、 php: //input と $_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 要求データ パケットが含まれます。グローバル変数 $_POST
2. PHP が Content-Type タイプを認識できない場合、http リクエスト パッケージ内の対応するデータは変数 $HTTP_RAW_POST_DATA
3 を使用する場合には代入されません。 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 フィールド query_path 部分に、グローバル変数 $_GET を入力します。通常、GET メソッドによって送信される http リクエストの本文は空です。
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のおすすめ
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート