1
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHPで生のリクエストボディーを読む

Last updated at Posted at 2019-07-30

PHPではリクエストからパラメータを取得する場合$_GET$_POSTが用意されていますが、これはContent-Typeapplication/x-www-form-urlencodedの場合の話です。

JSON-RPCのようにContent-Typeapplication/jsonの場合にパラメーターを取得するにはPHPに頼らずリクエストボディーのJSONを自力でパースする必要があります。

stream を使う

リクエストボディーを取得するにはWEBサーバとして動かす場合は php://input を使います。

var_dump(file_get_contents('php://input'));

下記を短く書いています。

$stream = fopen('php://input');
$data = stream_get_contents($stream);
fclose($stream);
var_dump($data);

コード

リクエストボディーのJSONをパースしてダンプするスクリプトを test.php としてファイルにします。

test.php
<?php

var_dump(json_decode(file_get_contents('php://input'), true));

動作確認

PHPのビルトインサーバでホストし、curlでtest.phpを呼び出します。

$ php -S localhost:8080 # test.php の存在するディレクトリで実行する
$ curl -X POST \
    -d '{"hello":"world", "こんにちは":"世界"}' \
    -H "Content-Type: application/json" \
    http://localhost:8080/test.php

array(2) {
  ["hello"]=>
  string(5) "world"
  ["こんにちは"]=>
  string(6) "世界"
}

例ではapplication/jsonが送られてくる場合を仮定しましたが、application/x-www-form-urlencodedでも、パースされていない生データを取得することができます。 (もちろんjson_decodeしてはいけません)

ヒント

php://inputphp://stdin の違いがよくわかっていなくて、 php://stdin を使用すると、ブロッキングしてしまってWEBサーバがレスポンスを返さなくなります。CLIだとエンターを押すまでブロッキングするからでしょうかね。

アプリケーションサーバとして使う場合はphp://inputを使いましょう。そしてブロッキングしてるWEBサーバは再起動しましょう。

CLIの場合はSTDIN定数やphp://stdin を使うのだと思います。

STDINfopen('php://stdin')と等価です

$HTTP_RAW_POST_DATA 変数を使う

PHP7 より前は $HTTP_RAW_POST_DATA に生のPOSTデータがセットされていましたが、PHP7以降では使えません。

1
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?