RFC: Built-in web server

Twitter / @moriyoshit: いま作っているphpのビルトインwebサーバでsym ...

2011-03-03 に PHP のビルトインサーバーが RFC として提出された。
内容は以下のようなものである。

日本人が英語で書いたものをまた日本語に訳すという楽しい作業。

RFC: Built-in web server

はじめに

多くの開発者は、 PHPApache HTTPD サーバーの組み合わせが開発においては最良であると思っているでしょう。
しかし、Ruby on RailsDjango のようなスクリプト言語のWeb アプリケーションフレームワークの開発経験者からすると、どうせ開発環境でしか使わないのに httpd.conf を設定するのは大げさだと感じるかもしれません。
なぜなら、それらのフレームワークにはたいていコマンドライン一発で起動できるような小規模のウェブサーバーがつきものだからです。

PHP の強力なストリーム API を利用すれば、スタンドアロンなウェブサーバを PHP で書くことは可能です。
しかし、各ウェブアプリケーションフレームワークごとに PHP でウェブサーバを書くことにはあまり意味がありません。
PHP はリクエスト単位でのリソース管理を行うメインイベントループをもつため、Runkit を使わなければ、標準的な環境を十分に再現できません。

それならば、PHPCLI 版が、ウェブサーバとしての機能も果たすというのが自然な帰結でしょう。

提案

CLI 版の PHP に新たなコマンドラインオプション -S を設けます。
このオプションには続けてホストのアドレス(IP またはドメイン)とポート番号をコロン(:)区切りで指定します。
PHP は、指定されたアドレスとポートで待ち受けるビルトインウェブサーバを起動します。

php -S localhost:8000

以下が出力されます。

Server is listening on localhost:8000... Press CTRL-C to quit.

各リクエストも同様にコンソールに出力されます。

ドキュメントルートの指定

ハイフン(-)で始まるいかなるオプションにも属さない単独の引数を与えると、ドキュメントルートを指定することが出来ます。
省略した場合はカレントディレクトリが使われます。

php -S localhost:8000 docroot
ルータースクリプト

多くのウェブアプリケーションは、ウェブサーバーの URL リライト機能を使って、見栄えのいいパスを使ったルーティングを実現しています。
ルータースクリプトを使うことによってこのような機能をエミュレート出来ます。
ルータースクリプトとは、ウェブサーバーへの各リクエストに適用され、リクエストをどのように扱うかを判断するものです。
リクエストに対してスクリプトが false を返すと、そのリクエストはデフォルトの動作をします。
それ以外の場合、クライアントへ適切なレスポンスを返すように振る舞います。

php -S localhost:8000 routing.php

ドキュメントルートを指定する箇所にファイルへのパスが与えられた場合、ルータースクリプトとして扱われます。
その場合、ドキュメントルートはルータースクリプトのあるディレクトリとなります。

<?php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"]))
    return false; // serve the requested resource as-is.
else
    ...
?>
サポートするプラットフォーム

現時点では POSIX に準拠した OS と Windows をサポートしています。

Hacker News での反応

Twitter / @moriyoshit: Hacker news 見たら、的外れな否定的意見が ...

さて、この RFC についてHacker News
多くのコメントが寄せられている。

以下適当に翻訳して抜粋する。

うわやだなコレ。
サーバーと言語をセットにするって、
DjangoRails 共通の弱点だと俺は思うんだよな。
dev 環境と本番環境の違いのせいで、デプロイのハードルが高くなるから。

PHP の強みは、本番と開発環境とでほぼ同じ環境を使えることじゃないかな。
デプロイはただファイルをコピーするだけだし(この辺は好きなように最適化出来る)。

初心者に教えるなら、デフォルトの Apache のインストールの仕方を教えるのもPHP のサーバーの立ち上げ方を教えるのも大して変わらないし(特に最近は LAMP や WAMP のインストーラーが全部やってくれるし)、どうせ本番にデプロイする段になったら Apache のこと教える必要があるんだし。

(上のコメントに大して)その考え方はちょっとベストプラクティスとは言いがたいと思うなあ。

まず第一に dev 環境は本番環境と同様に動くとは限らない。
だからステージングサーバーが必要になる。
自分の dev 環境にはいろんなツールやらデバッグツールがごちゃごちゃ入ってる。
さらに dev ではひとつのマシンですべてを動かすけれど、実際は分散して動いている。
dev と本番が同じように動くことを仮定するのはまずいと思うよ。

第二に、一般的な、HTTP をしゃべって、標準的なインタフェースを持っていて、ロードバランサ(nginx とか)と HTTP でしゃべるようなアプリケーションサーバー(ruby だと Rack、 python だと WSGI)はすごく簡単に動かせる。
Apache を設定するよりかは楽。
`cd myproject && rails server` で一発。

第三に、君は本番サーバに大して数えきれないほどの勘違いをしている。
リクエストをアプリケーションサーバーにどうやってプロクシしているか分からないようじゃ、そもそもサーバーを設定してる場合じゃないよ。
はなからおかしい話なんだよ。

