

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Gestionnaires et intergiciels dans la version 3 AWS SDK pour PHP
<a name="guide_handlers-and-middleware"></a>

Le principal mécanisme d'extension passe par les AWS SDK pour PHP **gestionnaires et les** **intergiciels**. Chaque classe de client de kit SDK possède une instance `Aws\HandlerList` accessible via la méthode `getHandlerList()` d'un client. Vous pouvez récupérer la `HandlerList` d'un client et la modifier afin d'ajouter ou de supprimer un comportement client.

## Gestionnaires
<a name="handlers"></a>

Un gestionnaire est une fonction qui transforme une commande et une requête en un résultat. Il envoie généralement des requêtes HTTP. Les gestionnaires peuvent comporter des intergiciels, qui renforcent leur comportement. Un gestionnaire est une fonction qui accepte un `Aws\CommandInterface` et un `Psr\Http\Message\RequestInterface`, et renvoie une promesse exécutée avec un `Aws\ResultInterface` ou rejetée avec une raison `Aws\Exception\AwsException`.

Voici un gestionnaire qui renvoie le même résultat fictif pour chaque appel.

```
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);
};
```

Vous pouvez utiliser ce gestionnaire avec un client de kit SDK en spécifiant une option `handler` dans le constructeur du client.

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

Vous pouvez également modifier le gestionnaire existant d'un client à l'aide de la méthode `setHandler` de `Aws\ClientInterface`.

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

**Note**  
Pour modifier le gestionnaire d'un client multirégional une fois celui-ci construit, utilisez la `useCustomHandler` méthode d'un. `Aws\MultiRegionClient`  

```
$multiRegionClient->useCustomHandler($myHandler);
```

### Gestionnaire fictif
<a name="mock-handler"></a>

