Zend_Http_Client - 接続アダプタ 概要 Zend_Http_Client は、接続アダプタとして設計されています。 接続アダプタは実際にサーバへの接続を行うオブジェクトで、 リクエストの書き込みやレスポンスの読み込みも行います。 この接続アダプタは置き換えることができます。 つまり、デフォルトの接続アダプタを継承して自分の好みにあうように変更することができます。 HTTP クライアントクラス全体を書き換える必要はありません。 同じインターフェイスを実装しているだけでいいのです。 現在、Zend_Http_Client クラスは三つの組み込み接続アダプタを提供しています。 Zend_Http_Client_Adapter_Socket (デフォルト) Zend_Http_Client_Adapter_Proxy Zend_Http_Client_Adapter_Test Zend_Http_Client_Adapter_Curl Zend_Http_Client オブジェクトの接続アダプタを指定するには、 設定オプション 'adapter' を使用します。 クライアントオブジェクトのインスタンスを作成する際に、オプション 'adapter' にアダプタの名前 (たとえば 'Zend_Http_Client_Adapter_Socket' など) を指定することができます。あるいは、アダプタオブジェクトの変数 (たとえば new Zend_Http_Client_Adapter_Test など) を指定することもできます。 Zend_Http_Client->setConfig() メソッドを使用し、 アダプタを後で設定することも可能です。 ソケットアダプタ デフォルトの接続アダプタは Zend_Http_Client_Adapter_Socket です。明示的に接続アダプタを指定しない場合は、これが使用されます。 Socket アダプタは PHP の組み込み関数 fsockopen() を使用しており、特別な拡張モジュールやコンパイルオプションは必要ありません。 ソケットアダプタには、追加の設定オプションを指定することができます。これは Zend_Http_Client->setConfig() で指定するか、 あるいはクライアントのコンストラクタに渡します。 Zend_Http_Client_Adapter_Socket の設定パラメータ パラメータ 説明 予期する型 デフォルト値 persistent 持続的な TCP 接続を使用するかどうか boolean false ssltransport SSL トランスポート層 (たとえば 'sslv2'、'tls') 文字列 ssl sslcert PEM でエンコードした、SSL 証明書ファイルへのパス 文字列 null sslpassphrase SSL 証明書ファイルのパスフレーズ 文字列 null
持続的な TCP 接続 持続的な TCP 接続を使用すると、HTTP リクエストの処理速度が向上する可能性があります。 しかし、たいていの場合はその効果はごくわずかで、 接続先の HTTP サーバにかかる負荷が大きくなります。 持続的な TCP 接続を使用するのは、 同じサーバに頻繁に接続する場合で そのサーバが同時に多数の接続を処理できることがわかっている場合のみにすることを推奨します。 いずれにせよ、このオプションを使用する前には クライアント側の速度だけでなくサーバ側の負荷についてもベンチマークをとるようにしましょう。 さらに、持続的な接続を使用するときには で説明した Keep-Alive HTTP リクエストも有効にしておくことを推奨します。 そうしないと、持続的な接続の効果はほとんどといっていいほどなくなってしまいます。 HTTPS SSL ストリームパラメータ ssltransport, sslcert および sslpassphrase は、HTTPS 接続で使用する SSL レイヤーにのみ関連するものです。 たいていの場合はデフォルトの SSL 設定でうまく動作するでしょうが、 接続先のサーバが特別なクライアント設定を要求している場合は それにあわせた設定をする必要があるかもしれません。 その場合は、 ここ で SSL トランスポート層やオプションについての説明を参照ください。
HTTPS トランスポート層の変更 'Zend_Http_Client_Adapter_Socket', 'ssltransport' => 'tls' ); // クライアントオブジェクトのインスタンスを作成します $client = new Zend_Http_Client('https://www.example.com', $config); // これ以降のリクエストは、TLS セキュア接続上で行われます $response = $client->request(); ]]> 上の例の結果は、次の PHP コマンドで TCP 接続をオープンした場合と同じになります。 fsockopen('tls://www.example.com', 443)
プロキシアダプタ Zend_Http_Client_Adapter_Proxy アダプタはデフォルトのソケットアダプタとほぼ同じです。 ただし、対象となるサーバに直接接続するのではなく HTTP プロキシサーバを経由して接続するという点が異なります。 これにより、Zend_Http_Client をプロキシサーバの中から使用できるようになります。 セキュリティやパフォーマンス上の理由により、これが必要となる場合もあるでしょう。 プロキシアダプタを使用するには、 デフォルトの 'adapter' オプション以外に いくつか追加のパラメータを設定する必要があります。 Zend_Http_Client の設定パラメータ パラメータ 説明 想定している型 値の例 proxy_host プロキシサーバのアドレス string 'proxy.myhost.com' あるいは '10.1.2.3' proxy_port プロキシサーバの TCP ポート integer 8080 (デフォルト) あるいは 81 proxy_user 必要に応じて、プロキシのユーザ名 string 'shahar' あるいは指定しない場合は '' (デフォルト) proxy_pass 必要に応じて、プロキシのパスワード string 'secret' あるいは指定しない場合は '' (デフォルト) proxy_auth プロキシの HTTP 認証形式 string Zend_Http_Client::AUTH_BASIC (デフォルト)
proxy_host は常に設定しなければなりません。指定しなかった場合は、 自動的に Zend_Http_Client_Adapter_Socket による直接接続に切り替わります。 proxy_port のデフォルトは '8080' です。もし別のポートをプロキシで使用している場合は、 適切に設定する必要があります。 proxy_user および proxy_pass は、 プロキシサーバが認証を必要とする場合にのみ設定します。 これらを指定すると、'Proxy-Authentication' ヘッダがリクエストに追加されます。プロキシで認証を必要としない場合は、 このふたつのオプションはそのままにしておきます。 proxy_auth は、プロキシが認証を必要としている場合に、 その認証形式を指定します。設定できる値は Zend_Http_Client::setAuth() メソッドと同じです。現在はベーシック認証 (Zend_Http_Client::AUTH_BASIC) のみをサポートしています。 プロキシサーバを使用した Zend_Http_Client の使用法 'Zend_Http_Client_Adapter_Proxy', 'proxy_host' => 'proxy.int.zend.com', 'proxy_port' => 8000, 'proxy_user' => 'shahar.e', 'proxy_pass' => 'bananashaped' ); // クライアントオブジェクトのインスタンスを作成します $client = new Zend_Http_Client('http://www.example.com', $config); // 作業を続けます... ]]> 説明したとおり、もし proxy_host を省略したり空文字列を設定したりすると、 自動的に直接接続に切り替わります。これにより、設定パラメータによって オプションでプロキシを使用できるようなアプリケーションを書くことが可能となります。
テストアダプタ HTTP 接続に依存するテストコードを書くのは非常に難しいものです。 たとえば、リモートサーバから RSS を取得するアプリケーションをテストするには、 ネットワークにつながっている必要があります。常にネットワークが使用できるとは限りません。 このようなときのためにあるのが Zend_Http_Client_Adapter_Test アダプタです。 Zend_Http_Client を使用するアプリケーションを作成し、それをテストしたい場合には、 デフォルトのアダプタを Test アダプタ (モックオブジェクト) に変更します。 これで、サーバに接続せずにテストを行えるようになります。 Zend_Http_Client_Adapter_Test には setResponse() というメソッドがあります。 このメソッドのパラメータには、HTTP レスポンスをテキストか Zend_Http_Response オブジェクトで指定することができます。 レスポンスを設定すると、Test アダプタは常にこのレスポンスを返すようになります。 実際の HTTP リクエストは行いません。 HTTP レスポンススタブを使用したテスト $adapter )); // 想定するレスポンスを設定します $adapter->setResponse( "HTTP/1.1 200 OK" . "\r\n" . "Content-type: text/xml" . "\r\n" . "\r\n" . '' . '' . ' ' . ' Premature Optimization' . // などなど... ''); $response = $client->request('GET'); // .. $response の処理を続けます... ]]> 上の例のようにすると、HTTP クライアントにお望みのレスポンスを返させることができます。 その際にネットワーク接続は使用しません。また、実際のサーバからのレスポンスも使用しません。 この場合、このテストでテストするのは、 レスポンス本文の XML をアプリケーションが正しくパースできるかどうかということです。 時には、オブジェクトに対するひとつのメソッド呼び出しの中で複数の HTTP トランザクションを行うこともあるでしょう。そのような場合は setResponse() を単独で使うことはできません。なぜなら、 結果が呼び出し元に返ってくるまで次のレスポンスを設定できないからです。 複数の HTTP レスポンススタブを使用したテスト $adapter )); // 最初の応答として期待する値を設定します $adapter->setResponse( "HTTP/1.1 302 Found" . "\r\n" . "Location: /" . "\r\n" . "Content-Type: text/html" . "\r\n" . "\r\n" . '' . ' Moved' . '

