

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Gestori e middleware nella versione 3 AWS SDK per PHP
<a name="guide_handlers-and-middleware"></a>

**Il meccanismo principale per estendere il AWS SDK per PHP è tramite **gestori e middleware.**** Ogni classe di client SDK possiede un'istanza `Aws\HandlerList` accessibile tramite il metodo `getHandlerList()` di un client. Puoi recuperare un `HandlerList` del client e modificarlo per aggiungere o rimuovere il comportamento client.

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

Un gestore è una funzione che esegue l'effettiva trasformazione di un comando e richiesta in un risultato. Un gestore in genere invia richieste HTTP. I gestori possono essere composti con middleware per potenziare il comportamento. Un gestore è una funzione che accetta un `Aws\CommandInterface` e un `Psr\Http\Message\RequestInterface` e restituisce una promessa che viene soddisfatta con un `Aws\ResultInterface` o respinta con un motivo `Aws\Exception\AwsException`.

Ecco un gestore che restituisce lo stesso risultato fittizio per ogni chiamata.

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

Puoi quindi utilizzare questo gestore con un client SDK fornendo un'opzione `handler` nel costruttore di un 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
]);
```

Puoi anche modificare il gestore di un client dopo che è stata costruito utilizzando il metodo `setHandler` di un `Aws\ClientInterface`.

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

**Nota**  
Per modificare il gestore di un client multiregionale dopo la sua creazione, usa il metodo di un. `useCustomHandler` `Aws\MultiRegionClient`  

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

### Gestore fittizio
<a name="mock-handler"></a>

Ti consigliamo di usare il `MockHandler` quando scrivi test che utilizzano l'SDK. Puoi usare `Aws\MockHandler` per restituire risultati fittizi o generare eccezioni fittizie. I risultati o le eccezioni vengono accodati e poi li rimuove in ordine FIFO MockHandler .

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

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

Il middleware è uno speciale tipo di funzioni di alto livello che migliorano il comportamento di trasferimento di un comando ed eseguono la delega a un gestore "successivo". Le funzioni middleware accettano `Aws\CommandInterface` e `Psr\Http\Message\RequestInterface` e restituiscono una promessa che viene soddisfatta con `Aws\ResultInterface` o respinta con un motivo `Aws\Exception\AwsException`.

Un middleware è una funzione di ordine più alto che modifica un comando, richiesta o risultato quando passa attraverso il middleware. Un middleware ha la forma seguente.

```
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 middleware riceve un comando per l'esecuzione e un oggetto di richiesta opzionale. Il middleware può scegliere di potenziare la richiesta e il comando o di lasciarli senza alcuna modifica. Un middleware invoca quindi l'handle successivo nella catena o può scegliere di cortocircuitare il gestore successivo e restituire una promessa. La promessa creata invocando il gestore successivo può essere potenziata utilizzando il metodo `then` della promessa di modificare il risultato o l'errore prima di restituire la promessa dello stack di middleware.

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

L'SDK usa un `Aws\HandlerList` per gestire il middleware e i gestori utilizzati quando si esegue un comando. Ogni client SDK possiede un `HandlerList`e questo `HandlerList` viene clonato e aggiunto a ogni comando creato da un client. Puoi collegare un middleware e gestore predefinito da utilizzare per ogni comando creato da un client aggiungendo un middleware all'`HandlerList` del client. Puoi aggiungere e rimuovere middleware da comandi specifici modificando l'`HandlerList` di proprietà di un comando specifico.

Un `HandlerList` rappresenta uno stack di middleware che vengono utilizzato per avvolgere un **gestore**. Per aiutarti a gestire l'elenco di middleware e l'ordine in cui avvolgono un handler, l'`HandlerList` divide lo stack middleware in passaggi denominati che rappresentano parte del ciclo di vita di trasferimento di un comando:

1.  `init` - Aggiungi parametri di default

1.  `validate` - Convalida parametri obbligatori

1.  `build` - Serializza una richiesta HTTP per l'invio

1.  `sign` - Firma la richiesta HTTP serializzata

1. <gestore > (non una fase, ma esegue il trasferimento effettivo)