こんなことやってないでクソみたいな名前空間をなんとかしろよ…。

'apt-get install apache2 php5 && a2enmod php'でほぼ解決してるような問題よりももっと他に解決すべき問題があるだろ。
言語の基本的な部分の改善とか、SPLをつくるとか、他のライブラリ作るとか。

それに(俺含めて)ほとんどのやつは PHP のシステムは肥大化しすぎだと思ってるんだよ。
ウェブサーバの機能をまるごと入れるなんて普通のスクリプト言語はやらねーぞ?
だって肥大化しすぎるもん。

追記
マイナス票を投じる前にさ、これがすでに明らかに解決済みの問題じゃないって言うんなら説明してくれよ。
ス ク リ プ ト 言 語 が独自のウェブサーバーを丸ごと含んでいるなんて肥大化以外のなんだって言うんだ?
開発機に限って言えば Apache をインストールするのなんてWindows だって簡単に出来るじゃん。

(上のコメントに対して)開発者は LAMP 環境をまるまる設定してる時間が惜しいんだよ。
だから DjangoRails も独自にウェブサーバを持ってるんだし、それ使えば開発とかテストを本当にすぐに始められるでしょ。
SQLite 使えば DB を用意する必要もないし。

テスト用に素早くサーバーを起動できる、いいことじゃん?
俺は自分のサイトで(静的なポートフォリオウェブサイトを作るために)poole.py を使ってるけど、コミット前とか実際動かす前に変更を確認するときはビルトインサーバー使ってる。

Python とか Ruby みたいにPHP も簡単にウェブサーバーを立ち上げられるようになるんなら面白いだろうね。
ローカルマシンに mod_php いれて Apache 動かしてーとかリモートに立てて、デプロイとテスト繰り返したり、遅い SSH ごしにファイル編集したり FTP で送ったりするのはなあ。

そうじゃなくて、もう PHP にビルトインウェブサーバーが入ってしまって、リクエストを扱えるっていうんだから素晴らしいね。
単純なウェブサーバ一個もつぐらい肥大化とは言わないんじゃない?
Python とか Ruby だってそうでしょ。

(さらに反論して)でも PHP を動かすための最低限の Apache の設定なんて難しくないっしょ?
Linux だったらさっきのたった二つのコマンド叩くだけだしWindows だったらインストーラー落として一発よ?
確か Windows でもインストールが終わったらすぐに http://localhostPHP 動くぜ??

PHP がなんでこんなにまで人気が出たかっていうと、
1) タダ
2) 基本的な HTML の操作が簡単
3) セットアップしてとりあえず起動するまでが簡単
っていうことがあったから。

一個だけ行くサイトが増えて一個だけインストーラが増えるってだけなのにわざわざスクリプト言語にカスタムウェブサーバーをバンドルする意味が分からない。
ずっとマイナス票ばっかりだから、何かでかい見落としでもあるのかなーって心配になるんだが…。
今度は 'sudo apt-get install mysql' の手間を惜しんで MySQL エンジンを組み込むのか?
インストーラ実行してる間の時間ももったいないから Tux Racer で遊べるようにそれも同梱するのか???

追記
マイナス票覚悟で言うけど、基本的な Apache/mod_php のインストールすら難しいっていうんなら、そいつらは PHP 始める前にもっとやることがあるんじゃねえの…。
新しく組み込まれる PHP のサーバーを起動するのも Apache の開発用インスタンスをインストール出来るようにするのも難易度は変わらないだろ?

(上のコメントに対して)おちけつ。
言いたいことは分かるよ。

多分君は PHP を自分の環境だけで動かすことを想定してるんじゃないかな?
複数の環境を考えてみよう。
それか同じコードベースからチェックアウトされたいくつかのブランチを
それぞれ実行したい、という場合は?
VirtualHost と取っ組み合って、ServerAlias にワイルドカードとか設定すればまあできるけど、それはもう'apt-get apache'で終わるような単純な話じゃないよね。

どんなプロジェクトを扱っていても「'php -S' を実行して」って伝えられるなら、そのほうがシンプルだと思わない?

(二つ前のコメントに対して)そこまで簡単って言えるか?
インストールが終わったら今度はドキュメントルートの設定だのmod_php を使えるようにするだの、virtual host の設定だの色々設定しなきゃならないことは残ってる。バーチャルホスト切ったらどのドキュメントがどのポートにマッピングされてるのかとかメンテしなきゃならないし…

否定的な意見の多くは「そんなことよりやることがあるだろう」的なスタンスで書かれていることが多いように感じた。

dev 環境と本番環境をなるべく同じようにするっていうアプローチは自分もしているし、正直ウェブサーバーが組み込まれることに対して利点を見いだせない…。
経験が少ないのと、コメントで挙げられてるような Rails とか Django みたいなフレームワークを使ったことがないのが原因なんですが。

でも別にこの機能がついたから困るわけじゃないし、否定してる人たちの気持ちはよく分からないなあ。