ホリデープログラミング入門

ホリデーにプログラミングを楽しむための入門 by 船木信宏

全体表示

[ リスト ]

HTTPの生通信に慣れる

HTTPの生通信



ウェブの世界は基本的にHTTPの通信で成り立っています。ブラウザでサイトを見ているときは気になりませんが、AjaxやらAPIを使ったりしていると通信の中身を気にする場面が出てきます。

通信の中身を見る


クライアント側で見る


HTTPの仕様は各所で紹介されています。それなりにややこしいのでまずは通信の内容を見てみます。

IEを使っているならHttpSpyが便利です。
HttpSpy download and review - capture and display HTTP traffic from SnapFiles

FirefoxならlivehttpheadersかFirebug。Firebugの方は多機能なので、HTTPの通信を見るだけならlivehttpheadersの方がシンプルです。


これらはブラウザでアクセスした際に発生したHTTP通信の中身を表示してくれます。

サーバ側で見る


サーバ側で通信の中身を知るには、ウェブサーバのログを見る必要があります。

ロリポップで見るにはちょっと面倒で、WEBツールのアクセスログのページに飛んだ後、生ログファイル ダウンロード、で1日分ずつ見れます。

ウェブサーバはLinux上でapacheを使っている場合が多いと思います。RedHat系だと/var/log/httpd/access_logがログファイル。root権限がないと見れないかもしれません。

デバッグ中には
$ tail -f /var/log/httpd/access_log
などとして眺めることが多いです。

PHPでHTTP通信を手動で行う


file_get_contentsを使うと1行ですんでしまうのですが、あえて何種類かの方法でHTTPの通信を書いてみることにします。

echo file_get_contents('http://yahoo.co.jp/');

fsockopenを使う


PHP: fsockopen - Manual
マニュアルにちょうど載っています。

$purl = parse_url('http://example.org/');
$fp = fsockopen($purl['host'], (isset($purl['port']) ? $purl['port'] : 80), $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)\n";
} else {
$out = "GET " . $purl['path'] . " HTTP/1.1\r\n";
$out .= "Host: " . $purl['host'] . "\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp);
}
fclose($fp);
}

マニュアルとはちょっと変えて、parse_urlを使ってみました。fsockopenの2番目の引数にしているのが「ポート」。

ちなみにURLは
http://localhost:8080/
といった風にホスト名(fsockopenの1番目の引数に入れる値)のあとにコロン(Y!ブログの制約で上記は全角で書いています)、続けてポート番号を指定できます。ウェブサーバは普通80番です。

上記のコードを実行すると
HTTP/1.1 200 OK
Date: Sat, 14 Jul 2007 13:30:17 GMT
Server: Apache/2.2.3 (CentOS)
Last-Modified: Tue, 15 Nov 2005 13:24:10 GMT
ETag: "280100-1b6-80bfd280"
Accept-Ranges: bytes
Content-Length: 438
Connection: close
Content-Type: text/html; charset=UTF-8

こんな感じに結果が出力されるでしょうか。
これがHTTPのヘッダー。ブラウザで表示されるのはこの下に改行を1つ入れて続くHTMLの部分だけなので普段お目にかかることはありません。

fsockopenはfopenと同じような関数。そして通信はこちらから送るときはfwrite、受信するときはfgetsを使って行います。

$outに含まれる内容がHTTPの生な通信内容。


get_headers()


print_r(get_headers('http://yahoo.co.jp/'));
ヘッダーを受信するだけなら便利な関数があります。

file_get_contentsを実行したときも、
file_get_contents('http://yahoo.co.jp/');
print_r($http_response_header);

$http_response_headerという変数が予約されていて、ヘッダー情報が配列で自動的に入ります。

stream_context_create()


$opts = array(
'http'=>array(
'method'=>"GET",
'header'=>"If-Modified-Since: Sat, 14 Jul 2007 02:24:43 GMT\r\n"
)
);
$context = stream_context_create($opts);
echo file_get_contents('http://example.org/', false, $context);

file_get_contentsは案外拡張性があって便利なのですが、こうやってHTTPヘッダをカスタマイズすることもできます。

HTTP/1.1 200 OKではなく、以下のような結果になるかと思います。
Warning: file_get_contents(http://example.org/): failed to open stream: HTTP request failed! HTTP/1.1 304 Not Modified


PHPのライブラリでHTTP通信を行う


PEARのHTTP_Clientというライブラリを使うのも便利です。生のHTTP通信を記述するよりも簡単でしょう。
PEAR :: Package :: HTTP_Client

require_once 'HTTP/Client.php';

$params = array(
'user' => 'funaki',
'pass' => '***',
);

$client = new HTTP_Client($params);
$client->get('/');

$response = $client->currentResponse();
print_r($response);

Basic認証のかかっているページにアクセスしてみたり。
PEARのソース(HTTP/Request.php)を見るとaddHeaderでヘッダを追加している様がわかります。

手動でHTTPの通信を行いたいときの1つに、POSTを使うときがあります。HTMLのformに
<form action="" method="POST">と指定したときの通信です。

これはfsockopenでやっていると大変ですし、file_get_contentsはPOSTまではカバーしていません。HTTP_Clientを使えば簡単にできます。

require_once 'HTTP/Client.php';

$client = new HTTP_Client;
$params = array('next_url' => '/home.pl', 'email' => '***', 'password' => '***');
$client->post('http://mixi.jp/login.pl', $params);
ここのを参考にしました。
【PHP TIPS】 35. PEAR::HTTP_Clientでサイトの内容取得:ITpro

先のHttpSpyなどで、ブラウザを使って普通にmixiにログインすると、
POST /login.pl HTTP/1.1
と通信している箇所があるはずで、そこを真似するとプログラムからでもmixiにログインできるようになります。

おまけ php://input


POSTの内容を受信するときは普通、$_POSTを使いますが生のデータにアクセスするにはphp://inputを使います。
file_get_contents('php://input');
Ajaxや何やでXML通信をするときなどに使うかと思います。


まとめ


ずらずら並べるだけにしてしまいましたが、参考になる箇所はあったでしょうか。ウェブ系をやっている以上、HTTPはつきもの。CPUやメモリーの仕組みと同じように、HTTPの仕様もざっくりつかんでおきたいところです。

この記事に

閉じる コメント(1)

顔アイコン

はじめまして!
phpでpost受信どーするのか分からなかったんですが、
file_get_contents('php://input');
大変参考になりました!!
バッチリ受信できました!
ありがとうございますm(__)m 削除

2009/4/28(火) 午後 10:31 [ mitch ] 返信する

コメント投稿

顔アイコン

顔アイコン・表示画像の選択

名前パスワードブログ
絵文字
×
  • オリジナル
  • SoftBank1
  • SoftBank2
  • SoftBank3
  • SoftBank4
  • docomo1
  • docomo2
  • au1
  • au2
  • au3
  • au4
投稿

開く トラックバック(1)


.


みんなの更新記事