====== PSR-18: HTTP Client ====== --- //[[http://www.y2sunlight.com|y2sunlight]] 2020-07-28// 本章は、若干の補足を加筆してはいるものの単に[[https://www.php-fig.org/psr/|PSRのサイト]]を日本語に翻訳したものに過ぎません。英語が堪能な方は原文をご参照下さい。翻訳に当たっては、基本的に機械翻訳を使い、理解できない部分は独断で意訳しております。拙い訳では御座いますが恥を忍んで投稿しておりますので、ご指摘など御座いましたらコメントを頂ければ幸いです。 関連記事 * [[psr:top|PSR - PHP標準勧告]] * [[psr:psr1|PSR-1: Basic Coding Standard - 基本コーディング規約]] * [[psr:psr3|PSR-3: Logger Interface - ロガーインターフェイス]] * [[psr:psr4|PSR-4: Autoloading Standard - オートローディング規約]] * [[psr:psr5|PSR-5: PHPDoc Standard(Draft) - PHPDoc規約]] * [[psr:psr6|PSR-6: Caching Interface - キャッシングインターフェイス]] * [[psr:psr7|PSR-7: HTTP Message Interface - HTTPメッセージインターフェイス]] * [[psr:psr11|PSR-11: Container Interface - コンテナインターフェイス]] * [[psr:psr12|PSR-12: Extended Coding Style - 拡張コーディングスタイル]] * [[psr:psr13|PSR-13: Link definition interfaces - リンク定義インターフェース]] * [[psr:psr14|PSR-14: Event Dispatcher - イベントディスパッチャー]] * [[psr:psr15|PSR-15: HTTP Server Request Handlers - HTTPサーバーリクエストハンドラー]] * [[psr:psr16|PSR-16: Common Interface for Caching Libraries - キャッシングライブラリのための共通インターフェース]] * [[psr:psr17|PSR-17: HTTP Factories - HTTPファクトリー]] * PSR-18: HTTP Client - HTTPクライアント * [[psr:psr19|PSR-19: PHPDoc tags(Draft) - PHPDocタグ]] ----- ====== PSR-18: HTTPクライアント ====== --- // 原文より翻訳 [[https://www.php-fig.org/psr/psr-18/|PSR-18: HTTP Client]] 2020-08-25 現在 // このドキュメントでは、HTTPリクエストを送信し、HTTPレスポンスを受信するための一般的なインターフェースについて説明します。 このドキュメントのキーワード ''MUST'' , ''MUST NOT'' , ''REQUIRED'' , ''SHALL'' , ''SHALL NOT'' , ''SHOULD'' , ''SHOULD NOT'' , ''RECOMMENDED'' , ''MAY'' 及び ''OPTIONAL'' は、 [[https://www.ietf.org/rfc/rfc2119.txt|RFC 2119]]で説明されているように解釈して下さい。 > **RFC 2119の説明** > ''MUST'', ''REQUIRED'', ''SHALL'' --- 絶対必要 > ''MUST NOT'', ''SHALL NOT'' --- 絶対禁止 > ''SHOULD'', ''RECOMMENDED'' --- 推奨(但し、無視できる特定の正当な理由が存在するかもしれない) > ''SHOULD NOT'' --- 推奨できない(但し、許可できる特定の正当な理由が存在するかもしれない) > ''MAY'', ''OPTIONAL'' --- オプション \\ ===== 目標 ====== このPSRの目標は、開発者がHTTPクライアントの実装から分離されたライブラリを作成できるようにすることです。これにより、依存関係の数が減り、バージョンの競合の可能性が低くなるため、ライブラリの再利用性が高まります。 2番目の目標は、[[https://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%B9%E3%82%B3%E3%83%95%E3%81%AE%E7%BD%AE%E6%8F%9B%E5%8E%9F%E5%89%87|リスコフの置換原理]]に従ってHTTPクライアントを置き換えることができることです。これは、リクエストを送信するときに全てのクライアントが同じように動作する必要があること( ''MUST'' )を意味します。 \\ ===== 定義 ====== * ''クライアント'' --- ''クライアント''は、PSR-7互換のHTTPリクエストメッセージを送信し、PSR-7互換のHTTPレスポンスメッセージを呼び出し側ライブラリに返す目的でこの仕様を実装するライブラリです。\\ \\ * 呼び出しライブラリ --- 呼び出しライブラリは、このPSRで定義されているHTTP''クライアント''を利用するコードで、この仕様のインターフェースは実装していませんが、それらを実装するオブジェクト(HTTP''クライアント'')を使用しています。 \\ ===== クライアント ====== クライアントは、''ClientInterface'' を実装するオブジェクトです。 **クライアントの選択**( ''MAY'' ): * クライアントは提供されたものから変更されたHTTPリクエストを送信することを選択できます( ''MAY'' )。例えば、送信メッセージの本文を圧縮できます。\\ \\ * クライアントは呼び出したライブラリに返す前に、受信したHTTPレスポンスを変更することを選択できます( ''MAY'' )。例えば、受信メッセージの本文を解凍できます。 クライアントがHTTPリクエストまたはHTTPレスポンスのいずれかを変更することを選択した場合、オブジェクトが内部的に一貫していることを保証する必要があります( ''MUST'' )。例えば、クライアントがメッセージ本文を解凍することを選択した場合は、''Content-Encoding'' ヘッダーも削除して、''Content-Length'' ヘッダーを調整する必要があります。 その結果、[[https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-7-http-message-meta.md#why-value-objects|PSR-7オブジェクトは不変である]]ため、呼び出し側ライブラリは、''ClientInterface::sendRequest()'' に渡されたオブジェクトが実際に送信されるPHPオブジェクトと同じであることを想定してはなりません。例えば、例外によって返されるRequestオブジェクトは、''sendRequest()'' に渡されるオブジェクトとは異なるオブジェクトになる可能性があるため、参照による比較( ''==='' )はできません。 **クライアントの義務**( ''MUST'' ): * クライアントは呼び出し元ライブラリに返されるものがステータスコード200以上の有効なHTTPレスポンスになるように、マルチステップHTTP 1xxレスポンス自体を再構成する必要があります( ''MUST'' )。 \\ ===== エラー処理 ====== クライアントは、整形式のHTTPリクエストまたはHTTPレスポンスをエラー状態として扱わないでください( ''MUST NOT'' )。例えば、400と500の範囲のレスポンスステータスコードは例外を発生させてはならず( ''MUST NOT'' )、通常どおり呼び出しライブラリに返される必要があります( ''MUST'' )。 クライアントは、HTTPリクエストをまったく送信できない場合、または HTTPレスポンスを PSR-7 レスポンスオブジェクトにパースできなかった場合にのみ、''Psr\Http\Client\ClientExceptionInterface'' のインスタンスをスローする必要があります( ''MUST'' )。 リクエストメッセージが整形式のHTTPリクエストではないか、重要な情報(ホストやメソッドなど)がないためにリクエストを送信できない場合、クライアントは ''Psr\Http\Client\RequestExceptionInterface'' のインスタンスをスローする必要があります( ''MUST'' )。 タイムアウトを含むあらゆる種類のネットワーク障害が原因でリクエストを送信できない場合、クライアントは ''Psr\Http\Client\NetworkExceptionInterface'' のインスタンスをスローする必要があります( ''MUST'' )。 クライアントは、上記で定義された適切なインターフェースを実装している場合、ここで定義されたものよりも具体的な例外(例えば、 ''TimeOutException'' または ''HostNotFoundException'' )をスローできます( ''MAY'' )。 \\ ===== インターフェース ====== ==== ClientInterface ===== namespace Psr\Http\Client; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; interface ClientInterface { /** * PSR-7リクエストを送信し、PSR-7レスポンスを返します。 * * @param RequestInterface $request * @return ResponseInterface * * @throws \Psr\Http\Client\ClientExceptionInterface リクエストの処理中にエラーが発生した場合。 * */ public function sendRequest(RequestInterface $request): ResponseInterface; } \\ ==== ClientExceptionInterface ===== namespace Psr\Http\Client; /** * すべてのHTTPクライアント関連の例外は、このインターフェイスを実装する必要があります。 */ interface ClientExceptionInterface extends \Throwable { } \\ ==== RequestExceptionInterface ===== namespace Psr\Http\Client; use Psr\Http\Message\RequestInterface; /** * リクエストが失敗した場合の例外。 * * 例: * -リクエストが無効です(メソッドが見つからないなど) * -ランタイムリクエストエラー(ボディストリームがシークできないなど) */ interface RequestExceptionInterface extends ClientExceptionInterface { /** * リクエストを返します。 * * リクエストオブジェクトは、ClientInterface::sendRequest()に渡されるオブジェクトとは * 異なるオブジェクトである可能性があります * * @return RequestInterface */ public function getRequest(): RequestInterface; } \\ ==== NetworkExceptionInterface ===== namespace Psr\Http\Client; use Psr\Http\Message\RequestInterface; /** * ネットワークの問題のためにリクエストを完了できない場合にスローされます。 * * この例外は、応答が受信されなかった場合にスローされるため、応答オブジェクトはありません。 * * 例:ターゲットホスト名を解決できないか、接続が失敗しました。 */ interface NetworkExceptionInterface extends ClientExceptionInterface { /** * Returns the request. * * リクエストオブジェクトは、ClientInterface::sendRequest()に渡されるオブジェクトとは * 異なるオブジェクトである可能性があります * * @return RequestInterface */ public function getRequest(): RequestInterface; } \\