vendor/aws/aws-sdk-php/src/Api/Serializer/RestSerializer.php line 29

Open in your IDE?
  1. <?php
  2. namespace Aws\Api\Serializer;
  3. use Aws\Api\Service;
  4. use Aws\Api\Operation;
  5. use Aws\Api\Shape;
  6. use Aws\Api\StructureShape;
  7. use Aws\Api\TimestampShape;
  8. use Aws\CommandInterface;
  9. use GuzzleHttp\Psr7;
  10. use Psr\Http\Message\RequestInterface;
  11. /**
  12.  * Serializes HTTP locations like header, uri, payload, etc...
  13.  * @internal
  14.  */
  15. abstract class RestSerializer
  16. {
  17.     /** @var Service */
  18.     private $api;
  19.     /** @var Psr7\Uri */
  20.     private $endpoint;
  21.     /**
  22.      * @param Service $api      Service API description
  23.      * @param string  $endpoint Endpoint to connect to
  24.      */
  25.     public function __construct(Service $api$endpoint)
  26.     {
  27.         $this->api $api;
  28.         $this->endpoint Psr7\uri_for($endpoint);
  29.     }
  30.     /**
  31.      * @param CommandInterface $command Command to serialized
  32.      *
  33.      * @return RequestInterface
  34.      */
  35.     public function __invoke(CommandInterface $command)
  36.     {
  37.         $operation $this->api->getOperation($command->getName());
  38.         $args $command->toArray();
  39.         $opts $this->serialize($operation$args);
  40.         $uri $this->buildEndpoint($operation$args$opts);
  41.         return new Psr7\Request(
  42.             $operation['http']['method'],
  43.             $uri,
  44.             isset($opts['headers']) ? $opts['headers'] : [],
  45.             isset($opts['body']) ? $opts['body'] : null
  46.         );
  47.     }
  48.     /**
  49.      * Modifies a hash of request options for a payload body.
  50.      *
  51.      * @param StructureShape   $member  Member to serialize
  52.      * @param array            $value   Value to serialize
  53.      * @param array            $opts    Request options to modify.
  54.      */
  55.     abstract protected function payload(
  56.         StructureShape $member,
  57.         array $value,
  58.         array &$opts
  59.     );
  60.     private function serialize(Operation $operation, array $args)
  61.     {
  62.         $opts = [];
  63.         $input $operation->getInput();
  64.         // Apply the payload trait if present
  65.         if ($payload $input['payload']) {
  66.             $this->applyPayload($input$payload$args$opts);
  67.         }
  68.         foreach ($args as $name => $value) {
  69.             if ($input->hasMember($name)) {
  70.                 $member $input->getMember($name);
  71.                 $location $member['location'];
  72.                 if (!$payload && !$location) {
  73.                     $bodyMembers[$name] = $value;
  74.                 } elseif ($location == 'header') {
  75.                     $this->applyHeader($name$member$value$opts);
  76.                 } elseif ($location == 'querystring') {
  77.                     $this->applyQuery($name$member$value$opts);
  78.                 } elseif ($location == 'headers') {
  79.                     $this->applyHeaderMap($name$member$value$opts);
  80.                 }
  81.             }
  82.         }
  83.         if (isset($bodyMembers)) {
  84.             $this->payload($operation->getInput(), $bodyMembers$opts);
  85.         }
  86.         return $opts;
  87.     }
  88.     private function applyPayload(StructureShape $input$name, array $args, array &$opts)
  89.     {
  90.         if (!isset($args[$name])) {
  91.             return;
  92.         }
  93.         $m $input->getMember($name);
  94.         if ($m['streaming'] ||
  95.            ($m['type'] == 'string' || $m['type'] == 'blob')
  96.         ) {
  97.             // Streaming bodies or payloads that are strings are
  98.             // always just a stream of data.
  99.             $opts['body'] = Psr7\stream_for($args[$name]);
  100.             return;
  101.         }
  102.         $this->payload($m$args[$name], $opts);
  103.     }
  104.     private function applyHeader($nameShape $member$value, array &$opts)
  105.     {
  106.         if ($member->getType() == 'timestamp') {
  107.             $value TimestampShape::format($value'rfc822');
  108.         }
  109.         $opts['headers'][$member['locationName'] ?: $name] = $value;
  110.     }
  111.     /**
  112.      * Note: This is currently only present in the Amazon S3 model.
  113.      */
  114.     private function applyHeaderMap($nameShape $member, array $value, array &$opts)
  115.     {
  116.         $prefix $member['locationName'];
  117.         foreach ($value as $k => $v) {
  118.             $opts['headers'][$prefix $k] = $v;
  119.         }
  120.     }
  121.     private function applyQuery($nameShape $member$value, array &$opts)
  122.     {
  123.         if ($value !== null) {
  124.             $opts['query'][$member['locationName'] ?: $name] = $value;
  125.         }
  126.     }
  127.     private function buildEndpoint(Operation $operation, array $args, array $opts)
  128.     {
  129.         $varspecs = [];
  130.         // Create an associative array of varspecs used in expansions
  131.         foreach ($operation->getInput()->getMembers() as $name => $member) {
  132.             if ($member['location'] == 'uri') {
  133.                 $varspecs[$member['locationName'] ?: $name] =
  134.                     isset($args[$name])
  135.                         ? $args[$name]
  136.                         : null;
  137.             }
  138.         }
  139.         $relative preg_replace_callback(
  140.             '/\{([^\}]+)\}/',
  141.             function (array $matches) use ($varspecs) {
  142.                 $isGreedy substr($matches[1], -11) == '+';
  143.                 $k $isGreedy substr($matches[1], 0, -1) : $matches[1];
  144.                 if (!isset($varspecs[$k])) {
  145.                     return '';
  146.                 } elseif ($isGreedy) {
  147.                     return str_replace('%2F''/'rawurlencode($varspecs[$k]));
  148.                 } else {
  149.                     return rawurlencode($varspecs[$k]);
  150.                 }
  151.             },
  152.             $operation['http']['requestUri']
  153.         );
  154.         // Add the query string variables or appending to one if needed.
  155.         if (!empty($opts['query'])) {
  156.             $append Psr7\build_query($opts['query']);
  157.             $relative .= strpos($relative'?') ? "&{$append}"?$append";
  158.         }
  159.         // Expand path place holders using Amazon's slightly different URI
  160.         // template syntax.
  161.         return Psr7\Uri::resolve($this->endpoint$relative);
  162.     }
  163. }