vendor/aws/aws-sdk-php/src/WrappedHttpHandler.php line 196

Open in your IDE?
  1. <?php
  2. namespace Aws;
  3. use Aws\Api\Parser\Exception\ParserException;
  4. use Aws\Exception\AwsException;
  5. use GuzzleHttp\Promise;
  6. use Psr\Http\Message\RequestInterface;
  7. use Psr\Http\Message\ResponseInterface;
  8. /**
  9.  * Converts an HTTP handler into a Command HTTP handler.
  10.  *
  11.  * HTTP handlers have the following signature:
  12.  *     function(RequestInterface $request, array $options) : PromiseInterface
  13.  *
  14.  * The promise returned form an HTTP handler must resolve to a PSR-7 response
  15.  * object when fulfilled or an error array when rejected. The error array
  16.  * can contain the following data:
  17.  *
  18.  * - exception: (required, Exception) Exception that was encountered.
  19.  * - response: (ResponseInterface) PSR-7 response that was received (if a
  20.  *   response) was received.
  21.  * - connection_error: (bool) True if the error is the result of failing to
  22.  *   connect.
  23.  */
  24. class WrappedHttpHandler
  25. {
  26.     private $httpHandler;
  27.     private $parser;
  28.     private $errorParser;
  29.     private $exceptionClass;
  30.     private $collectStats;
  31.     /**
  32.      * @param callable $httpHandler    Function that accepts a request and array
  33.      *                                 of request options and returns a promise
  34.      *                                 that fulfills with a response or rejects
  35.      *                                 with an error array.
  36.      * @param callable $parser         Function that accepts a response object
  37.      *                                 and returns an AWS result object.
  38.      * @param callable $errorParser    Function that parses a response object
  39.      *                                 into AWS error data.
  40.      * @param string   $exceptionClass Exception class to throw.
  41.      * @param bool     $collectStats   Whether to collect HTTP transfer
  42.      *                                 information.
  43.      */
  44.     public function __construct(
  45.         callable $httpHandler,
  46.         callable $parser,
  47.         callable $errorParser,
  48.         $exceptionClass AwsException::class,
  49.         $collectStats false
  50.     ) {
  51.         $this->httpHandler $httpHandler;
  52.         $this->parser $parser;
  53.         $this->errorParser $errorParser;
  54.         $this->exceptionClass $exceptionClass;
  55.         $this->collectStats $collectStats;
  56.     }
  57.     /**
  58.      * Calls the simpler HTTP specific handler and wraps the returned promise
  59.      * with AWS specific values (e.g., a result object or AWS exception).
  60.      *
  61.      * @param CommandInterface $command Command being executed.
  62.      * @param RequestInterface $request Request to send.
  63.      *
  64.      * @return Promise\PromiseInterface
  65.      */
  66.     public function __invoke(
  67.         CommandInterface $command,
  68.         RequestInterface $request
  69.     ) {
  70.         $fn $this->httpHandler;
  71.         $options $command['@http'] ?: [];
  72.         $stats = [];
  73.         if ($this->collectStats || !empty($options['collect_stats'])) {
  74.             $options['http_stats_receiver'] = static function (
  75.                 array $transferStats
  76.             ) use (&$stats) {
  77.                 $stats $transferStats;
  78.             };
  79.         } elseif (isset($options['http_stats_receiver'])) {
  80.             throw new \InvalidArgumentException('Providing a custom HTTP stats'
  81.                 ' receiver to Aws\WrappedHttpHandler is not supported.');
  82.         }
  83.         return Promise\Create::promiseFor($fn($request$options))
  84.             ->then(
  85.                 function (
  86.                     ResponseInterface $res
  87.                 ) use ($command$request, &$stats) {
  88.                     return $this->parseResponse($command$request$res$stats);
  89.                 },
  90.                 function ($err) use ($request$command, &$stats) {
  91.                     if (is_array($err)) {
  92.                         $err $this->parseError(
  93.                             $err,
  94.                             $request,
  95.                             $command,
  96.                             $stats
  97.                         );
  98.                     }
  99.                     return new Promise\RejectedPromise($err);
  100.                 }
  101.             );
  102.     }
  103.     /**
  104.      * @param CommandInterface  $command
  105.      * @param RequestInterface  $request
  106.      * @param ResponseInterface $response
  107.      * @param array             $stats
  108.      *
  109.      * @return ResultInterface
  110.      */
  111.     private function parseResponse(
  112.         CommandInterface $command,
  113.         RequestInterface $request,
  114.         ResponseInterface $response,
  115.         array $stats
  116.     ) {
  117.         $parser $this->parser;
  118.         $status $response->getStatusCode();
  119.         $result $status 300
  120.             $parser($command$response)
  121.             : new Result();
  122.         $metadata = [
  123.             'statusCode'    => $status,
  124.             'effectiveUri'  => (string) $request->getUri(),
  125.             'headers'       => [],
  126.             'transferStats' => [],
  127.         ];
  128.         if (!empty($stats)) {
  129.             $metadata['transferStats']['http'] = [$stats];
  130.         }
  131.         // Bring headers into the metadata array.
  132.         foreach ($response->getHeaders() as $name => $values) {
  133.             $metadata['headers'][strtolower($name)] = $values[0];
  134.         }
  135.         $result['@metadata'] = $metadata;
  136.         return $result;
  137.     }
  138.     /**
  139.      * Parses a rejection into an AWS error.
  140.      *
  141.      * @param array            $err     Rejection error array.
  142.      * @param RequestInterface $request Request that was sent.
  143.      * @param CommandInterface $command Command being sent.
  144.      * @param array            $stats   Transfer statistics
  145.      *
  146.      * @return \Exception
  147.      */
  148.     private function parseError(
  149.         array $err,
  150.         RequestInterface $request,
  151.         CommandInterface $command,
  152.         array $stats
  153.     ) {
  154.         if (!isset($err['exception'])) {
  155.             throw new \RuntimeException('The HTTP handler was rejected without an "exception" key value pair.');
  156.         }
  157.         $serviceError "AWS HTTP error: " $err['exception']->getMessage();
  158.         if (!isset($err['response'])) {
  159.             $parts = ['response' => null];
  160.         } else {
  161.             try {
  162.                 $parts call_user_func(
  163.                     $this->errorParser,
  164.                     $err['response'],
  165.                     $command
  166.                 );
  167.                 $serviceError .= {$parts['code']} ({$parts['type']}): "
  168.                     "{$parts['message']} - " $err['response']->getBody();
  169.             } catch (ParserException $e) {
  170.                 $parts = [];
  171.                 $serviceError .= ' Unable to parse error information from '
  172.                     "response - {$e->getMessage()}";
  173.             }
  174.             $parts['response'] = $err['response'];
  175.         }
  176.         $parts['exception'] = $err['exception'];
  177.         $parts['request'] = $request;
  178.         $parts['connection_error'] = !empty($err['connection_error']);
  179.         $parts['transfer_stats'] = $stats;
  180.         return new $this->exceptionClass(
  181.             sprintf(
  182.                 'Error executing "%s" on "%s"; %s',
  183.                 $command->getName(),
  184.                 $request->getUri(),
  185.                 $serviceError
  186.             ),
  187.             $command,
  188.             $parts,
  189.             $err['exception']
  190.         );
  191.     }
  192. }