AWS SDK for PHP バージョン 3 でのハンドラーとミドルウェア - AWS SDK for PHP

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS SDK for PHP バージョン 3 でのハンドラーとミドルウェア

AWS SDK for PHP を拡張するには、主なメカニズムとしてハンドラーミドルウェアを使用します。各 SDK クライアントクラスには、クライアントの Aws\HandlerList メソッドでアクセスできる独自の getHandlerList() インスタンスがあります。クライアントの HandlerList を取得して変更することによって、クライアントの動作を追加または削除できます。

ハンドラー

ハンドラーは、コマンドおよびリクエストから結果への実際の変換を実行する関数です。ハンドラーは、通常、HTTP リクエストを送信します。ハンドラーをミドルウェアで構成して動作を補強できます。ハンドラー関数は、Aws\CommandInterfacePsr\Http\Message\RequestInterface を受け入れて、Aws\ResultInterface で満たすかまたは Aws\Exception\AwsException 理由で拒否する promise を返します。

次に示しているハンドラーは、呼び出しごとに同じ Mock 結果を返します。

use Aws\CommandInterface; use Aws\Result; use Psr\Http\Message\RequestInterface; use GuzzleHttp\Promise; $myHandler = function (CommandInterface $cmd, RequestInterface $request) { $result = new Result(['foo' => 'bar']); return Promise\promise_for($result); };

クライアントのコンストラクタの handler オプションにこのハンドラーを指定することによって、SDK クライアントで使用できます。

// Set the handler of the client in the constructor $s3 = new Aws\S3\S3Client([ 'region' => 'us-east-1', 'version' => '2006-03-01', 'handler' => $myHandler ]);

クライアントを作成した後に、setHandlerAws\ClientInterface メソッドを使用して、そのクライアントのハンドラーを変更することもできます。

// Set the handler of the client after it is constructed $s3->getHandlerList()->setHandler($myHandler);
注記

コンストラクトした後、マルチリージョンクライアントのハンドラーを変更するには、Aws\MultiRegionClientuseCustomHandler メソッドを使用します。

$multiRegionClient->useCustomHandler($myHandler);

Mock ハンドラー

SDK を使用するテストを記述する場合は MockHandler を使用することをお勧めします。Aws\MockHandler を使用して、模擬結果を返すか、または Mock 例外をスローできます。結果または例外をキューに追加すると、MockHandler は FIFO ルールに従ってそれをキューから削除します。

use Aws\Result; use Aws\MockHandler; use Aws\DynamoDb\DynamoDbClient; use Aws\CommandInterface; use Psr\Http\Message\RequestInterface; use Aws\Exception\AwsException; $mock = new MockHandler(); // Return a mocked result $mock->append(new Result(['foo' => 'bar'])); // You can provide a function to invoke; here we throw a mock exception $mock->append(function (CommandInterface $cmd, RequestInterface $req) { return new AwsException('Mock exception', $cmd); }); // Create a client with the mock handler $client = new DynamoDbClient([ 'region' => 'us-west-2', 'version' => 'latest', 'handler' => $mock ]); // Result object response will contain ['foo' => 'bar'] $result = $client->listTables(); // This will throw the exception that was enqueued $client->listTables();

ミドルウェア

ミドルウェアは、コマンドの転送動作を補強して「next」ハンドラーに委任する、特殊なタイプの高レベル関数です。ミドルウェア関数は Aws\CommandInterfacePsr\Http\Message\RequestInterface を受け入れて、Aws\ResultInterface で満たすかまたは Aws\Exception\AwsException 理由で拒否する promise を返します。

ミドルウェアは高次関数であり、ミドルウェアを通過したコマンド、リクエスト、または結果が変更されます。ミドルウェアは次のような形式です。

