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

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

  • 2007-07-21 (土) 13:19
  • PHP
この記事の所要時間: 124

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

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

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

# ; を外す
extension=php_sockets.dll

サーバを起動する

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

<?php
class HttpServer {
  private $socket = null;

  private $method = null;
  private $uri = null;
  private $headers = null;
  private $body = null;

  public function __construct($port = 9000) {
    $this->socket = socket_create_listen($port);
    if ($this->socket === false) {
      $this->error(); 
    }
  }

  public function execute() {
    while (true) {
      $client = socket_accept($this->socket);
      if ($client === false) {
        $this->error();
      }

      $request = $this->read($client);

      $header = "HTTP/1.x 200 OK\r\n";
      $header .= "Content-Type: text/html\r\n";
      $header .= "\r\n\r\n";
      socket_write($client, $header, strlen($header));

      $request = nl2br($request);
      socket_write($client, $request, strlen($request));
      socket_close($client);
    }
  }

  private function read($client) {
    $this->body = "";
    $req = "";
    while (true) {
      $buff = socket_read($client, 2048, PHP_BINARY_READ);
      $req .= $buff;

      if ($buff === false) {
        $this->error();
      } else if ($buff === "" || strlen($buff) < 2048) {
        if (preg_match("/\r\n\r\n$/", $req)) {
          $this->parseHeader($req);
        } else {
          $this->body .= $buff;
        }

        if ($this->isComplete()) {
          return $req;
        }
      }
    }
  }

  protected function parseHeader($req) {
		$lines = explode("\r\n", $req);
    $this->setRequestLine(array_shift($lines));

    foreach ($lines as $line) {
      $line = trim($line);
      if (empty($line)) {
        continue;
      }
      $this->setHeader($line);
    }
  }

	protected function setRequestLine($line) {
		list($this->method, $this->uri) = explode(" ", $line);
	}

	protected function setHeader($line) {
		$header = explode(":", $line);
		$this->headers[trim(array_shift($header))] = trim(join( ":", $header ));
	}

  protected function isComplete() {
    if ($this->method == "POST" && !empty($this->headers['Content-Length'])) {
      return strlen($this->body) == $this->headers['Content-Length'];
    }

    return true;
  }

  private function error() {
    $message = sprintf("error:%d %s", socket_last_error()
                                    , socket_strerror(socket_last_error()));
    die($message);
  }

  public function __destruct() {
    if (is_resource($this->socket)) {
      socket_close($this->socket);
    }
  }
}

$server = new HttpServer();
$server->execute();
?>

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

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

次はHTTPサーバ?

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

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

Pocket

follow us in feedly

トラックバック:1

このエントリーのトラックバックURL
/blog/2007/07/php_http_echo_server.html/trackback
Listed below are links to weblogs that reference
HTTPリスエストをそのまま返すPHPサーバ from Shin x blog
pingback from ぱんぴーまっしぐら » 今日のチェキ 2007-07-24 10-07-04 (日) 8:38

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

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

検索
フィード
メタ情報

Return to page top