Nous vous recommandons d'utiliser `MockHandler` lorsque vous écrivez des tests qui utilisent le kit SDK. `Aws\MockHandler` vous permet de renvoyer des résultats fictifs ou de lancer des exceptions de simulation. Vous mettez en file d'attente les résultats ou les exceptions, puis vous les MockHandler replacez dans l'ordre 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();
```

## Intergiciel
<a name="middleware"></a>

Un intergiciel est un type spécial de fonction de haut niveau qui augmente le comportement de transfert d'une commande et délègue la tâche à un gestionnaire « suivant ». Les fonctions d'intergiciel acceptent un `Aws\CommandInterface` et un `Psr\Http\Message\RequestInterface`, et renvoient une promesse exécutée avec un `Aws\ResultInterface` ou rejetée avec une raison `Aws\Exception\AwsException`.

Un intergiciel est une fonction supérieure qui modifie les commandes, les requêtes ou les résultats qu'il traite. Un intergiciel se présente sous la forme suivante.

```
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;
        };
    };
};
```

Un intergiciel reçoit une commande à exécuter et un objet de requête facultatif. Il peut choisir d'augmenter la requête et la commande ou de les laisser en l'état. Un intergiciel appelle le gestionnaire suivant de la chaîne ou choisit de le court-circuiter et de renvoyer une promesse. La promesse ainsi créée en appelant le gestionnaire suivant peut alors être augmentée à l'aide de la méthode `then` de la promesse afin de modifier le résultat ou l'erreur avant le renvoi de la promesse à la pile d'intergiciels.

### HandlerList
<a name="handlerlist"></a>

Le kit SDK utilise `Aws\HandlerList` pour gérer les intergiciels et les gestionnaires utilisés lors de l'exécution d'une commande. Chaque client du kit SDK possède une `HandlerList`. Cette `HandlerList` est clonée et ajoutée à chaque commande créée par un client. Vous pouvez attacher un intergiciel et un gestionnaire par défaut à utiliser pour chaque commande créée par un client en ajoutant un intergiciel à la `HandlerList` du client. Vous pouvez ajouter et supprimer des intergiciels de certaines commandes spécifiques en modifiant la `HandlerList` appartenant à une commande spécifique.

`HandlerList` représente une pile d’intergiciels utilisés pour encapsuler un **gestionnaire**. Pour vous aider à gérer la liste d'intergiciels et l'ordre dans lequel ils encapsulent un gestionnaire, `HandlerList` divise la pile d'intergiciels en plusieurs étapes nommées qui représentent une partie du cycle de vie du transfert d'une commande :

1.  `init` - Ajout des paramètres par défaut

1.  `validate` - Validation des paramètres obligatoires

1.  `build` - Sérialisation d'une requête HTTP pour envoi

1.  `sign` - Signature de la requête HTTP sérialisée

1. <handler> (il ne s’agit pas ici d’une étape, mais du transfert lui-même)

**init**  
Cette étape du cycle de vie représente l'initialisation d'une commande. La requête n'a pas encore été sérialisée. Cette étape est généralement utilisée pour ajouter des paramètres par défaut à une commande.  
Vous pouvez ajouter un intergiciel à l'étape `init` à l'aide des méthodes `appendInit` et `prependInit`, où `appendInit` ajoute l'intergiciel à la fin de la liste `prepend`, et où `prependInit` ajoute l'intergiciel au début de la liste `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');
```

**valider**  
Cette étape du cycle de vie permet de valider les paramètres d'entrée d'une commande.  
Vous pouvez ajouter un intergiciel à l'étape `validate` à l'aide des méthodes `appendValidate` et `prependValidate`, où `appendValidate` ajoute l'intergiciel à la fin de la liste `validate`, et où `prependValidate` ajoute l'intergiciel au début de la liste `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');
```

**build**  
Cette étape du cycle de vie permet de sérialiser une requête HTTP pour la commande en cours d'exécution. Les événements du cycle de vie en aval recevront une commande et une requête HTTP PSR-7.  
Vous pouvez ajouter un intergiciel à l'étape `build` à l'aide des méthodes `appendBuild` et `prependBuild`, où `appendBuild` ajoute l'intergiciel à la fin de la liste `build`, et où `prependBuild` ajoute l'intergiciel au début de la liste `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**  
Cette étape du cycle de vie est généralement utilisée pour signer les requêtes HTTP avant leur envoi sur le réseau. De manière générale, nous vous recommandons d'éviter de muter une requête HTTP qui a déjà été signée afin d'éviter les erreurs de signature.  
Il s'agit de la dernière étape de `HandlerList` avant le transfert de la requête HTTP par un gestionnaire.  
Vous pouvez ajouter un intergiciel à l'étape `sign` à l'aide des méthodes `appendSign` et `prependSign`, où `appendSign` ajoute l'intergiciel à la fin de la liste `sign`, et où `prependSign` ajoute l'intergiciel au début de la liste `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');
```

### Intergiciels disponibles
<a name="available-middleware"></a>

Le kit SDK comporte plusieurs intergiciels que vous pouvez utiliser pour augmenter le comportement d'un client ou pour observer l'exécution d'une commande.

#### mapCommand
<a name="map-command"></a>

L'intergiciel `Aws\Middleware::mapCommand` vous permet de modifier une commande avant qu'elle ne soit sérialisée en tant que requête HTTP. Par exemple, vous pouvez utiliser `mapCommand` pour effectuer une validation ou pour ajouter des paramètres par défaut. La fonction `mapCommand` accepte une fonction de type callable, qui accepte un objet `Aws\CommandInterface` et renvoie un objet `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'] = 'amzn-s3-demo-bucket';
        // Be sure to return the command!
        return $command;
    }),
    'add-param'
);
```

#### mapRequest
<a name="map-request"></a>

L'intergiciel `Aws\Middleware::mapRequest` vous permet de modifier une requête après sa sérialisation, mais avant son envoi. Vous pouvez par exemple l'utiliser pour ajouter des en-têtes HTTP personnalisés à une requête. La fonction `mapRequest` accepte une fonction de type callable, qui accepte un argument `Psr\Http\Message\RequestInterface` et renvoie un objet `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' => 'amzn-s3-demo-bucket'
]);

// 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'
);
```

Désormais, lorsque la commande est exécutée, elle est envoyée avec l'en-tête personnalisé.

