widgetown 開発チームブログ(仮)

4月 1st, 2008

PHPで作る簡易Httpプロキシ

Posted by kokuno in 未分類

こんにちは、サーバー担当 kokunoです

ウィジェットの開発でそれなりに面倒なのが、通信のテストです。

問題が起こった場合に、ウィジェット側なのかサーバー側なのかの
切り分けを行うのは、以外に面倒。

Webアプリであれば、ブラウザのデバッグツールが使えたり
(FirefoxのLiveHTTPHeadersとか便利ですねー)するのですが、
ウィジェットの場合そういったツールは使えません。

コマンドラインツールのngrep(windows版tcpdump)で十分な場合も
あるのですが、ちょっと凝ったものなら、プロキシを立ててキャプチャしたいところです。

下記は、以前にちょっと試したプロキシのサンプルです。
実用にはなりませんが、リクエストヘッダーがキャプチャして、
自動化テストに利用しようかなと思ったりしました。

ウィジェットの場合は、IEコンポーネントを使う場合が多いので、
IEのプロキシ設定を行っておけば、通信状況を確認できるのは便利ですね。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
< ?php 
 
define('_BUF_SIZE',1024);  //サービスポートのリスニング
$port = 8080;
 
$proxylistner = socket_create_listen($port,0) 
  or die("socket_create_listen({$port}) failed.\n");
 
do {
    //ブラウザからの要求の受付
    $clientreq = socket_accept($proxylistner);
    $resbuf="";
    //レスポンスの取得
    $reqin = socket_read($clientreq, _BUF_SIZE,PHP_BINARY_READ);
    $headers = explode("\r\n",$reqin);
    //URLから接続先をチェック
    for($i=0;$i<count($headers);$i++){
      if(preg_match('#^(GET|POST) (http|https)://([^/]*)([^\s]*) HTTP/(.*$)$#i',$headers[$i],$match)){
        $schem=$match[2];
        $host=$match[3];
        $path=$match[4];
        $rep = preg_replace("#^([^\s]*) ({$schem}://{$host}{$path}) (.*)$#i","$1 $path $3",$headers[$i]);
        $headers[$i]=$rep;
      }
    }
 
    $service_port = getservbyname($schem, 'tcp');
    $address = gethostbyname($host);
    $senddata=implode("\r\n",$headers)."\r\n";
 
 
    $clientsocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) 
      or die("socket_create() failed.\n");
 
    //クライアント接続の開始
    $resbuf="";   
    $reqresult = socket_connect($clientsocket, $address, $service_port);
    if ($reqresult) {
        //リクエスト要求
      socket_write($clientsocket, $senddata, strlen($senddata));
      //レスポンスの返却
      while ($resin = socket_read($clientsocket, _BUF_SIZE,PHP_BINARY_READ)) {
        $ret = socket_write($clientreq, $resin, strlen($resin));
      }
    }
  socket_close($clientreq);
  socket_close($clientsocket);
 
}while (true);
socket_close($proxylistner);

参考URL:

ソケット関数
http://www.php.net/manual/ja/ref.sockets.php

PHP でサーバソケットプログラミング (1):Rainy Day Codings:So-net blog:
http://rainyday.blog.so-net.ne.jp/2007-02-17