httpメッセージ、phpの 事情ば分かっとっと?

43
HTTPメッセージ、PHPの 事情ば分かっとっと第102回 PHP勉強会@東京 @sasezaki 『開発者は、ウェブアプリケーションを構築する際に HTTPメッセージとどう対峙していけばいいのだろ う?そのためには、SAPI・ストリーム・出力バッファ リングと向きあなわければいけないのでは?』が今日 のテーマです。 2016.05.25

Upload: sasezaki

Post on 07-Jan-2017

1.185 views

Category:

Internet


1 download

TRANSCRIPT

Page 1: HTTPメッセージ、PHPの 事情ば分かっとっと?

HTTPメッセージ、PHPの

事情ば分かっとっと?

第102回 PHP勉強会@東京@sasezaki

『開発者は、ウェブアプリケーションを構築する際に

HTTPメッセージとどう対峙していけばいいのだろ

う?そのためには、SAPI・ストリーム・出力バッファ

リングと向きあなわければいけないのでは?』が今日

のテーマです。

2016.05.25

Page 2: HTTPメッセージ、PHPの 事情ば分かっとっと?

● 自己紹介ここ数年の記事とか発表– 2015年03月 日記

PHP - 憂鬱な希望としての PSR-7 http://sasezaki.hatenablog.com/entry/2015/03/07/195908

– 2015年06月 Symfony Meetup

Symfony ユーザ向け psr-7 zend-diactoros Middleware 入門http://psr7.net/sasezaki/slide20150620/

– 2015年06月 動作確認

ストリーム 関連のプロジェクトの話https://gistlog.co/sasezaki/fb703148b0542d61f0bb

– 2015年11月 PHP勉強会@相模原

PSR-7 - これは何だhttp://psr7.net/sasezaki/slide20151110/

Page 3: HTTPメッセージ、PHPの 事情ば分かっとっと?

● 自己紹介ここ数年の記事とか発表– 2016年05月 PHPカンファレンス福岡2016

HTTPメッセージ - PHPで扱う場合の再入門http://psr7.net/sasezaki/phpconfuk2016/

NEW

・・・ということで、察しがついたかも知れませんが、今日の話は先日の発表をベースにしてます。

Page 4: HTTPメッセージ、PHPの 事情ば分かっとっと?

https://twitter.com/chobi_e/status/193717178615345153

Page 5: HTTPメッセージ、PHPの 事情ば分かっとっと?