**Important**  
Notez que l'intergiciel a été ajouté à la liste des gestionnaires à la fin de l'étape `build`. Cela permet de s'assurer qu'une requête a été créée avant l'appel de cet intergiciel.

#### mapResult
<a name="mapresult"></a>

L'intergiciel `Aws\Middleware::mapResult` permet de modifier le résultat de l'exécution d'une commande. La fonction `mapResult` accepte une fonction de type callable, qui accepte un argument `Aws\ResultInterface` et renvoie un objet `Aws\ResultInterface`.

```
use Aws\Middleware;
use Aws\ResultInterface;

$command = $s3Client->getCommand('HeadObject', [
    'Key'    => 'test',
    'Bucket' => 'amzn-s3-demo-bucket'
]);

$command->getHandlerList()->appendSign(
    Middleware::mapResult(function (ResultInterface $result) {
        // Add a custom value to the result
        $result['foo'] = 'bar';
        return $result;
    })
);
```

Désormais, lorsque la commande est exécutée, le résultat renvoyé contient un attribut `foo`.

#### historique
<a name="history"></a>

L'intergiciel `history` permet de vérifier que le kit SDK a bien exécuté les commandes attendues, qu'il a bien envoyé les requêtes HTTP spécifiées, et qu'il a bien reçu les résultats escomptés. Globalement, il agit de manière similaire à l'historique d'un navigateur web.

```
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));
```

Un conteneur d'historique `Aws\History` stocke 10 entrées par défaut avant de purger ses entrées. Vous pouvez personnaliser le nombre d'entrées en indiquant combien le constructeur peut en recevoir.

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

Vous pouvez inspecter le conteneur d'historique après l'exécution de requêtes traitées par l'intergiciel d'historique.

```
// 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
<a name="tap"></a>

L'intergiciel `tap` fonctionne comme un observateur. Vous pouvez l'utiliser pour appeler des fonctions lors de l'envoi de commandes via la chaîne d'intergiciels. La fonction `tap` accepte une fonction de type callable qui accepte `Aws\CommandInterface` et une option `Psr\Http\Message\RequestInterface` en cours d'exécution (facultatif).

```
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";
        }
    }
);
```

## Création de gestionnaires personnalisés
<a name="creating-custom-handlers"></a>

Un gestionnaire est une fonction qui accepte des objets `Aws\CommandInterface` et `Psr\Http\Message\RequestInterface`, et renvoie une promesse `GuzzleHttp\Promise\PromiseInterface` exécutée avec `Aws\ResultInterface` ou rejetée avec `Aws\Exception\AwsException`.

Même si le kit SDK possède plusieurs options `@http`, un gestionnaire n'a besoin de savoir utiliser que les options suivantes :
+  [connect\_timeout](guide_configuration.md#http-connect-timeout) 
+  [debug](guide_configuration.md#http-debug) 
+  [decode\_content](guide_configuration.md#http-decode-content) (facultatif)
+  [delay](guide_configuration.md#http-delay) 
+  [progress](guide_configuration.md#http-progress) (facultatif)
+  [proxy](guide_configuration.md#http-proxy) 
+  [sink](guide_configuration.md#http-sink) 
+  [synchronous](guide_configuration.md#http-sync) (facultatif)
+  [stream](guide_configuration.md#http-stream) (facultatif)
+  [timeout](guide_configuration.md#http-timeout) 
+  [verify](guide_configuration.md#http-verify) 
+ http\_stats\_receiver (facultatif) - Fonction à appeler avec un tableau associatif de statistiques de transfert HTTP sur demande à l’aide du paramètre de configuration [stats](guide_configuration.md#config-stats).

Un gestionnaire DOIT pouvoir gérer l'option ou DOIT renvoyer une promesse rejetée, sauf si l'option est spécifiée comme étant facultative.

En plus de gérer des `@http` options spécifiques, un gestionnaire DOIT ajouter un `User-Agent` en-tête qui prend la forme suivante, où « 3.X » peut être remplacé par `Aws\Sdk::VERSION` et « HandlerSpecificData /version... » doit être remplacé par la chaîne User-Agent spécifique à votre gestionnaire.

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