HTTPって大変だね
Posted: Updated:
HTTPリクエスト
class TinyHttp
{
public $header;
public $body;
public $error;
public function __construct($url, $context = null)
{
if ( !empty($context) ) {
$this->body = @file_get_contents($url, false, $context);
} else {
$this->body = @file_get_contents($url);
}
$this->header = $http_response_header;
$this->error = !((bool) $this->body);
}
public function getStatusCode()
{
if ( preg_match('@^\s?HTTP\/([0-9].[0-9x])\s+([0-9]{3})\s+([0-9a-zA-z\s]*)$@', $this->header[0], $match) )
{
$status = array(
'version' => $match[1],
'code' => $match[2],
'status' => $match[3],
);
}
return !empty($status) ? $status : false;
}
}
//contextはなくてもいい。
$http = new TinyHttp($request, stream_context_create($context));
//ヘッダー
print_r $http->header;
if ( $http->error ) {
//しっぱい
} else {
//どれどれボディを見せてもらおうか
print_r $http->body;
}
こんなん書いてみたわけさ。API宛てに手軽にリクエスト撃ちたかったので。
したら、不都合ありありで苦戦した次第。
PHPの組み込み関数は200 OK以外のレスポンスボディを取ってこない
※レスポンスボディは、HTTPでどっかのサーバーをぺちっと叩いて、返ってきたモノのメイン部分。前半分のサーバー同士のやり取りに使われる取り決められた情報は、レスポンスヘッダーらしい。
file_get_contentsとかstream_get_contentsのファイルやらストリームの関数は、正常にリクエストできないとWarnning噴くわボディは取ってこないわ潔すぎる感じ。
Twitter APIの場合、401 Not Authorizedとか、400 Bad Requestが返ってきたときにボディまで読まないと真の理由が分からなかったりする。(ボディ読んでも適当なことのほうが多いけど)
下記の情報によると、PHP5.3からはコンテキストにignore_errorsを混ぜるといいらしい。でも5.3って、仕事では、いまだにお目に掛かったことない罠。あと、既存の関数共も、正確には2xxなときに取ってくるみたい。200限定ではないらしい。
参考:HTTP ストリーム ignore_errors オプション in PHP 5.3 - 親方、空から覚え書きが!
$http_response_headerはよい子
何らかのHTTP的な動作の直後に、このhttp_response_headerという変数にレスポンスヘッダーが格納されるみたい。配列型で。$はついてるけど、定数的な動作?
上のコードでも、コレのおかげでレスポンスヘッダーだけは何となく取得できるので良い感じ。
file_get_contentsでもPOSTできる
やれば出来る子ですねー。上のコードも、file_get_contentsに適当に依存してるので、context混ぜればPOSTします。
参考:file_get_contentsでPOSTデータ送信 - PHPはやれば出来る子
車輪のナントカ?
というような発見と悩みを抱えながら、ソケット接続からHTTPリクエストして、レスポンスヘッダーもボディもちゃんと取ってくる、API叩く君を書いてました。いまだに、gzipの処理とか、chunkedなデータの扱いとかが納得いかないできばえ。もうちょっと頑張ります。