← All changes
|
includes/sdk/s3/Aws/S3/BucketEndpointMiddleware.php
+34
-47
1.2.13
→
1.4.2
View file →
| @@ -2,8 +2,9 @@ | ||
| 2 | 2 | |
| 3 | 3 | namespace Dudlewebs\WPMCS\s3\Aws\S3; |
| 4 | 4 | |
| 5 | 5 | use Dudlewebs\WPMCS\s3\Aws\CommandInterface; |
| 6 | +use Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7\Uri; | |
| 6 | 7 | use Dudlewebs\WPMCS\s3\Psr\Http\Message\RequestInterface; |
| 7 | 8 | /** |
| 8 | 9 | * Used to update the host used for S3 requests in the case of using a |
| 9 | 10 | * "bucket endpoint" or CNAME bucket. |
| @@ -15,22 +16,29 @@ | ||
| 15 | 16 | class BucketEndpointMiddleware |
| 16 | 17 | { |
| 17 | 18 | private static $exclusions = ['GetBucketLocation' => \true]; |
| 18 | 19 | private $nextHandler; |
| 20 | + private bool $useEndpointV2; | |
| 21 | + private ?string $endpoint; | |
| 19 | 22 | /** |
| 20 | 23 | * Create a middleware wrapper function. |
| 21 | 24 | * |
| 25 | + * @param bool $useEndpointV2 | |
| 26 | + * @param string|null $endpoint | |
| 27 | + * | |
| 22 | 28 | * @return callable |
| 23 | 29 | */ |
| 24 | - public static function wrap() | |
| 30 | + public static function wrap(bool $useEndpointV2 = \false, ?string $endpoint = null) : callable | |
| 25 | 31 | { |
| 26 | - return function (callable $handler) { | |
| 27 | - return new self($handler); | |
| 32 | + return function (callable $handler) use($useEndpointV2, $endpoint) { | |
| 33 | + return new self($handler, $useEndpointV2, $endpoint); | |
| 28 | 34 | }; |
| 29 | 35 | } |
| 30 | - public function __construct(callable $nextHandler) | |
| 36 | + public function __construct(callable $nextHandler, bool $useEndpointV2, ?string $endpoint = null) | |
| 31 | 37 | { |
| 32 | 38 | $this->nextHandler = $nextHandler; |
| 39 | + $this->useEndpointV2 = $useEndpointV2; | |
| 40 | + $this->endpoint = $endpoint; | |
| 33 | 41 | } |
| 34 | 42 | public function __invoke(CommandInterface $command, RequestInterface $request) |
| 35 | 43 | { |
| 36 | 44 | $nextHandler = $this->nextHandler; |
| @@ -40,63 +48,42 @@ | ||
| 40 | 48 | } |
| 41 | 49 | return $nextHandler($command, $request); |
| 42 | 50 | } |
| 43 | 51 | /** |
| 44 | - * Performs a one-time removal of Bucket from path, then if | |
| 45 | - * the bucket name is duplicated in the path, performs additional | |
| 46 | - * removal which is dependent on the number of occurrences of the bucket | |
| 47 | - * name in a path-like format in the key name. | |
| 52 | + * @param string $path | |
| 53 | + * @param string $bucket | |
| 48 | 54 | * |
| 49 | 55 | * @return string |
| 50 | 56 | */ |
| 51 | - private function removeBucketFromPath($path, $bucket, $key) | |
| 57 | + private function removeBucketFromPath(string $path, string $bucket) : string | |
| 52 | 58 | { |
| 53 | - $occurrencesInKey = $this->getBucketNameOccurrencesInKey($key, $bucket); | |
| 54 | - do { | |
| 55 | - $len = \strlen($bucket) + 1; | |
| 56 | - if (\substr($path, 0, $len) === "/{$bucket}") { | |
| 57 | - $path = \substr($path, $len); | |
| 58 | - } | |
| 59 | - } while (\substr_count($path, "/{$bucket}") > $occurrencesInKey + 1); | |
| 59 | + $len = \strlen($bucket) + 1; | |
| 60 | + if (\str_starts_with($path, "/{$bucket}")) { | |
| 61 | + $path = \substr($path, $len); | |
| 62 | + } | |
| 60 | 63 | return $path ?: '/'; |
| 61 | 64 | } |
| 62 | - private function removeDuplicateBucketFromHost($host, $bucket) | |
| 65 | + /** | |
| 66 | + * @param RequestInterface $request | |
| 67 | + * @param CommandInterface $command | |
| 68 | + * | |
| 69 | + * @return RequestInterface | |
| 70 | + */ | |
| 71 | + private function modifyRequest(RequestInterface $request, CommandInterface $command) : RequestInterface | |
| 63 | 72 | { |
| 64 | - if (\substr_count($host, $bucket) > 1) { | |
| 65 | - while (\strpos($host, "{$bucket}.{$bucket}") === 0) { | |
| 66 | - $hostArr = \explode('.', $host); | |
| 67 | - \array_shift($hostArr); | |
| 68 | - $host = \implode('.', $hostArr); | |
| 69 | - } | |
| 70 | - } | |
| 71 | - return $host; | |
| 72 | - } | |
| 73 | - private function getBucketNameOccurrencesInKey($key, $bucket) | |
| 74 | - { | |
| 75 | - $occurrences = 0; | |
| 76 | - if (empty($key)) { | |
| 77 | - return $occurrences; | |
| 78 | - } | |
| 79 | - $segments = \explode('/', $key); | |
| 80 | - foreach ($segments as $segment) { | |
| 81 | - if (\strpos($segment, $bucket) === 0) { | |
| 82 | - $occurrences++; | |
| 83 | - } | |
| 84 | - } | |
| 85 | - return $occurrences; | |
| 86 | - } | |
| 87 | - private function modifyRequest(RequestInterface $request, CommandInterface $command) | |
| 88 | - { | |
| 89 | - $key = isset($command['Key']) ? $command['Key'] : null; | |
| 90 | 73 | $uri = $request->getUri(); |
| 91 | 74 | $path = $uri->getPath(); |
| 92 | 75 | $host = $uri->getHost(); |
| 93 | 76 | $bucket = $command['Bucket']; |
| 94 | - $path = $this->removeBucketFromPath($path, $bucket, $key); | |
| 95 | - $host = $this->removeDuplicateBucketFromHost($host, $bucket); | |
| 77 | + if ($this->useEndpointV2 && !empty($this->endpoint)) { | |
| 78 | + // V2 provider adds bucket name to host by default | |
| 79 | + // preserve original host | |
| 80 | + $host = (new Uri($this->endpoint))->getHost(); | |
| 81 | + } | |
| 82 | + $path = $this->removeBucketFromPath($path, $bucket); | |
| 96 | 83 | // Modify the Key to make sure the key is encoded, but slashes are not. |
| 97 | - if ($key) { | |
| 84 | + if ($command['Key']) { | |
| 98 | 85 | $path = S3Client::encodeKey(\rawurldecode($path)); |
| 99 | 86 | } |
| 100 | - return $request->withUri($uri->withHost($host)->withPath($path)); | |
| 87 | + return $request->withUri($uri->withPath($path)->withHost($host)); | |
| 101 | 88 | } |
| 102 | 89 | } |