HTTPリクエストするためのクラス書いてみた

Category : PHP < ウェブ開発

Tags : HTTP php

HTTPリクエスト再び

Twitter API用のライブラリがどうとか言いながら、全然公開してませんな。

スピンアウト品による、HTTPリクエストについてメモしとくです。この後にOAuthかな。そしてTwitter, Flickr, Google, YahooあたりのAPIと遊ぶ方法とか。一通り試した後なので、暇を見つけながら、内容をまとめて自分メモ的にブログ書くつもり。a-blog cmsと連携したTwitter BOTぐらいはちゃんと作って公開すっか。

APIを叩く用に

<?php
$http = new SimpleHttp();

$http->get('http://havelog.ayumusato.com');

$res = $http->header;
$body = $http->body;

if ( !($http->error) ) {
     return true;
} else {
     return false;
}
?>

GET!POST!で適当にリクエスト投げれて、レスポンスヘッダーもレスポンスボディも、一通り取ってこれるようにしたかったのです。API相手しか考えてないので、POSTメソッドもクエリーのやり取りしか考えられてません。

file_get_contentsとかだとレスポンスコード200以外のときのレスポンスボディを端折りやがるので、ソケット接続から始めてリクエストを書き込んで受け取って、と地味な作業を繰り返してます。地味ですけど、HTTPの仕様の勉強になります。裏でこういうやり取りされてたんですね。

ハードウェアやソフトウェアの深淵を見るには、文系の自分には叶いません。でも、たまーに少し深いところを垣間見ると、なんとなく、してやったりという気分になれます。ああ現金。

覚え書きリスト

  • リクエスト時の改行コードはCR+LFで鉄板くさい
  • 末尾の改行コードが足りないとシカトされることすらある
  • ステータスコード204と304はレスポンスボディがない(仕様的に)
  • HTTP1.1のchunkedデータは、送ってきたり送ってこなかったりする
  • chunked受け取りたくなかったら1.0としてリクエスト
  • phpのparse_url関数はステキ(regex書き終わった頃に教えてもらった)
  • httpsはssl://に変換して、portも合わせて変える


HTTPって大変だね

Category : PHP < ウェブ開発

Tags : HTTP php

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なデータの扱いとかが納得いかないできばえ。もうちょっと頑張ります。