| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 | 
							- <?php
 
- namespace Aws\S3;
 
- use Aws\Arn\ArnParser;
 
- use Aws\Arn\ObjectLambdaAccessPointArn;
 
- use Aws\ClientResolver;
 
- use Aws\CommandInterface;
 
- use Aws\Endpoint\EndpointProvider;
 
- use Aws\Endpoint\PartitionEndpointProvider;
 
- use GuzzleHttp\Exception\InvalidArgumentException;
 
- use GuzzleHttp\Psr7\Uri;
 
- use Psr\Http\Message\RequestInterface;
 
- /**
 
-  * Used to update the URL used for S3 requests to support:
 
-  * S3 Accelerate, S3 DualStack or Both. It will build to
 
-  * host style paths unless specified, including for S3
 
-  * DualStack.
 
-  *
 
-  * IMPORTANT: this middleware must be added after the "build" step.
 
-  *
 
-  * @internal
 
-  */
 
- class S3EndpointMiddleware
 
- {
 
-     private static $exclusions = [
 
-         'CreateBucket' => true,
 
-         'DeleteBucket' => true,
 
-         'ListBuckets' => true,
 
-     ];
 
-     const NO_PATTERN = 0;
 
-     const DUALSTACK = 1;
 
-     const ACCELERATE = 2;
 
-     const ACCELERATE_DUALSTACK = 3;
 
-     const PATH_STYLE = 4;
 
-     const HOST_STYLE = 5;
 
-     /** @var bool */
 
-     private $accelerateByDefault;
 
-     /** @var bool */
 
-     private $dualStackByDefault;
 
-     /** @var bool */
 
-     private $pathStyleByDefault;
 
-     /** @var string */
 
-     private $region;
 
-     /** @var callable */
 
-     private $endpointProvider;
 
-     /** @var callable */
 
-     private $nextHandler;
 
-     /** @var string */
 
-     private $endpoint;
 
-     /**
 
-      * Create a middleware wrapper function
 
-      *
 
-      * @param string $region
 
-      * @param EndpointProvider $endpointProvider
 
-      * @param array  $options
 
-      *
 
-      * @return callable
 
-      */
 
-     public static function wrap($region, $endpointProvider, array $options)
 
-     {
 
-         return function (callable $handler) use ($region, $endpointProvider, $options) {
 
-             return new self($handler, $region, $options, $endpointProvider);
 
-         };
 
-     }
 
-     public function __construct(
 
-         callable $nextHandler,
 
-         $region,
 
-         array $options,
 
-         $endpointProvider = null
 
-     ) {
 
-         $this->pathStyleByDefault = isset($options['path_style'])
 
-             ? (bool) $options['path_style'] : false;
 
-         $this->dualStackByDefault = isset($options['dual_stack'])
 
-             ? (bool) $options['dual_stack'] : false;
 
-         $this->accelerateByDefault = isset($options['accelerate'])
 
-             ? (bool) $options['accelerate'] : false;
 
-         $this->region = (string) $region;
 
-         $this->endpoint = isset($options['endpoint'])
 
-             ? $options['endpoint'] : "";
 
-         $this->endpointProvider = is_null($endpointProvider)
 
-             ? PartitionEndpointProvider::defaultProvider()
 
-             : $endpointProvider;
 
-         $this->nextHandler = $nextHandler;
 
-     }
 
-     public function __invoke(CommandInterface $command, RequestInterface $request)
 
-     {
 
-         if (!empty($this->endpoint)) {
 
-             $request = $this->applyEndpoint($command, $request);
 
-         } else {
 
-             switch ($this->endpointPatternDecider($command, $request)) {
 
-                 case self::HOST_STYLE:
 
-                     $request = $this->applyHostStyleEndpoint($command, $request);
 
-                     break;
 
-                 case self::NO_PATTERN:
 
-                     break;
 
-                 case self::PATH_STYLE:
 
-                     $request = $this->applyPathStyleEndpointCustomizations($command, $request);
 
-                     break;
 
-                 case self::DUALSTACK:
 
-                     $request = $this->applyDualStackEndpoint($command, $request);
 
-                     break;
 
-                 case self::ACCELERATE:
 
-                     $request = $this->applyAccelerateEndpoint(
 
-                         $command,
 
-                         $request,
 
-                         's3-accelerate'
 
-                     );
 
-                     break;
 
-                 case self::ACCELERATE_DUALSTACK:
 
-                     $request = $this->applyAccelerateEndpoint(
 
-                         $command,
 
-                         $request,
 
-                         's3-accelerate.dualstack'
 
-                     );
 
-                     break;
 
-             }
 
-         }
 
-         $nextHandler = $this->nextHandler;
 
-         return $nextHandler($command, $request);
 
-     }
 
-     private static function isRequestHostStyleCompatible(
 
-         CommandInterface $command,
 
-         RequestInterface $request
 
-     ) {
 
-         return S3Client::isBucketDnsCompatible($command['Bucket'])
 
-             && (
 
-                 $request->getUri()->getScheme() === 'http'
 
-                 || strpos($command['Bucket'], '.') === false
 
-             )
 
-             && filter_var($request->getUri()->getHost(), FILTER_VALIDATE_IP) === false;
 
-     }
 
-     private function endpointPatternDecider(
 
-         CommandInterface $command,
 
-         RequestInterface $request
 
-     ) {
 
-         $accelerate = isset($command['@use_accelerate_endpoint'])
 
-             ? $command['@use_accelerate_endpoint'] : $this->accelerateByDefault;
 
-         $dualStack = isset($command['@use_dual_stack_endpoint'])
 
-             ? $command['@use_dual_stack_endpoint'] : $this->dualStackByDefault;
 
-         $pathStyle = isset($command['@use_path_style_endpoint'])
 
-             ? $command['@use_path_style_endpoint'] : $this->pathStyleByDefault;
 
-         if ($accelerate && $dualStack) {
 
-             // When try to enable both for operations excluded from s3-accelerate,
 
-             // only dualstack endpoints will be enabled.
 
-             return $this->canAccelerate($command)
 
-                 ? self::ACCELERATE_DUALSTACK
 
-                 : self::DUALSTACK;
 
-         }
 
-         if ($accelerate && $this->canAccelerate($command)) {
 
-             return self::ACCELERATE;
 
-         }
 
-         if ($dualStack) {
 
-             return self::DUALSTACK;
 
-         }
 
-         if (!$pathStyle
 
-             && self::isRequestHostStyleCompatible($command, $request)
 
-         ) {
 
-             return self::HOST_STYLE;
 
-         }
 
-         return self::PATH_STYLE;
 
-     }
 
-     private function canAccelerate(CommandInterface $command)
 
-     {
 
-         return empty(self::$exclusions[$command->getName()])
 
-             && S3Client::isBucketDnsCompatible($command['Bucket']);
 
-     }
 
-     private function getBucketStyleHost(CommandInterface $command, $host)
 
-     {
 
-         // For operations on the base host (e.g. ListBuckets)
 
-         if (!isset($command['Bucket'])) {
 
-             return $host;
 
-         }
 
-         return "{$command['Bucket']}.{$host}";
 
-     }
 
-     private function applyHostStyleEndpoint(
 
-         CommandInterface $command,
 
-         RequestInterface $request
 
-     ) {
 
-         $uri = $request->getUri();
 
-         $request = $request->withUri(
 
-             $uri->withHost($this->getBucketStyleHost(
 
-                     $command,
 
-                     $uri->getHost()
 
-                 ))
 
-                 ->withPath($this->getBucketlessPath(
 
-                     $uri->getPath(),
 
-                     $command
 
-                 ))
 
-         );
 
-         return $request;
 
-     }
 
-     private function applyPathStyleEndpointCustomizations(
 
-         CommandInterface $command,
 
-         RequestInterface $request
 
-     ) {
 
-         if ($command->getName() == 'WriteGetObjectResponse') {
 
-             $dnsSuffix = $this->endpointProvider
 
-                 ->getPartition($this->region, 's3')
 
-                 ->getDnsSuffix();
 
-             $fips = \Aws\is_fips_pseudo_region($this->region) ? "-fips" : "";
 
-             $region = \Aws\strip_fips_pseudo_regions($this->region);
 
-             $host =
 
-                 "{$command['RequestRoute']}.s3-object-lambda{$fips}.{$region}.{$dnsSuffix}";
 
-             $uri = $request->getUri();
 
-             $request = $request->withUri(
 
-                 $uri->withHost($host)
 
-                     ->withPath($this->getBucketlessPath(
 
-                         $uri->getPath(),
 
-                         $command
 
-                     ))
 
-             );
 
-         }
 
-         return $request;
 
-     }
 
-     private function applyDualStackEndpoint(
 
-         CommandInterface $command,
 
-         RequestInterface $request
 
-     ) {
 
-         $request = $request->withUri(
 
-             $request->getUri()->withHost($this->getDualStackHost())
 
-         );
 
-         if (empty($command['@use_path_style_endpoint'])
 
-             && !$this->pathStyleByDefault
 
-             && self::isRequestHostStyleCompatible($command, $request)
 
-         ) {
 
-             $request = $this->applyHostStyleEndpoint($command, $request);
 
-         }
 
-         return $request;
 
-     }
 
-     private function getDualStackHost()
 
-     {
 
-         $dnsSuffix = $this->endpointProvider
 
-             ->getPartition($this->region, 's3')
 
-             ->getDnsSuffix();
 
-         return "s3.dualstack.{$this->region}.{$dnsSuffix}";
 
-     }
 
-     private function applyAccelerateEndpoint(
 
-         CommandInterface $command,
 
-         RequestInterface $request,
 
-         $pattern
 
-     ) {
 
-         $request = $request->withUri(
 
-             $request->getUri()
 
-                 ->withHost($this->getAccelerateHost($command, $pattern))
 
-                 ->withPath($this->getBucketlessPath(
 
-                     $request->getUri()->getPath(),
 
-                     $command
 
-                 ))
 
-         );
 
-         return $request;
 
-     }
 
-     private function getAccelerateHost(CommandInterface $command, $pattern)
 
-     {
 
-         $dnsSuffix = $this->endpointProvider
 
-             ->getPartition($this->region, 's3')
 
-             ->getDnsSuffix();
 
-         return "{$command['Bucket']}.{$pattern}.{$dnsSuffix}";
 
-     }
 
-     private function getBucketlessPath($path, CommandInterface $command)
 
-     {
 
-         $pattern = '/^\\/' . preg_quote($command['Bucket'], '/') . '/';
 
-         $path = preg_replace($pattern, '', $path) ?: '/';
 
-         if (substr($path, 0 , 1) !== '/') {
 
-             $path = '/' . $path;
 
-         }
 
-         return $path;
 
-     }
 
-     private function applyEndpoint(
 
-         CommandInterface $command,
 
-         RequestInterface $request
 
-     ) {
 
-         $dualStack = isset($command['@use_dual_stack_endpoint'])
 
-             ? $command['@use_dual_stack_endpoint'] : $this->dualStackByDefault;
 
-         if (ArnParser::isArn($command['Bucket'])) {
 
-             $arn = ArnParser::parse($command['Bucket']);
 
-             $outpost = $arn->getService() == 's3-outposts';
 
-             if ($outpost && $dualStack) {
 
-                 throw new InvalidArgumentException("Outposts + dualstack is not supported");
 
-             }
 
-             if ($arn instanceof ObjectLambdaAccessPointArn) {
 
-                 return $request;
 
-             }
 
-         }
 
-         if ($dualStack) {
 
-             throw new InvalidArgumentException("Custom Endpoint + Dualstack not supported");
 
-         }
 
-         if ($command->getName() == 'WriteGetObjectResponse') {
 
-             $host = "{$command['RequestRoute']}.{$this->endpoint}";
 
-             $uri = $request->getUri();
 
-             return $request = $request->withUri(
 
-                 $uri->withHost($host)
 
-                     ->withPath($this->getBucketlessPath(
 
-                         $uri->getPath(),
 
-                         $command
 
-                     ))
 
-             );
 
-         }
 
-         $host = ($this->pathStyleByDefault) ?
 
-             $this->endpoint :
 
-             $this->getBucketStyleHost(
 
-                 $command,
 
-                 $this->endpoint
 
-             );
 
-         $uri = $request->getUri();
 
-         $scheme = $uri->getScheme();
 
-         if(empty($scheme)){
 
-             $request = $request->withUri(
 
-                 $uri->withHost($host)
 
-             );
 
-         } else {
 
-             $request = $request->withUri($uri);
 
-         }
 
-         return $request;
 
-     }
 
- }
 
 
  |