

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

# Manipuladores e middleware no AWS SDK para PHP versão 3
<a name="guide_handlers-and-middleware"></a>

O mecanismo principal para estender o AWS SDK para PHP é por meio de **manipuladores** e de **middleware**. Cada classe de cliente do SDK possui uma instância de `Aws\HandlerList` que pode ser acessada por meio do método `getHandlerList()` de um cliente. Você pode recuperar a `HandlerList` de um cliente e modificá-la para adicionar ou remover o comportamento do cliente.

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

Um manipulador é uma função que executa a transformação real de um comando e de uma solicitação em um resultado. Um manipulador normalmente envia solicitações HTTP. Os manipuladores podem ser compostos com middleware para aumentar seu comportamento. Um manipulador é uma função que aceita uma `Aws\CommandInterface` e uma `Psr\Http\Message\RequestInterface` e retorna uma promessa que é cumprida com uma `Aws\ResultInterface` ou rejeitada com uma razão de `Aws\Exception\AwsException`.

Este é um manipulador que retorna o mesmo resultado simulado para cada chamada.

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

Em seguida, você pode usar esse manipulador com um cliente do SDK fornecendo uma opção `handler` no construtor de um cliente.

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

Você também pode alterar o manipulador de um cliente depois que ele for construído usando o método `setHandler` de uma `Aws\ClientInterface`.

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

**nota**  
Para alterar o manipulador de um cliente multirregional após sua construção, use o método `useCustomHandler` de um `Aws\MultiRegionClient`.  

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

### Manipulador simulado
<a name="mock-handler"></a>

Recomendamos usar o `MockHandler` ao escrever testes que usam o SDK. Você pode usar o `Aws\MockHandler` para retornar resultados simulados ou gerar exceções simuladas. Você enfileira os resultados ou as exceções, e o MockHandler os remove da fila na ordem 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();
```

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

Middleware é um tipo especial de função de alto nível que aumenta o comportamento de transferência de um comando, e delega para um "próximo" manipulador. As funções de middleware aceitam uma `Aws\CommandInterface` e uma `Psr\Http\Message\RequestInterface` e retornam uma promessa que é cumprida com uma `Aws\ResultInterface` ou rejeitada com um motivo de `Aws\Exception\AwsException`.

Um middleware é uma função de ordem superior que modifica um comando, solicitação ou resultado que é passado por meio do middleware. Um middleware assume a seguinte forma.

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

Um middleware recebe um comando para execução e um objeto de solicitação opcional. O middleware pode optar por aumentar a solicitação e o comando ou deixá-los no estado em que se encontram. Em seguida, um middleware chama a próxima alça na cadeia ou pode escolher dar um curto circuito no próximo manipulador e retornar uma promessa. A promessa criada chamando o próximo manipulador pode ser aumentada usando o método `then` da promessa para modificar o eventual resultado ou o erro antes de retornar a promessa de volta para a pilha do middleware.

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

O SDK usa uma `Aws\HandlerList` para gerenciar o middleware e os manipuladores usados ao executar um comando. Cada cliente do SDK possui uma `HandlerList`, e essa `HandlerList` é clonada e adicionada a cada comando criado por um cliente. Você pode anexar um middleware e um manipulador padrão a ser usado para cada comando criado por um cliente adicionando um middleware à do cliente `HandlerList`. Você pode adicionar e remover o middleware de comandos específicos modificando a `HandlerList` de propriedade de um comando específico.

Uma `HandlerList` representa uma pilha de middleware que é usada para encapsular um **manipulador**. Para ajudar a gerenciar a lista de middleware e a ordem na qual ela encapsula um manipulador, a `HandlerList` divide a pilha de middleware em etapas nomeadas que representam parte do ciclo de vida da transferência de um comando:

1.  `init` - adicionar parâmetros padrão

1.  `validate` - validar parâmetros necessários

1.  `build` - serializar uma solicitação HTTP para envio

1.  `sign` - assinar a solicitação HTTP serializada

1. <handler> (não é uma etapa, mas executa a transferência real)

**init**  
Essa etapa do ciclo de vida representa a inicialização de um comando, e uma solicitação ainda não foi serializada. Essa etapa geralmente é usada para adicionar parâmetros padrão a um comando.  
Você pode adicionar um middleware à etapa `init` usando os métodos `appendInit` e `prependInit`, em que `appendInit` adiciona o middleware ao final da lista `prepend` enquanto `prependInit` adiciona o middleware na frente da lista `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');
```

**validar**  
Essa etapa do ciclo de vida é usada para validar os parâmetros de entrada de um comando.  
Você pode adicionar um middleware à etapa `validate` usando os métodos `appendValidate` e `prependValidate`, em que `appendValidate` adiciona o middleware ao final da lista `validate` enquanto `prependValidate` adiciona o middleware na frente da lista `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**  
Essa etapa do ciclo de vida é usada para serializar uma solicitação HTTP para o comando que está sendo executado. Os eventos downstream do ciclo de vida receberão um comando e uma solicitação HTTP do PSR-7.  
Você pode adicionar um middleware à etapa `build` usando os métodos `appendBuild` e `prependBuild`, em que `appendBuild` adiciona o middleware ao final da lista `build` enquanto `prependBuild` adiciona o middleware na frente da lista `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**  
Essa etapa do ciclo de vida normalmente é usada para assinar solicitações HTTP antes de serem enviadas pela rede. Normalmente, você deve evitar modificar uma solicitação HTTP depois que ela é assinada para evitar erros de assinatura.  
Esta é a última etapa da `HandlerList` antes da solicitação HTTP ser transferida por um manipulador.  
Você pode adicionar um middleware à etapa `sign` usando os métodos `appendSign` e `prependSign`, em que `appendSign` adiciona o middleware ao final da lista `sign` enquanto `prependSign` adiciona o middleware na frente da lista `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 disponível
<a name="available-middleware"></a>