**init**  
Questa fase del ciclo di vita rappresenta l'inizializzazione di un comando e una richiesta non è stata ancora serializzata. Questa fase viene in genere utilizzata per aggiungere parametri di default a un comando.  
Puoi aggiungere un middleware alla fase `init` usando i metodi `appendInit` e `prependInit`, dove `appendInit` aggiunge il middleware alla fine dell'elenco `prepend` mentre `prependInit` aggiunge il middleware all'inizio dell'elenco `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**  
Questa fase del ciclo di vita viene utilizzata per convalidare i parametri di input di un comando.  
Puoi aggiungere un middleware alla fase `validate` usando i metodi `appendValidate` e `prependValidate`, dove `appendValidate` aggiunge il middleware alla fine dell'elenco `validate` mentre `prependValidate` aggiunge il middleware all'inizio dell'elenco `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**  
Questa fase del ciclo di vita viene utilizzata per serializzare una richiesta HTTP per il comando in esecuzione. Gli eventi del ciclo di vita a valle riceveranno un comando e una richiesta PSR-7 HTTP.  
Puoi aggiungere un middleware alla fase `build` usando i metodi `appendBuild` e `prependBuild`, dove `appendBuild` aggiunge il middleware alla fine dell'elenco `build` mentre `prependBuild` aggiunge il middleware all'inizio dell'elenco `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');
```

**Firma**  
Questa fase del ciclo di vita viene in genere utilizzata per firmare le richieste HTTP prima che siano inviate tramite la rete. È consigliabile in genere non mutare mai una richiesta HTTP dopo averla firmata per evitare errori di firma.  
Questa è l'ultima fase di `HandlerList` prima che la richiesta HTTP viene trasferita da un gestore.  
Puoi aggiungere un middleware alla fase `sign` usando i metodi `appendSign` e `prependSign`, dove `appendSign` aggiunge il middleware alla fine dell'elenco `sign` mentre `prependSign` aggiunge il middleware all'inizio dell'elenco `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');
```

### Middleware disponibile
<a name="available-middleware"></a>

L'SDK fornisce diversi middleware che puoi utilizzare per potenziare il comportamento di un client o per osservare l'esecuzione di un comando.

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

Il middleware `Aws\Middleware::mapCommand` è utile quando devi modificare un comando prima che il comando venga serializzato come una richiesta HTTP. Ad esempio, `mapCommand` può essere utilizzato per eseguire la convalida o aggiungere parametri di default. La funzione `mapCommand` accetta un chiamabile che accetta un oggetto `Aws\CommandInterface` e restituisce un oggetto `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>

Il middleware `Aws\Middleware::mapRequest` è utile quando devi modificare una richiesta dopo che è stata serializzata ma prima che è stata inviata. Ad esempio, questo può essere utilizzato per aggiungere intestazioni HTTP personalizzate a una richiesta. La funzione `mapRequest` accetta un chiamabile che accetta un argomento `Psr\Http\Message\RequestInterface` e restituisce un oggetto `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'
);
```

Quando si esegue il comando, viene inviata con l'intestazione personalizzata.

**Importante**  
Si noti che il middleware è stato aggiunto all'elenco dei gestori alla fine della fase `build`. Questo è per far sì che una richiesta sia stata creata prima della chiamata del middleware.

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

Il middleware `Aws\Middleware::mapResult` è utile quando devi modificare il risultato dell'esecuzione di un comando. La funzione `mapResult` accetta un chiamabile che accetta un argomento `Aws\ResultInterface` e restituisce un oggetto `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;
    })
);
```

Ora quando il comando viene eseguito, il risultato restituito conterrà un attributo `foo`.

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

Il middleware `history` è utile per verificare che l'SDK abbia eseguito i comandi previsti, inviato le richieste HTTP previste e ricevuto i risultati previsti. È essenzialmente un middleware che agisce in modo analogo alla cronologia di un browser 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 container cronologico `Aws\History` memorizza 10 voci per impostazione predefinita prima di rimuovere le voci. Puoi personalizzare il numero di voci passando il numero di voci che persistono al costruttore.

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

Puoi controllare il container cronologico dopo l'esecuzione di richieste che passano il middleware di cronologia.

```
// 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>

Il middleware `tap` viene utilizzato come osservatore. Puoi usare questo middleware per richiamare le funzioni quando invii comandi attraverso la catena di middleware. La funzione `tap` accetta un chiamabile che accetta `Aws\CommandInterface` e un ulteriore `Psr\Http\Message\RequestInterface` che viene eseguito.

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

## Creazione di gestori personalizzati
<a name="creating-custom-handlers"></a>

Un gestore è semplicemente una funzione che accetta un oggetto `Aws\CommandInterface` e un oggetto `Psr\Http\Message\RequestInterface` e restituisce un `GuzzleHttp\Promise\PromiseInterface` che viene soddisfatto con un `Aws\ResultInterface` o rifiutato con un `Aws\Exception\AwsException`.

Sebbene l'SDK disponga di diverse opzioni `@http`, un gestore deve sapere solo come utilizzare le seguenti opzioni:
+  [connect\_timeout](guide_configuration.md#http-connect-timeout) 
+  [debug](guide_configuration.md#http-debug) 
+  [decode\_content](guide_configuration.md#http-decode-content) (opzionale)
+  [delay](guide_configuration.md#http-delay) 
+  [progress](guide_configuration.md#http-progress) (opzionale)
+  [proxy](guide_configuration.md#http-proxy) 
+  [sink](guide_configuration.md#http-sink) 
+  [synchronous](guide_configuration.md#http-sync) (opzionale)
+  [stream](guide_configuration.md#http-stream) (opzionale)
+  [timeout](guide_configuration.md#http-timeout) 
+  [Verifica](guide_configuration.md#http-verify) 
+ http\_stats\_receiver (opzionale) - Una funzione per invocare con un array associativo di statistiche di trasferimento HTTP se richiesto utilizzando il parametro di configurazione [stats](guide_configuration.md#config-stats).

A meno che l'opzione non sia specificata come opzionale, un gestore DEVE essere in grado di gestire l'opzione oppure DEVE restituire una promessa rifiutata.

Oltre a gestire `@http` opzioni specifiche, un gestore DEVE aggiungere un'`User-Agent`intestazione che assuma il seguente formato, dove «3.X» può essere sostituito con `Aws\Sdk::VERSION` e «HandlerSpecificData/version...» deve essere sostituito con la stringa User-Agent specifica del gestore.

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