読者です 読者をやめる 読者になる 読者になる

中年engineerの独り言 - crumbjp

LinuxとApacheの憂鬱

PHPで自由フォーマットのPOST

PHPでPOST

普通は$_POSTを使う。
これは

key1=value1&key2=value2&....

こんな形式のPOSTデータを

array( 'key1' => 'value1' , 'key2' => 'value2' ...);

の様にパースして渡してくれるが
逆に、この形式になっていないと

array();

が返って来る

しかしajaxjsonをやり取りする場合など、生のPOSTデータが欲しい場合があり
その場合はこの様に取る

 $STR = file_get_contentsf('php://input');

ただしこの場合$_POSTも作成(しようと)しておりこれはCPU性能的に無駄!!

しかも$_POSTまで作成出来てしまった時はモリー的にも無駄無駄無駄!!

ApachePHPではモリーとの戦いになる事が多いので後者は勘弁して貰いたい訳です。

スマートに解決

そんな訳で綺麗にしてみた。

まずは$_POSTを節約

php.ini の設定は通常こんな感じだと思いますが・・・

variables_order="GPCS"

Pを消します

variables_order="GCS"
PHPコードでうねうね

あとはPOSTデータがパース可能なら$_POSTを作り
そうでなければ生データのまま扱うコードを書くだけですが
パーサを自前で作るのは頭が悪すぎます。
PHPが$_POSTを作ってるんだがら何か関数があんだろ?

と軽く思ってたら中々見つからない・・・

でもやっとこさ見付けた。
http://php.net/manual/ja/function.parse-str.php

センス悪っ!!名前ダメ過ぎだろ!!検索し難い訳だ

そんな訳で最終的なコード

  if ( $_SERVER[REQUEST_METHOD] === 'POST' ) {
    $STR = file_get_contents('php://input');
    if ( preg_match('@^(?:[^=&]*=[^=&]*(?:&[^=&]*=[^=&]*)*)?$@',$STR,$matches) !== 0 ) {
      Log::trace($NAME,'Query format');
      parse_str($STR,$POST);
    }else{
      Log::trace($NAME,'Not Query format');
      $POST=$STR;
    }
  }

一応マジメにパース可能か否かのチェックを掛けているがCPU的にはパースと同じ位の負荷が掛かってしまっている。
もっと大雑把でも良いと思う。

最初は行き成りparse_str()に渡して空だったら・・・みたいな判定をしていたのだが

中途半端にパースして妙なarray()を生成してくた
のでこうなった。

効果計測

試しに1MB程度のデータを扱って見た所、こんな感じでちゃんと効果が現れてる模様。。
よかったよかった

  • variables_order="GPCS"
$ ps aux | grep httpd
500      25775  6.7  1.1 230572 36732 ?        S    17:07   0:00 /usr/local/apache-2.2.21/bin/httpd -k start
                                  ↑ココが使用メモリ
  • variables_order="GCS"
$ ps aux | grep httpd
500      25895  2.0  0.7 216612 22828 ?        S    17:23   0:00 /usr/local/apache-2.2.21/bin/httpd -k start
                                  ↑ちゃんと減ってる!