O SDK fornece vários middleware que você pode usar para aumentar o comportamento de um cliente ou para observar a execução de um comando.

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

O middleware `Aws\Middleware::mapCommand` é útil quando você precisa modificar um comando antes que ele seja serializado como uma solicitação HTTP. Por exemplo, `mapCommand` pode ser usado para executar a validação ou adicionar parâmetros padrão. A função `mapCommand` aceita um chamável que aceita um objeto `Aws\CommandInterface` e retorna um objeto `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>

O middleware `Aws\Middleware::mapRequest` é útil quando você precisa modificar uma solicitação depois de ela ser serializada, mas antes de ela ser enviada. Por exemplo, isso pode ser usado para adicionar cabeçalhos HTTP personalizados a uma solicitação. A função `mapRequest` aceita um chamável que aceita um argumento `Psr\Http\Message\RequestInterface` e retorna um objeto `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'
);
```

Agora quando o comando for executado, ele será enviado com o cabeçalho personalizado.

**Importante**  
Observe que o middleware foi acrescentado à lista de manipuladores no final da etapa `build`. Isso é para garantir que uma solicitação tenha sido criada antes desse middleware ser invocado.

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

O middleware `Aws\Middleware::mapResult` é útil quando você precisa modificar o resultado da execução de um comando. A função `mapResult` aceita um chamável que aceita um argumento `Aws\ResultInterface` e retorna um objeto `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;
    })
);
```

Agora quando o comando é executado, o resultado retornado conterá um atributo `foo`.

#### histórico
<a name="history"></a>

O middleware `history` é útil para testar se o SDK executou os comandos esperados, enviou as solicitações HTTP esperadas e recebeu os resultados esperados. Essencialmente, é um middleware que funciona de forma semelhante ao histórico de um navegador da 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));
```

Um contêiner de histórico `Aws\History` armazena 10 entradas por padrão antes de limpar entradas. Você pode personalizar o número de entradas passando o número de entradas a serem persistidas para o construtor.

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

Você pode inspecionar o contêiner do histórico depois de executar solicitações que passam o middleware do histórico.

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

O middleware `tap` é usado como um observador. Você pode usar esse middleware para invocar funções ao enviar comandos por meio da cadeia de middleware. A função `tap` aceita um chamável que aceita a `Aws\CommandInterface` e uma `Psr\Http\Message\RequestInterface` opcional que está sendo executada.

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

## Criação de manipuladores personalizados
<a name="creating-custom-handlers"></a>

Um manipulador é simplesmente uma função que aceita um objeto `Aws\CommandInterface` e um objeto `Psr\Http\Message\RequestInterface` e retorna uma `GuzzleHttp\Promise\PromiseInterface` que é cumprida com uma `Aws\ResultInterface` ou rejeitada com uma `Aws\Exception\AwsException`.

Embora o SDK tenha várias opções `@http`, um manipulador só precisa saber como usar as seguintes opções:
+  [connect\_timeout](guide_configuration.md#http-connect-timeout) 
+  [depurar](guide_configuration.md#http-debug) 
+  [decode\_content](guide_configuration.md#http-decode-content) (opcional)
+  [delay](guide_configuration.md#http-delay) 
+  [progress](guide_configuration.md#http-progress) (opcional)
+  [Proxy](guide_configuration.md#http-proxy) 
+  [sink](guide_configuration.md#http-sink) 
+  [synchronous](guide_configuration.md#http-sync) (opcional)
+  [stream](guide_configuration.md#http-stream) (opcional)
+  [timeout](guide_configuration.md#http-timeout) 
+  [verificar](guide_configuration.md#http-verify) 
+ http\_stats\_receiver (opcional) – Uma função para invocar com uma matriz associativa de estatísticas de transferência HTTP se solicitada usando o parâmetro de configuração [stats](guide_configuration.md#config-stats).

A menos que a opção seja especificada como opcional, um manipulador DEVE poder lidar com a opção ou DEVE retornar uma promessa rejeitada.

Além de lidar com opções `@http` específicas, um manipulador DEVE adicionar um cabeçalho `User-Agent` que usa o seguinte formato, em que "3.X" pode ser substituído por `Aws\Sdk::VERSION` e "HandlerSpecificData/version..." deve ser substituído por sua sequência de agente de usuário específica ao manipulador.

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