use Aws\CommandInterface; use Psr\Http\Message\RequestInterface; $middleware = function () { return function (callable $handler) use ($fn) { return function ( CommandInterface $command, RequestInterface $request = null ) use ($handler, $fn) { // Do something before calling the next handler // ... $promise = $fn($command, $request); // Do something in the promise after calling the next handler // ... return $promise; }; }; };

ミドルウェアは、実行する 1 つのコマンドと 1 つのリクエストオブジェクト (省略可能) を受け取ります。ミドルウェアは、リクエストおよびコマンドを補強するかそのままにするかを選択できます。ミドルウェアは、チェーン内の次のハンドラーを呼び出すか、または次のハンドラーを省略して promise を返すことを選択できます。次のハンドラーを呼び出すことによって作成された promise を、その promise の then メソッドを使用して、promise をミドルウェアのスタックに戻す前に最終結果またはエラーを変更するように補強できます。

HandlerList

SDK では、コマンドの実行時に使用されるミドルウェアとハンドラーを管理するために Aws\HandlerList が使用されます。各 SDK クライアントには独自の HandlerList があり、その HandlerList のクローンが作成され、クライアントで作成された各コマンドに追加されます。ミドルウェアをクライアントの HandlerList に追加することによって、ミドルウェアとデフォルトハンドラーをアタッチして、クライアントで作成された各コマンドで使用されるようにできます。特定のコマンドで所有されている HandlerList を変更することによって、そのコマンドに対してミドルウェアを追加および削除できます。

HandlerList は、ハンドラーをラップするために使用されるミドルウェアのスタックを表します。ミドルウェアのリストとミドルウェアがハンドラーをラップする順序を管理しやすいように、HandlerList では、ミドルウェアスタックは次のように、コマンドの転送のライフサイクルの各部分を表す名前付きのステップに分かれています。

  1. init - デフォルトパラメーターを追加します

  2. validate - 必須パラメーターを検証します

  3. build - HTTP リクエストを送信用にシリアル化します

  4. sign - シリアル化した HTTP リクエストに署名します

  5. <handler> (ステップではありませんが、実際の転送を実行します)

初期化

このライフサイクルステップは、コマンドの初期化を表し、リクエストはまだシリアル化されていません。このステップは通常、コマンドにデフォルトパラメーターを追加するために使用されます。

init および appendInit メソッドを使用して、prependInit ステップにミドルウェアを追加できます。ミドルウェアは、appendInit では prepend リストの末尾に追加され、prependInit では prepend リストの先頭に追加されます。

use Aws\Middleware; $middleware = Middleware::tap(function ($cmd, $req) { // Observe the step }); // Append to the end of the step with a custom name $client->getHandlerList()->appendInit($middleware, 'custom-name'); // Prepend to the beginning of the step $client->getHandlerList()->prependInit($middleware, 'custom-name');
validate

このライフサイクルステップは、コマンドの入力パラメーターを検証するために使用されます。

validate および appendValidate メソッドを使用して、prependValidate ステップにミドルウェアを追加できます。ミドルウェアは、appendValidate では validate リストの末尾に追加され、prependValidate では validate リストの先頭に追加されます。

use Aws\Middleware; $middleware = Middleware::tap(function ($cmd, $req) { // Observe the step }); // Append to the end of the step with a custom name $client->getHandlerList()->appendValidate($middleware, 'custom-name'); // Prepend to the beginning of the step $client->getHandlerList()->prependValidate($middleware, 'custom-name');
buid (構築)

このライフサイクルステップは、実行するコマンドの HTTP リクエストをシリアル化するために使用されます。下流のライフサイクルイベントは、コマンドと PSR-7 HTTP リクエストを受け取ります。

build および appendBuild メソッドを使用して、prependBuild ステップにミドルウェアを追加できます。ミドルウェアは、appendBuild では build リストの末尾に追加され、prependBuild では build リストの先頭に追加されます。

use Aws\Middleware; $middleware = Middleware::tap(function ($cmd, $req) { // Observe the step }); // Append to the end of the step with a custom name $client->getHandlerList()->appendBuild($middleware, 'custom-name'); // Prepend to the beginning of the step $client->getHandlerList()->prependBuild($middleware, 'custom-name');
sign

このライフサイクルステップは通常、送信前に HTTP リクエストに署名するために使用されます。通常は、署名エラーを避けるために、署名した後に HTTP リクエストを変更しないでください。

このステップは、HTTP リクエストがハンドラーによって転送される前の、HandlerList での最後のステップです。

sign および appendSign メソッドを使用して、prependSign ステップにミドルウェアを追加できます。ミドルウェアは、appendSign では sign リストの末尾に追加され、prependSign では sign リストの先頭に追加されます。

use Aws\Middleware; $middleware = Middleware::tap(function ($cmd, $req) { // Observe the step }); // Append to the end of the step with a custom name $client->getHandlerList()->appendSign($middleware, 'custom-name'); // Prepend to the beginning of the step $client->getHandlerList()->prependSign($middleware, 'custom-name');

使用可能なミドルウェア

この SDK には、クライアントの動作を補強するため、またはクライアントまたはコマンドの実行を確認するために使用できるいくつかのミドルウェアが付属しています。

mapCommand

Aws\Middleware::mapCommand ミドルウェアは、コマンドが HTTP リクエストとしてシリアル化される前に、そのコマンドを変更する必要がある場合に便利です。たとえば、mapCommand を使用して、デフォルトパラメーターの検証または追加を実行できます。mapCommand 関数は、Aws\CommandInterface オブジェクトを受け入れて Aws\CommandInterface オブジェクトを返す呼び出し可能関数を受け入れます。

use Aws\Middleware; use Aws\CommandInterface; // Here we've omitted the require Bucket parameter. We'll add it in the // custom middleware. $command = $s3Client->getCommand('HeadObject', ['Key' => 'test']); // Apply a custom middleware named "add-param" to the "init" lifecycle step $command->getHandlerList()->appendInit( Middleware::mapCommand(function (CommandInterface $command) { $command['Bucket'] = 'mybucket'; // Be sure to return the command! return $command; }), 'add-param' );

mapRequest

Aws\Middleware::mapRequest ミドルウェアは、コマンドが HTTP リクエストとしてシリアル化された後、かつ送信される前に、リクエストを変更する必要がある場合に便利です。たとえば、このミドルウェアを使用して、リクエストにカスタム HTTP ヘッダーを追加できます。mapRequest 関数は、Psr\Http\Message\RequestInterface 引数を受け入れて Psr\Http\Message\RequestInterface オブジェクトを返す呼び出し可能関数を受け入れます。

use Aws\Middleware; use Psr\Http\Message\RequestInterface; // Create a command so that we can access the handler list $command = $s3Client->getCommand('HeadObject', [ 'Key' => 'test', 'Bucket' => 'mybucket' ]); // Apply a custom middleware named "add-header" to the "build" lifecycle step $command->getHandlerList()->appendBuild( Middleware::mapRequest(function (RequestInterface $request) { // Return a new request with the added header return $request->withHeader('X-Foo-Baz', 'Bar'); }), 'add-header' );

これで、コマンドが実行されたときに、カスタムヘッダー付きで送信されるようになりました。

重要

このミドルウェアは、build ステップの最後でハンドラーリストに追加されています。これは、リクエストが作成された後に、このミドルウェアが呼び出されるようにするためです。

mapResult

Aws\Middleware::mapResult ミドルウェアは、コマンドの実行結果を変更する必要がある場合に便利です。mapResult 関数は、Aws\ResultInterface 引数を受け入れて Aws\ResultInterface オブジェクトを返す呼び出し可能関数を受け入れます。

use Aws\Middleware; use Aws\ResultInterface; $command = $s3Client->getCommand('HeadObject', [ 'Key' => 'test', 'Bucket' => 'mybucket' ]); $command->getHandlerList()->appendSign( Middleware::mapResult(function (ResultInterface $result) { // Add a custom value to the result $result['foo'] = 'bar'; return $result; }) );

これで、コマンドが実行されたときに、返される結果に foo 属性が含まれるようになりました。

history

history ミドルウェアは、SDK で、期待どおりのコマンドが実行され、期待どおりの HTTP リクエストが送信され、期待どおりの結果が受け取られたかどうかをテストする場合に便利です。これは、実質的には、ウェブブラウザの履歴と同じように動作するミドルウェアです。

use Aws\History; use Aws\Middleware; $ddb = new Aws\DynamoDb\DynamoDbClient([ 'version' => 'latest', 'region' => 'us-west-2' ]); // Create a history container to store the history data $history = new History(); // Add the history middleware that uses the history container $ddb->getHandlerList()->appendSign(Middleware::history($history));

Aws\History 履歴コンテナには、デフォルトでは 10 個のエントリが保存され、それを越えるエントリは消去されます。このエントリ数は、保持するエントリ数をコンストラクタに渡すことによってカスタマイズできます。

// Create a history container that stores 20 entries $history = new History(20);

history ミドルウェアに渡すリクエストの実行後に、履歴コンテナを調べることができます。

// The object is countable, returning the number of entries in the container count($history); // The object is iterable, yielding each entry in the container foreach ($history as $entry) { // You can access the command that was executed var_dump($entry['command']); // The request that was serialized and sent var_dump($entry['request']); // The result that was received (if successful) var_dump($entry['result']); // The exception that was received (if a failure occurred) var_dump($entry['exception']); } // You can get the last Aws\CommandInterface that was executed. This method // will throw an exception if no commands have been executed. $command = $history->getLastCommand(); // You can get the last request that was serialized. This method will throw an exception // if no requests have been serialized. $request = $history->getLastRequest(); // You can get the last return value (an Aws\ResultInterface or Exception). // The method will throw an exception if no value has been returned for the last // executed operation (e.g., an async request has not completed). $result = $history->getLastReturn(); // You can clear out the entries using clear $history->clear();

tap

tap ミドルウェアはオブザーバーとして使用されます。このミドルウェアを使用して、ミドルウェアのチェーンを通じてコマンドを送信するときに関数を呼び出すことができます。この tap 関数は、実行される Aws\CommandInterface および Psr\Http\Message\RequestInterface (省略可能) を受け入れる呼び出し可能関数を受け入れます。

use Aws\Middleware; $s3 = new Aws\S3\S3Client([ 'region' => 'us-east-1', 'version' => '2006-03-01' ]); $handlerList = $s3->getHandlerList(); // Create a tap middleware that observes the command at a specific step $handlerList->appendInit( Middleware::tap(function (CommandInterface $cmd, RequestInterface $req = null) { echo 'About to send: ' . $cmd->getName() . "\n"; if ($req) { echo 'HTTP method: ' . $request->getMethod() . "\n"; } } );

カスタムハンドラーの作成

ハンドラーは、Aws\CommandInterfacePsr\Http\Message\RequestInterface を受け入れて、GuzzleHttp\Promise\PromiseInterface で満たすかまたは Aws\ResultInterface 理由で拒否する Aws\Exception\AwsException を返すだけの関数です。

SDK にはいくつかの @http オプションがありますが、以下のオプションの使用法を知る必要があるのはハンドラーだけです。

このオプションが省略可能として指定されている場合を除いて、ハンドラーはこのオプションを処理できる必要があり、そうでない場合は拒否された promise を返す必要があります。

特定の @http オプションを処理することに加えて、ハンドラーは次の形式の User-Agent ヘッダーを追加する必要があります。ここで、「3.X」は Aws\Sdk::VERSION に置き換えることができ、「HandlerSpecificData/version ...」はハンドラー固有の User-Agent 文字列に置き換える必要があります。

User-Agent: aws-sdk-php/3.X HandlerSpecificData/version ...