This page has moved.

' . ''); // それに続くレスポンスを設定します $adapter->addResponse( "HTTP/1.1 200 OK" . "\r\n" . "Content-Type: text/html" . "\r\n" . "\r\n" . '' . ' My Pet Store Home Page' . '

...

' . ''); // HTTP クライアントオブジェクト ($client) をテスト対象の // オブジェクトに注入し、オブジェクトの動きを以下でテストします ]]>
setResponse() メソッドは、 Zend_Http_Client_Adapter_Test のバッファにあるレスポンスをすべて削除し、 最初に返されるレスポンスを設定します。addResponse() メソッドは、それに続くレスポンスを追加します。 レスポンスは、それを追加した順に再生されます。 登録したよりも多くのリクエストが発生した場合は、 返されるレスポンスは最初のものに戻り、そこからまた順に返されるようになります。 上の例で、このアダプタがテストするように設定されているのは、 302 リダイレクトが発生した場合のオブジェクトの挙動です。 アプリケーションの内容によって、リダイレクトさせるべきなのかそうでないのかは異なるでしょう。 この例ではリダイレクトさせることを想定しているので、 テストアダプタもそれにあわせて設定しています。 最初の 302 レスポンスを setResponse() メソッドで設定し、 次に返される 200 レスポンスを addResponse() メソッドで設定します。 テストアダプタを設定し終えたら、そのアダプタを含む HTTP クライアントをテスト対象オブジェクトに注入し、その挙動をテストします。
cURL アダプタ cURL は標準的な HTTP クライアントライブラリで、 多くの OS に含まれています。また PHP からは cURL 拡張モジュールで使用することができます。 HTTP クライアントで起こりうる多くの特別な例にも対応することができるので、 HTTP アダプタとしては完璧な選択肢といえるでしょう。 セキュアな接続やプロキシ、そしてあらゆる種類の認証にも対応しており、 大きなファイルをサーバ間で移動させるときなどにも使用できます。 cURL オプションの設定 'Zend_Http_Client_Adapter_Curl', 'curloptions' => array(CURLOPT_FOLLOWLOCATION => true), ); $client = new Zend_Http_Client($uri, $config); ]]> デフォルトでは、cURL アダプタは Socket アダプタとまったく同じ挙動となるように設定されています。 cURL のオプションを変更するには、アダプタのコンストラクタでキー 'curloptions' を指定するか、あるいは setCurlOption($name, $value) をコールします。 $name は、cURL 拡張モジュールの CURL_* 定数に対応します。 ハンドルによるファイル転送 cURL を使用して、巨大なファイルを HTTP 越しに転送することができます。 setAdapter($adapter); $adapter->setConfig(array( 'curloptions' => array( CURLOPT_INFILE => $putFileHandle, CURLOPT_INFILESIZE => $putFileSize ) )); $client->request("PUT"); ]]> 独自の接続アダプタの作成 独自の接続アダプタを作成し、それを使用することもできます。 たとえば持続的なソケットを使用するアダプタを作成したり、 キャッシュ機能を追加したアダプタを作成したりなど、 作成するアプリケーションの要件にあわせたものを作成することが可能です。 そのためには、Zend_Http_Client_Adapter_Interface を実装したクラスを作成する必要があります。 以下の例は、ユーザ定義のアダプタクラスの雛形となります。 この例で定義されているすべてのパブリック関数を、 アダプタで定義する必要があります。 独自の接続アダプタの作成 'MyApp_Http_Client_Adapter_BananaProtocol' )); ]]>