せやな(汗

...........SAPIって何?

Page 6: HTTPメッセージ、PHPの 事情ば分かっとっと?

「PHPの実行環境は、主にWebサーバ(でのモジュール)」「サーバにはapache以外にも色々ある。」「CLIもサーバ」

『第1回 身近なWeb[PDF] – 放送大学』よりhttp://morimoto.code.ouj.ac.jp/resources/2015_web/01.pdf

Page 7: HTTPメッセージ、PHPの 事情ば分かっとっと?

図コピペ元:http://tech.respect-pal.jp/php-helloworld/

Page 8: HTTPメッセージ、PHPの 事情ば分かっとっと?

サーバーリクエスト (Incoming Request )

Webサーバ

HTTPリクエスト

PHPスクリプトコード

・ $_SERVER,$_GET,$_POST,$_COOKIE,$_FILES ・ apache_request_headers() ・ php://input

apache_request_headers()が必要な場面について “In particular, it SHOULD remove any header fields

carrying authentication information, such as 'Authorization'; or that are available to the script in other variables, “ 

(RFC 3875より)

Page 9: HTTPメッセージ、PHPの 事情ば分かっとっと?

最大サイズ・最大長などの制限を設けてる● HashDosで知られるmax_input_varsの導入はPHP 5.3.9 から● もちろん、サーバソフト側でも制限設定項目はあり

● ApacheのLimitRequestBody ディレクティブなど

POSTメソッドでの場合の$_POSTへの変換● sapi_activateでのsapi_read_post_dataのコールにて取得

php-src/main/SAPI.c 参照● php.ini のenable_post_data_reading にて$_POST や $_FILESへの格納を無効化可能 (PHP 5.4より)

サーバーリクエストからのスーパーグローバルへ

Page 10: HTTPメッセージ、PHPの 事情ば分かっとっと?

『今の若い人は CGI なんか知らないと思いますが、そういうのがあって、昔はとてもよく使われてたんですよ。この CGI の仕様を借りて WSGI が Environment の仕様を決め、Rack もそれを継承しています。そのため、CGI を知らない人から見ると奇妙な仕様に見えるでしょう。「なんで User-Agent ヘッダーが HTTP_USER_AGENT に変わってるの?そのまま User-Agent 文字列を使えばいいのに。」のような感想が出てきそうです。』

$_SERVER, CGI, Environment(wsgi, rack)

http://qiita.com/kwatch/items/67657fef43666479bb99

Page 11: HTTPメッセージ、PHPの 事情ば分かっとっと?

※ ちなみに、PHPにおける”リアル”とは

Page 12: HTTPメッセージ、PHPの 事情ば分かっとっと?

PHPのひょうじゅんAPIつらぽよ

Page 13: HTTPメッセージ、PHPの 事情ば分かっとっと?

E_WARNING: Cannot modify header information - headers already sent by (output started at ...

Page 14: HTTPメッセージ、PHPの 事情ば分かっとっと?

スーパーグローバルを直に触るのはつらいheader()を先に呼ばなきゃいけないのがつらいファイル配列操作がつらいリクエストURIの操作がつらい

『PSR-7: HTTP Message Meta Document』から意訳&抜粋

Page 15: HTTPメッセージ、PHPの 事情ば分かっとっと?

アプリケーション実装者が行いたいことは、リクエストを受け取って、レスポンスを生成する

Page 16: HTTPメッセージ、PHPの 事情ば分かっとっと?

function dispatch($request,$response);

Page 17: HTTPメッセージ、PHPの 事情ば分かっとっと?

HTTPリクエスト

ディスパッチャ ( index.php )

ブートストラップ

コントローラ

ルーティング

リクエスト

レスポンス

View / テンプレート

リクエストルーター利用でのプロジェクト構成(例)

Page 18: HTTPメッセージ、PHPの 事情ば分かっとっと?

かくして、PHP開発者はHTTPメッセージと末永く暮らしていきましたとさ。

めでたし。めでた.....

Page 19: HTTPメッセージ、PHPの 事情ば分かっとっと?

Fatal error: Allowed memory size of 6291456 bytes exhausted (tried to allocate 2097153 bytes)

ひー

Page 20: HTTPメッセージ、PHPの 事情ば分かっとっと?

PHP、おまえだったのか。

いつもHTTPメッセージを

運んでくれたのは

Page 21: HTTPメッセージ、PHPの 事情ば分かっとっと?

メッセージボディは、文字列で決定やな。 * * @return string */ public function getContent() {

HTTPメッセージコンポーネント設計者

・・・なんや問題あるんか?

Page 22: HTTPメッセージ、PHPの 事情ば分かっとっと?

何が問題? 

メモリを制限なく消費する可能性→ ヘッダやボディに最大長についてRFC規定あっただろうか? 例えばApacheの場合、LimitRequestBodyにて許可バイト数設定

開発者は諦めてアクションでecho→ getContent()にてコールバックを許容した場合、 戻り値の方が一致しない

Streamリソース利用の発想が抜けている→ HTTPクライアントとして、ストリームは利用しているのに...

Page 23: HTTPメッセージ、PHPの 事情ば分かっとっと?

レスポンスボディの出力・フラッシュ標準の設定では、echoがあれば直ちに送信や文字列すべてを出力はしないパフォーマンスのためにデフォルトのphp.iniではoutput_buffering = 4096 に設定されている。※ CLIは除く

ob_start() コールバック関数ob_start() での引数、またはphp.iniでのoutput_handlerの指定により、出力バッファの内容を操作できる。 ob_gzhandler()関数など

テンプレートエンジン / Viewレンダラーでの応用出力内容を文字列として取得するために、ob_start() ob_get_contents()を行っている。ここでもメモリ使用量増大の可能性

出力出力バッファリング制御制御

Page 24: HTTPメッセージ、PHPの 事情ば分かっとっと?

せや、streamや!

* * @return stream */ public function getContent() {

HTTPメッセージコンポーネント設計者

Page 25: HTTPメッセージ、PHPの 事情ば分かっとっと?

抽象化 I/OPHP 4.3から登場したresourceオブジェクト普段のファイルシステムやhttpなどのスキーマは、デフォルトのラッパーにすぎない

入出力ストリームphp://temp により、メモリならびにテンポラリファイルへの読み書きが行える

ストリームフィルタストリームはカスタムフィルタを作成し、登録できる

PHPPHPにおにおけるStreamStream

Page 26: HTTPメッセージ、PHPの 事情ば分かっとっと?

レスポンス作成時の例外・エラー処理レスポンス作成時の例外・エラー処理 ストリームや出力バッファリング制御 の利用により、メモリ利用量を抑えレスポンス出力時に処理を実行することは可能でしょう。 ただし、レスポンスボディ作成時の例外(DBコネク

ションエラーなど)などを考慮すると一度テンポラリーに書き出しておき、そのストリームリソースを再度渡すなどの対応も考慮すべきでは。

Page 27: HTTPメッセージ、PHPの 事情ば分かっとっと?
Page 28: HTTPメッセージ、PHPの 事情ば分かっとっと?

HTTPメッセージコンポーネントがおおすぎる

Page 29: HTTPメッセージ、PHPの 事情ば分かっとっと?

• Cake\Network\{Request,Response}• CI_Input, CI_Output• Nette\Http\{Request,Response}• PHPixie\HTTP\{Request,Responses}• Symfony\Component\HttpFoundation\{Request,Response}• yii\web\{Request,Response}• Zend\Http\{Request,Response}

Rob Allen 『HTTP, PSR-7 and Middleware』から

Page 30: HTTPメッセージ、PHPの 事情ば分かっとっと?

依存を抑え、リクエスト・レスポンスを扱う処理

を相互運用するには?

Page 31: HTTPメッセージ、PHPの 事情ば分かっとっと?

HTTPレスポンス

ディスパッチャ

ブートストラップ

コントローラ

ルーティング

リクエスト

レスポンス

View / テンプレート

Debugツールバー

Authentication

ミドルウェア・ランナー

MiddlewareMiddleware

Middleware

Middleware

ミドルウェア利用でのプロジェクト構成例

while (! $stream->eof()) { echo $stream->read(8192);}

Page 32: HTTPメッセージ、PHPの 事情ば分かっとっと?

リクエストを受け取って、レスポンスを合成し、次の処理へ渡す

Page 33: HTTPメッセージ、PHPの 事情ば分かっとっと?

function __invoke( ServerRequestInterface $request, ResponseInterface $response, callable $next);

Page 34: HTTPメッセージ、PHPの 事情ば分かっとっと?

psr-7はHTTPメッセージの値についてのinterfaceを定義している従来のレスポンスクラスでは、send()メソッドなんて用意していた

サーバーリクエストには、アプリケーションでの相互運用のために attributesプロパティが用意されているミドルウェアシグネチャでの議論・検討の余地従来のEventManagerを利用したプラグインとの使い分けは?HTTPクライアントでのミドルウェアはどうあるべきか?インターフェイスなどにて別途psrを定義すべきでは?

PSR-7 とミドルウェア

Page 35: HTTPメッセージ、PHPの 事情ば分かっとっと?

PSR-7 PSR-7 に対するご意見に対するご意見

Page 36: HTTPメッセージ、PHPの 事情ば分かっとっと?

● PHPカンファレンス福岡2016で出た質問・余談

–Q「ストリームだと、今までの文字列関数を利用したフィルタリングに比べて大変では?」●私見「レスポンスボディ全体を文字列置換?(困惑)」(“エンコード”の範囲なら、今までのstream filterの想定範囲と同様に効力あるかと)

Page 37: HTTPメッセージ、PHPの 事情ば分かっとっと?

● PHPカンファレンス福岡2016で出た質問・余談

–Q「echo に比べてストリーム大変ですよ。。」

これを

Page 38: HTTPメッセージ、PHPの 事情ば分かっとっと?

● PHPカンファレンス福岡2016で出た質問・余談

–Q「echo に比べてストリーム大変ですよ。。」

こうしたり

Page 39: HTTPメッセージ、PHPの 事情ば分かっとっと?

● PHPカンファレンス福岡2016で出た質問・余談

–Q「echo に比べてストリーム大変ですよ。。」

こうじゃ!

Page 40: HTTPメッセージ、PHPの 事情ば分かっとっと?

● PHPカンファレンス福岡2016で出た質問・余談

–Q「PSR-7だと今のPHP組み込みのセッション機構と整合性がないのでは?」●私見「Cookieを利用したセッションということで?本発表で述べたように、PHPはHTTPメッセージ解釈機能を併せ持ってこそツールとしての価値があるのです。私は、それを崩そうとは思いません。従来の($_SESSIONをラップした)セッションコンポーネント使います。」(本音「そこまで、深く考えてなかったンゴwww」 今までのHTTPメッセージコンポーネントでも同様の問題では。。)※ 「PSR-7 and Session Cookies」http://paul-m-jones.com/archives/6310 という記事にセッションのクッキーヘッダーへのハック周りについて記載があります。

Page 41: HTTPメッセージ、PHPの 事情ば分かっとっと?

おわりです

ご清聴ありがとうございました

Page 42: HTTPメッセージ、PHPの 事情ば分かっとっと?

イラスト素材●http://www.wanpug.com/●http://hiyokoyarou.com/

Page 43: HTTPメッセージ、PHPの 事情ば分かっとっと?

参考文献● php と sapi と zendengine2 と..http://www.slideshare.net/do_aki/php-and-sapi-and-zendengine2-and

● PHP による hello world 入門http://tech.respect-pal.jp/php-helloworld/

● PHP output buffer in deephttp://jpauli.github.io/2014/12/19/php-output-buffer-in-deep.html

● PSR-7: HTTP message interfaceshttp://www.php-fig.org/psr/psr-7/

● PSR-7: HTTP Message Meta Documenthttp://www.php-fig.org/psr/psr-7/meta/

● A Case for Higher Level PHP Streams in PSR-7http://mtdowling.com/blog/2014/07/03/a-case-for-higher-level-php-streams/