| @@ -40,8 +40,12 @@ | ||
| 40 | 40 | * @method \Aws\Result copyObject(array $args = []) |
| 41 | 41 | * @method \GuzzleHttp\Promise\Promise copyObjectAsync(array $args = []) |
| 42 | 42 | * @method \Aws\Result createBucket(array $args = []) |
| 43 | 43 | * @method \GuzzleHttp\Promise\Promise createBucketAsync(array $args = []) |
| 44 | + * @method \Aws\Result createBucketMetadataConfiguration(array $args = []) | |
| 45 | + * @method \GuzzleHttp\Promise\Promise createBucketMetadataConfigurationAsync(array $args = []) | |
| 46 | + * @method \Aws\Result createBucketMetadataTableConfiguration(array $args = []) | |
| 47 | + * @method \GuzzleHttp\Promise\Promise createBucketMetadataTableConfigurationAsync(array $args = []) | |
| 44 | 48 | * @method \Aws\Result createMultipartUpload(array $args = []) |
| 45 | 49 | * @method \GuzzleHttp\Promise\Promise createMultipartUploadAsync(array $args = []) |
| 46 | 50 | * @method \Aws\Result createSession(array $args = []) |
| 47 | 51 | * @method \GuzzleHttp\Promise\Promise createSessionAsync(array $args = []) |
| @@ -58,8 +62,12 @@ | ||
| 58 | 62 | * @method \Aws\Result deleteBucketInventoryConfiguration(array $args = []) |
| 59 | 63 | * @method \GuzzleHttp\Promise\Promise deleteBucketInventoryConfigurationAsync(array $args = []) |
| 60 | 64 | * @method \Aws\Result deleteBucketLifecycle(array $args = []) |
| 61 | 65 | * @method \GuzzleHttp\Promise\Promise deleteBucketLifecycleAsync(array $args = []) |
| 66 | + * @method \Aws\Result deleteBucketMetadataConfiguration(array $args = []) | |
| 67 | + * @method \GuzzleHttp\Promise\Promise deleteBucketMetadataConfigurationAsync(array $args = []) | |
| 68 | + * @method \Aws\Result deleteBucketMetadataTableConfiguration(array $args = []) | |
| 69 | + * @method \GuzzleHttp\Promise\Promise deleteBucketMetadataTableConfigurationAsync(array $args = []) | |
| 62 | 70 | * @method \Aws\Result deleteBucketMetricsConfiguration(array $args = []) |
| 63 | 71 | * @method \GuzzleHttp\Promise\Promise deleteBucketMetricsConfigurationAsync(array $args = []) |
| 64 | 72 | * @method \Aws\Result deleteBucketOwnershipControls(array $args = []) |
| 65 | 73 | * @method \GuzzleHttp\Promise\Promise deleteBucketOwnershipControlsAsync(array $args = []) |
| @@ -100,8 +108,12 @@ | ||
| 100 | 108 | * @method \Aws\Result getBucketLocation(array $args = []) |
| 101 | 109 | * @method \GuzzleHttp\Promise\Promise getBucketLocationAsync(array $args = []) |
| 102 | 110 | * @method \Aws\Result getBucketLogging(array $args = []) |
| 103 | 111 | * @method \GuzzleHttp\Promise\Promise getBucketLoggingAsync(array $args = []) |
| 112 | + * @method \Aws\Result getBucketMetadataConfiguration(array $args = []) | |
| 113 | + * @method \GuzzleHttp\Promise\Promise getBucketMetadataConfigurationAsync(array $args = []) | |
| 114 | + * @method \Aws\Result getBucketMetadataTableConfiguration(array $args = []) | |
| 115 | + * @method \GuzzleHttp\Promise\Promise getBucketMetadataTableConfigurationAsync(array $args = []) | |
| 104 | 116 | * @method \Aws\Result getBucketMetricsConfiguration(array $args = []) |
| 105 | 117 | * @method \GuzzleHttp\Promise\Promise getBucketMetricsConfigurationAsync(array $args = []) |
| 106 | 118 | * @method \Aws\Result getBucketNotification(array $args = []) |
| 107 | 119 | * @method \GuzzleHttp\Promise\Promise getBucketNotificationAsync(array $args = []) |
| @@ -220,12 +232,18 @@ | ||
| 220 | 232 | * @method \Aws\Result putObjectTagging(array $args = []) |
| 221 | 233 | * @method \GuzzleHttp\Promise\Promise putObjectTaggingAsync(array $args = []) |
| 222 | 234 | * @method \Aws\Result putPublicAccessBlock(array $args = []) |
| 223 | 235 | * @method \GuzzleHttp\Promise\Promise putPublicAccessBlockAsync(array $args = []) |
| 236 | + * @method \Aws\Result renameObject(array $args = []) | |
| 237 | + * @method \GuzzleHttp\Promise\Promise renameObjectAsync(array $args = []) | |
| 224 | 238 | * @method \Aws\Result restoreObject(array $args = []) |
| 225 | 239 | * @method \GuzzleHttp\Promise\Promise restoreObjectAsync(array $args = []) |
| 226 | 240 | * @method \Aws\Result selectObjectContent(array $args = []) |
| 227 | 241 | * @method \GuzzleHttp\Promise\Promise selectObjectContentAsync(array $args = []) |
| 242 | + * @method \Aws\Result updateBucketMetadataInventoryTableConfiguration(array $args = []) | |
| 243 | + * @method \GuzzleHttp\Promise\Promise updateBucketMetadataInventoryTableConfigurationAsync(array $args = []) | |
| 244 | + * @method \Aws\Result updateBucketMetadataJournalTableConfiguration(array $args = []) | |
| 245 | + * @method \GuzzleHttp\Promise\Promise updateBucketMetadataJournalTableConfigurationAsync(array $args = []) | |
| 228 | 246 | * @method \Aws\Result uploadPart(array $args = []) |
| 229 | 247 | * @method \GuzzleHttp\Promise\Promise uploadPartAsync(array $args = []) |
| 230 | 248 | * @method \Aws\Result uploadPartCopy(array $args = []) |
| 231 | 249 | * @method \GuzzleHttp\Promise\Promise uploadPartCopyAsync(array $args = []) |
| @@ -233,17 +251,20 @@ | ||
| 233 | 251 | * @method \GuzzleHttp\Promise\Promise writeGetObjectResponseAsync(array $args = []) |
| 234 | 252 | */ |
| 235 | 253 | class S3Client extends AwsClient implements S3ClientInterface |
| 236 | 254 | { |
| 255 | + private const DIRECTORY_BUCKET_REGEX = '/^[a-zA-Z0-9_-]+--[a-z0-9]+-az\\d+--x-s3' . '(?!.*(?:-s3alias|--ol-s3|\\.mrap))$/'; | |
| 237 | 256 | use S3ClientTrait; |
| 238 | 257 | /** @var array */ |
| 239 | 258 | private static $mandatoryAttributes = ['Bucket', 'Key']; |
| 259 | + /** @var array */ | |
| 260 | + private static $checksumOptionEnum = ['when_supported' => \true, 'when_required' => \true]; | |
| 240 | 261 | public static function getArguments() |
| 241 | 262 | { |
| 242 | 263 | $args = parent::getArguments(); |
| 243 | 264 | $args['retries']['fn'] = [__CLASS__, '_applyRetryConfig']; |
| 244 | 265 | $args['api_provider']['fn'] = [__CLASS__, '_applyApiProvider']; |
| 245 | - return $args + ['bucket_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to a hardcoded ' . 'bucket endpoint rather than create an endpoint as a ' . 'result of injecting the bucket into the URL. This ' . 'option is useful for interacting with CNAME endpoints.'], 'use_arn_region' => ['type' => 'config', 'valid' => ['bool', Configuration::class, CacheInterface::class, 'callable'], 'doc' => 'Set to true to allow passed in ARNs to override' . ' client region. Accepts...', 'fn' => [__CLASS__, '_apply_use_arn_region'], 'default' => [UseArnRegionConfigurationProvider::class, 'defaultProvider']], 'use_accelerate_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Accelerate' . ' endpoint by default. Can be enabled or disabled on' . ' individual operations by setting' . ' \'@use_accelerate_endpoint\' to true or false. Note:' . ' you must enable S3 Accelerate on a bucket before it can' . ' be accessed via an Accelerate endpoint.', 'default' => \false], 'use_path_style_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 path style' . ' endpoint by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_path_style_endpoint\' to true or false.', 'default' => \false], 'disable_multiregion_access_points' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to disable the usage of' . ' multi region access points. These are enabled by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@disable_multiregion_access_points\' to true or false.', 'default' => \false], 'disable_express_session_auth' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to disable the usage of' . ' s3 express session authentication. This is enabled by default.', 'default' => [__CLASS__, '_default_disable_express_session_auth']], 's3_express_identity_provider' => ['type' => 'config', 'valid' => ['bool', 'callable'], 'doc' => 'Specifies the provider used to generate identities to sign s3 express requests. ' . 'Set to `false` to disable s3 express auth, or a callable provider used to create s3 express ' . 'identities or return null.', 'default' => [__CLASS__, '_default_s3_express_identity_provider']]]; | |
| 266 | + return ['request_checksum_calculation' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'Valid values are `when_supported` and `when_required`. Default is `when_supported`.' . ' `when_supported` results in checksum calculation when an operation has modeled checksum support.' . ' `when_required` results in checksum calculation when an operation has modeled checksum support and' . ' request checksums are modeled as required.', 'fn' => [__CLASS__, '_apply_request_checksum_calculation'], 'default' => [__CLASS__, '_default_request_checksum_calculation']], 'response_checksum_validation' => ['type' => 'config', 'valid' => ['string'], 'doc' => 'Valid values are `when_supported` and `when_required`. Default is `when_supported`.' . ' `when_supported` results in checksum validation when an operation has modeled checksum support.' . ' `when_required` results in checksum validation when an operation has modeled checksum support and' . ' `CheckSumMode` is set to `enabled`.', 'fn' => [__CLASS__, '_apply_response_checksum_validation'], 'default' => [__CLASS__, '_default_response_checksum_validation']]] + $args + ['bucket_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to a hardcoded ' . 'bucket endpoint rather than create an endpoint as a ' . 'result of injecting the bucket into the URL. This ' . 'option is useful for interacting with CNAME endpoints.'], 'use_arn_region' => ['type' => 'config', 'valid' => ['bool', Configuration::class, CacheInterface::class, 'callable'], 'doc' => 'Set to true to allow passed in ARNs to override' . ' client region. Accepts...', 'fn' => [__CLASS__, '_apply_use_arn_region'], 'default' => [UseArnRegionConfigurationProvider::class, 'defaultProvider']], 'use_accelerate_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 Accelerate' . ' endpoint by default. Can be enabled or disabled on' . ' individual operations by setting' . ' \'@use_accelerate_endpoint\' to true or false. Note:' . ' you must enable S3 Accelerate on a bucket before it can' . ' be accessed via an Accelerate endpoint.', 'default' => \false], 'use_path_style_endpoint' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to send requests to an S3 path style' . ' endpoint by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@use_path_style_endpoint\' to true or false.', 'default' => \false], 'disable_multiregion_access_points' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to disable the usage of' . ' multi region access points. These are enabled by default.' . ' Can be enabled or disabled on individual operations by setting' . ' \'@disable_multiregion_access_points\' to true or false.', 'default' => \false], 'disable_express_session_auth' => ['type' => 'config', 'valid' => ['bool'], 'doc' => 'Set to true to disable the usage of' . ' s3 express session authentication. This is enabled by default.', 'default' => [__CLASS__, '_default_disable_express_session_auth']], 's3_express_identity_provider' => ['type' => 'config', 'valid' => ['bool', 'callable'], 'doc' => 'Specifies the provider used to generate identities to sign s3 express requests. ' . 'Set to `false` to disable s3 express auth, or a callable provider used to create s3 express ' . 'identities or return null.', 'default' => [__CLASS__, '_default_s3_express_identity_provider']]]; | |
| 246 | 267 | } |
| 247 | 268 | /** |
| 248 | 269 | * {@inheritdoc} |
| 249 | 270 | * |
| @@ -306,13 +327,14 @@ | ||
| 306 | 327 | } |
| 307 | 328 | $this->addBuiltIns($args); |
| 308 | 329 | parent::__construct($args); |
| 309 | 330 | $stack = $this->getHandlerList(); |
| 331 | + $config = $this->getConfig(); | |
| 310 | 332 | $stack->appendInit(SSECMiddleware::wrap($this->getEndpoint()->getScheme()), 's3.ssec'); |
| 311 | - $stack->appendBuild(ApplyChecksumMiddleware::wrap($this->getApi()), 's3.checksum'); | |
| 333 | + $stack->appendBuild(ApplyChecksumMiddleware::wrap($this->getApi(), $this->getConfig()), 's3.checksum'); | |
| 312 | 334 | $stack->appendBuild(Middleware::contentType(['PutObject', 'UploadPart']), 's3.content_type'); |
| 313 | 335 | if ($this->getConfig('bucket_endpoint')) { |
| 314 | - $stack->appendBuild(BucketEndpointMiddleware::wrap(), 's3.bucket_endpoint'); | |
| 336 | + $stack->appendBuild(BucketEndpointMiddleware::wrap($this->isUseEndpointV2(), $args['endpoint'] ?? null), 's3.bucket_endpoint'); | |
| 315 | 337 | } elseif (!$this->isUseEndpointV2()) { |
| 316 | 338 | $stack->appendBuild(S3EndpointMiddleware::wrap($this->getRegion(), $this->getConfig('endpoint_provider'), ['accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint'), 'use_fips_endpoint' => $this->getConfig('use_fips_endpoint'), 'dual_stack' => $this->getConfig('use_dual_stack_endpoint')->isUseDualStackEndpoint()]), 's3.endpoint_middleware'); |
| 317 | 339 | } |
| 318 | 340 | $stack->appendBuild(BucketEndpointArnMiddleware::wrap($this->getApi(), $this->getRegion(), ['use_arn_region' => $this->getConfig('use_arn_region'), 'accelerate' => $this->getConfig('use_accelerate_endpoint'), 'path_style' => $this->getConfig('use_path_style_endpoint'), 'dual_stack' => $this->getConfig('use_dual_stack_endpoint')->isUseDualStackEndpoint(), 'use_fips_endpoint' => $this->getConfig('use_fips_endpoint'), 'disable_multiregion_access_points' => $this->getConfig('disable_multiregion_access_points'), 'endpoint' => $args['endpoint'] ?? null], $this->isUseEndpointV2()), 's3.bucket_endpoint_arn'); |
| @@ -369,13 +391,63 @@ | ||
| 369 | 391 | // The Configuration class itself will validate other inputs |
| 370 | 392 | $args['use_arn_region'] = new Configuration($value); |
| 371 | 393 | } |
| 372 | 394 | } |
| 395 | + public static function _default_request_checksum_calculation(array $args) : string | |
| 396 | + { | |
| 397 | + return ConfigurationResolver::resolve('request_checksum_calculation', ApplyChecksumMiddleware::DEFAULT_CALCULATION_MODE, 'string', $args); | |
| 398 | + } | |
| 399 | + public static function _apply_request_checksum_calculation(string $value, array &$args) : void | |
| 400 | + { | |
| 401 | + $value = \strtolower($value); | |
| 402 | + if (\array_key_exists($value, self::$checksumOptionEnum)) { | |
| 403 | + $args['request_checksum_calculation'] = $value; | |
| 404 | + } else { | |
| 405 | + $validValues = \implode(' | ', \array_keys(self::$checksumOptionEnum)); | |
| 406 | + throw new \InvalidArgumentException('invalid value provided for `request_checksum_calculation`.' . ' valid values are: ' . $validValues . '.'); | |
| 407 | + } | |
| 408 | + } | |
| 409 | + public static function _default_response_checksum_validation(array $args) : string | |
| 410 | + { | |
| 411 | + return ConfigurationResolver::resolve('response_checksum_validation', ValidateResponseChecksumResultMutator::DEFAULT_VALIDATION_MODE, 'string', $args); | |
| 412 | + } | |
| 413 | + public static function _apply_response_checksum_validation($value, array &$args) : void | |
| 414 | + { | |
| 415 | + $value = \strtolower($value); | |
| 416 | + if (\array_key_exists($value, self::$checksumOptionEnum)) { | |
| 417 | + $args['response_checksum_validation'] = $value; | |
| 418 | + } else { | |
| 419 | + $validValues = \implode(' | ', \array_keys(self::$checksumOptionEnum)); | |
| 420 | + throw new \InvalidArgumentException('invalid value provided for `response_checksum_validation`.' . ' valid values are: ' . $validValues . '.'); | |
| 421 | + } | |
| 422 | + } | |
| 423 | + public static function _default_disable_express_session_auth(array &$args) | |
| 424 | + { | |
| 425 | + return ConfigurationResolver::resolve('s3_disable_express_session_auth', \false, 'bool', $args); | |
| 426 | + } | |
| 427 | + public static function _default_s3_express_identity_provider(array $args) | |
| 428 | + { | |
| 429 | + if ($args['config']['disable_express_session_auth']) { | |
| 430 | + return \false; | |
| 431 | + } | |
| 432 | + return new S3ExpressIdentityProvider($args['region']); | |
| 433 | + } | |
| 373 | 434 | public function createPresignedRequest(CommandInterface $command, $expires, array $options = []) |
| 374 | 435 | { |
| 375 | 436 | $command = clone $command; |
| 376 | - $command->getHandlerList()->remove('signer'); | |
| 437 | + $list = $command->getHandlerList(); | |
| 438 | + $list->remove('signer'); | |
| 439 | + //Removes checksum calculation behavior by default | |
| 440 | + if (empty($command['ChecksumAlgorithm']) && empty($command['AddContentMD5'])) { | |
| 441 | + $list->remove('s3.checksum'); | |
| 442 | + } | |
| 377 | 443 | $request = \Dudlewebs\WPMCS\s3\Aws\serialize($command); |
| 444 | + //Applies ContentSHA256 parameter, if provided and not applied | |
| 445 | + // by middleware | |
| 446 | + $commandName = $command->getName(); | |
| 447 | + if (!empty($command['ContentSHA256'] && isset(ApplyChecksumMiddleware::$sha256[$commandName]) && !$request->hasHeader('X-Amz-Content-Sha256'))) { | |
| 448 | + $request = $request->withHeader('X-Amz-Content-Sha256', $command['ContentSHA256']); | |
| 449 | + } | |
| 378 | 450 | $signing_name = $command['@context']['signing_service'] ?? $this->getSigningName($request->getUri()->getHost()); |
| 379 | 451 | $signature_version = $this->getSignatureVersionFromCommand($command); |
| 380 | 452 | /** @var \Aws\Signature\SignatureInterface $signer */ |
| 381 | 453 | $signer = \call_user_func($this->getSignatureProvider(), $signature_version, $signing_name, $this->getConfig('signing_region')); |
| @@ -425,14 +497,18 @@ | ||
| 425 | 497 | { |
| 426 | 498 | $region = $this->getRegion(); |
| 427 | 499 | return static function (callable $handler) use($region) { |
| 428 | 500 | return function (Command $command, $request = null) use($handler, $region) { |
| 429 | - if ($command->getName() === 'CreateBucket') { | |
| 501 | + if ($command->getName() === 'CreateBucket' && !self::isDirectoryBucket($command['Bucket'])) { | |
| 430 | 502 | $locationConstraint = $command['CreateBucketConfiguration']['LocationConstraint'] ?? null; |
| 431 | 503 | if ($locationConstraint === 'us-east-1') { |
| 432 | 504 | unset($command['CreateBucketConfiguration']); |
| 433 | 505 | } elseif ('us-east-1' !== $region && empty($locationConstraint)) { |
| 434 | - $command['CreateBucketConfiguration'] = ['LocationConstraint' => $region]; | |
| 506 | + if (isset($command['CreateBucketConfiguration'])) { | |
| 507 | + $command['CreateBucketConfiguration']['LocationConstraint'] = $region; | |
| 508 | + } else { | |
| 509 | + $command['CreateBucketConfiguration'] = ['LocationConstraint' => $region]; | |
| 510 | + } | |
| 435 | 511 | } |
| 436 | 512 | } |
| 437 | 513 | return $handler($command, $request); |
| 438 | 514 | }; |
| @@ -463,9 +539,9 @@ | ||
| 463 | 539 | */ |
| 464 | 540 | private function getHeadObjectMiddleware() |
| 465 | 541 | { |
| 466 | 542 | return static function (callable $handler) { |
| 467 | - return function (CommandInterface $command, RequestInterface $request = null) use($handler) { | |
| 543 | + return function (CommandInterface $command, ?RequestInterface $request = null) use($handler) { | |
| 468 | 544 | if ($command->getName() === 'HeadObject' && !isset($command['@http']['decode_content'])) { |
| 469 | 545 | $command['@http']['decode_content'] = \false; |
| 470 | 546 | } |
| 471 | 547 | return $handler($command, $request); |
| @@ -538,9 +614,9 @@ | ||
| 538 | 614 | */ |
| 539 | 615 | private function getDisableExpressSessionAuthMiddleware() |
| 540 | 616 | { |
| 541 | 617 | return function (callable $handler) { |
| 542 | - return function (CommandInterface $command, RequestInterface $request = null) use($handler) { | |
| 618 | + return function (CommandInterface $command, ?RequestInterface $request = null) use($handler) { | |
| 543 | 619 | if (!empty($command['@context']['signature_version']) && $command['@context']['signature_version'] === 'v4-s3express') { |
| 544 | 620 | $command['@context']['signature_version'] = 's3v4'; |
| 545 | 621 | } |
| 546 | 622 | return $handler($command, $request); |
| @@ -560,19 +636,8 @@ | ||
| 560 | 636 | return 's3-object-lambda'; |
| 561 | 637 | } |
| 562 | 638 | return $this->getConfig('signing_name'); |
| 563 | 639 | } |
| 564 | - public static function _default_disable_express_session_auth(array &$args) | |
| 565 | - { | |
| 566 | - return ConfigurationResolver::resolve('s3_disable_express_session_auth', \false, 'bool', $args); | |
| 567 | - } | |
| 568 | - public static function _default_s3_express_identity_provider(array $args) | |
| 569 | - { | |
| 570 | - if ($args['config']['disable_express_session_auth']) { | |
| 571 | - return \false; | |
| 572 | - } | |
| 573 | - return new S3ExpressIdentityProvider($args['region']); | |
| 574 | - } | |
| 575 | 640 | /** |
| 576 | 641 | * If EndpointProviderV2 is used, removes `Bucket` from request URIs. |
| 577 | 642 | * This is now handled by the endpoint ruleset. |
| 578 | 643 | * |
| @@ -594,8 +659,12 @@ | ||
| 594 | 659 | if ($requestUri === "/{Bucket}") { |
| 595 | 660 | $requestUri = \str_replace('/{Bucket}', '/', $requestUri); |
| 596 | 661 | } else { |
| 597 | 662 | $requestUri = \str_replace('/{Bucket}', '', $requestUri); |
| 663 | + // If we're left with just a query string, prepend '/' | |
| 664 | + if (\str_starts_with($requestUri, '?')) { | |
| 665 | + $requestUri = '/' . $requestUri; | |
| 666 | + } | |
| 598 | 667 | } |
| 599 | 668 | $operation['http']['requestUri'] = $requestUri; |
| 600 | 669 | } |
| 601 | 670 | } |
| @@ -601,9 +670,9 @@ | ||
| 601 | 670 | } |
| 602 | 671 | } |
| 603 | 672 | foreach ($definition['shapes'] as $key => &$value) { |
| 604 | 673 | $suffix = 'Output'; |
| 605 | - if (\substr($key, -\strlen($suffix)) === $suffix) { | |
| 674 | + if (\str_ends_with($key, $suffix)) { | |
| 606 | 675 | if (isset($value['members']['Expires'])) { |
| 607 | 676 | $value['members']['Expires']['deprecated'] = \true; |
| 608 | 677 | $value['members']['ExpiresString'] = ['shape' => 'ExpiresString', 'location' => 'header', 'locationName' => 'Expires']; |
| 609 | 678 | } |
| @@ -646,8 +715,19 @@ | ||
| 646 | 715 | } |
| 647 | 716 | } |
| 648 | 717 | $this->clientBuiltIns[$key] = $value; |
| 649 | 718 | } |
| 719 | + /** | |
| 720 | + * Determines whether a bucket is a directory bucket. | |
| 721 | + * Only considers the availability zone/suffix format | |
| 722 | + * | |
| 723 | + * @param string $bucket | |
| 724 | + * @return bool | |
| 725 | + */ | |
| 726 | + public static function isDirectoryBucket(string $bucket) : bool | |
| 727 | + { | |
| 728 | + return \preg_match(self::DIRECTORY_BUCKET_REGEX, $bucket) === 1; | |
| 729 | + } | |
| 650 | 730 | /** @internal */ |
| 651 | 731 | public static function _applyRetryConfig($value, $args, HandlerList $list) |
| 652 | 732 | { |
| 653 | 733 | if ($value) { |
| @@ -697,9 +777,9 @@ | ||
| 697 | 777 | { |
| 698 | 778 | ClientResolver::_apply_api_provider($value, $args); |
| 699 | 779 | $s3Parser = new S3Parser($args['parser'], $args['error_parser'], $args['api'], $args['exception_class']); |
| 700 | 780 | $s3Parser->addS3ResultMutator('get-bucket-location', new GetBucketLocationResultMutator()); |
| 701 | - $s3Parser->addS3ResultMutator('validate-response-checksum', new ValidateResponseChecksumResultMutator($args['api'])); | |
| 781 | + $s3Parser->addS3ResultMutator('validate-response-checksum', new ValidateResponseChecksumResultMutator($args['api'], ['response_checksum_validation' => $args['response_checksum_validation']])); | |
| 702 | 782 | $args['parser'] = $s3Parser; |
| 703 | 783 | } |
| 704 | 784 | /** |
| 705 | 785 | * @internal |