iPhone/iPadのホーム画面コンテスト開催中!賞品は iTunes カード!

PHP 2007/07/21 13:19

HTTPリスエストをそのまま返すPHPサーバ

PHPで簡易サーバを書いてみました。ブラウザから来たHTTPリクエストをそのまま返すだけのものです。実用性はあまり無いですが、ブラウザがどんなリクエストを出しているか確認するにはちょっとだけ便利かもしれません。;-)

socketsライブラリを有効にする

PHPでsocketsライブラリが有効になっている必要があります。Win環境ならPHPパッケージにDLLが用意されているので、php.ini等で下のように有効にすればokです。

CODE:
  1. # ; を外す
  2. extension=php_sockets.dll

サーバを起動する

下のソースをローカルに保存して、phpコマンドで実行するとサーバが起動します。デフォルトではlocalhostの9000ポートでlistenします。

PHP:
  1. <?php
  2. class HttpServer {
  3.   private $socket = null;
  4.  
  5.   private $method = null;
  6.   private $uri = null;
  7.   private $headers = null;
  8.   private $body = null;
  9.  
  10.   public function __construct($port = 9000) {
  11.     $this->socket = socket_create_listen($port);
  12.     if ($this->socket === false) {
  13.       $this->error();
  14.     }
  15.   }
  16.  
  17.   public function execute() {
  18.     while (true) {
  19.       $client = socket_accept($this->socket);
  20.       if ($client === false) {
  21.         $this->error();
  22.       }
  23.  
  24.       $request = $this->read($client);
  25.  
  26.       $header = "HTTP/1.x 200 OK\r\n";
  27.       $header .= "Content-Type: text/html\r\n";
  28.       $header .= "\r\n\r\n";
  29.       socket_write($client, $header, strlen($header));
  30.  
  31.       $request = nl2br($request);
  32.       socket_write($client, $request, strlen($request));
  33.       socket_close($client);
  34.     }
  35.   }
  36.  
  37.   private function read($client) {
  38.     $this->body = "";
  39.     $req = "";
  40.     while (true) {
  41.       $buff = socket_read($client, 2048, PHP_BINARY_READ);
  42.       $req .= $buff;
  43.  
  44.       if ($buff === false) {
  45.         $this->error();
  46.       } else if ($buff === "" || strlen($buff) <2048) {
  47.         if (preg_match("/\r\n\r\n$/", $req)) {
  48.           $this->parseHeader($req);
  49.         } else {
  50.           $this->body .= $buff;
  51.         }
  52.  
  53.         if ($this->isComplete()) {
  54.           return $req;
  55.         }
  56.       }
  57.     }
  58.   }
  59.  
  60.   protected function parseHeader($req) {
  61.         $lines = explode("\r\n", $req);
  62.     $this->setRequestLine(array_shift($lines));
  63.  
  64.     foreach ($lines as $line) {
  65.       $line = trim($line);
  66.       if (empty($line)) {
  67.         continue;
  68.       }
  69.       $this->setHeader($line);
  70.     }
  71.   }
  72.  
  73.     protected function setRequestLine($line) {
  74.         list($this->method, $this->uri) = explode(" ", $line);
  75.     }
  76.  
  77.     protected function setHeader($line) {
  78.         $header = explode(":", $line);
  79.         $this->headers[trim(array_shift($header))] = trim(join( ":", $header ));
  80.     }
  81.  
  82.   protected function isComplete() {
  83.     if ($this->method == "POST" && !empty($this->headers['Content-Length'])) {
  84.       return strlen($this->body) == $this->headers['Content-Length'];
  85.     }
  86.  
  87.     return true;
  88.   }
  89.  
  90.   private function error() {
  91.     $message = sprintf("error:%d %s", socket_last_error()
  92.                                     , socket_strerror(socket_last_error()));
  93.     die($message);
  94.   }
  95.  
  96.   public function __destruct() {
  97.     if (is_resource($this->socket)) {
  98.       socket_close($this->socket);
  99.     }
  100.   }
  101. }
  102.  
  103. $server = new HttpServer();
  104. $server->execute();
  105. ?>

ブラウザでサーバへアクセスする

あとはブラウザで[http://localhost:9000/]にアクセスすればリクエストの内容がそのまま表示されます。適当なフォームをHTMLで作ってPOSTするとその内容もそのまま表示されます。

次はHTTPサーバ?

新大阪<->品川の新幹線で時間があったのでちゃちゃっと書いてみました。本当はもうちょっとちゃんとしたHTTPサーバもどきにしようと考えていたのですが、これはこれで面白かったのでアップしときます。。。

あとコードを書く際はZendFramework付属のhttp_serverを参考にしました。ZFはコードが読みやすいので結構好印象です。PHP5フレームワーク・ライブラリとして今後が楽しみですね。



■Related Posts

One Response to “HTTPリスエストをそのまま返すPHPサーバ”

  1. on 04 7月 2010 at 08:38 1.ぱんぴーまっしぐら » 今日のチェキ 2007-07-24 said …

    [...] ■HTTPリスエストをそのまま返すPHPサーバ [...]

Trackback This Post | Subscribe to the comments through RSS Feed

Leave a Reply