PluginProbe ʕ •ᴥ•ʔ
Transferito: WP Migration / trunk
Transferito: WP Migration vtrunk
trunk 11.4.0 12.0.0 13.1.0 14.0.0 14.0.11 14.0.7 14.1.0 14.1.1 14.1.2 14.1.3 14.1.4
transferito / vendor / aws / aws-sdk-php / src / S3 / S3EndpointMiddleware.php
transferito / vendor / aws / aws-sdk-php / src / S3 Last commit date
Crypto 11 months ago Exception 11 months ago RegionalEndpoint 11 months ago UseArnRegion 11 months ago AmbiguousSuccessParser.php 11 months ago ApplyChecksumMiddleware.php 11 months ago BatchDelete.php 11 months ago BucketEndpointArnMiddleware.php 11 months ago BucketEndpointMiddleware.php 11 months ago CalculatesChecksumTrait.php 11 months ago EndpointRegionHelperTrait.php 11 months ago GetBucketLocationParser.php 11 months ago MultipartCopy.php 11 months ago MultipartUploader.php 11 months ago MultipartUploadingTrait.php 11 months ago ObjectCopier.php 11 months ago ObjectUploader.php 11 months ago PermanentRedirectMiddleware.php 11 months ago PostObject.php 11 months ago PostObjectV4.php 11 months ago PutObjectUrlMiddleware.php 11 months ago RetryableMalformedResponseParser.php 11 months ago S3Client.php 11 months ago S3ClientInterface.php 11 months ago S3ClientTrait.php 11 months ago S3EndpointMiddleware.php 11 months ago S3MultiRegionClient.php 11 months ago S3UriParser.php 11 months ago SSECMiddleware.php 11 months ago StreamWrapper.php 11 months ago Transfer.php 11 months ago ValidateResponseChecksumParser.php 11 months ago
S3EndpointMiddleware.php
344 lines
1 <?php
2 namespace Aws\S3;
3
4 use Aws\Arn\ArnParser;
5 use Aws\Arn\ObjectLambdaAccessPointArn;
6 use Aws\ClientResolver;
7 use Aws\CommandInterface;
8 use Aws\Endpoint\EndpointProvider;
9 use Aws\Endpoint\PartitionEndpointProvider;
10 use GuzzleHttp\Exception\InvalidArgumentException;
11 use GuzzleHttp\Psr7\Uri;
12 use Psr\Http\Message\RequestInterface;
13
14 /**
15 * Used to update the URL used for S3 requests to support:
16 * S3 Accelerate, S3 DualStack or Both. It will build to
17 * host style paths unless specified, including for S3
18 * DualStack.
19 *
20 * IMPORTANT: this middleware must be added after the "build" step.
21 *
22 * @internal
23 */
24 class S3EndpointMiddleware
25 {
26 private static $exclusions = [
27 'CreateBucket' => true,
28 'DeleteBucket' => true,
29 'ListBuckets' => true,
30 ];
31
32 const NO_PATTERN = 0;
33 const DUALSTACK = 1;
34 const ACCELERATE = 2;
35 const ACCELERATE_DUALSTACK = 3;
36 const PATH_STYLE = 4;
37 const HOST_STYLE = 5;
38
39 /** @var bool */
40 private $accelerateByDefault;
41 /** @var bool */
42 private $dualStackByDefault;
43 /** @var bool */
44 private $pathStyleByDefault;
45 /** @var string */
46 private $region;
47 /** @var callable */
48 private $endpointProvider;
49 /** @var callable */
50 private $nextHandler;
51 /** @var string */
52 private $endpoint;
53
54 /**
55 * Create a middleware wrapper function
56 *
57 * @param string $region
58 * @param EndpointProvider $endpointProvider
59 * @param array $options
60 *
61 * @return callable
62 */
63 public static function wrap($region, $endpointProvider, array $options)
64 {
65 return function (callable $handler) use ($region, $endpointProvider, $options) {
66 return new self($handler, $region, $options, $endpointProvider);
67 };
68 }
69
70 public function __construct(
71 callable $nextHandler,
72 $region,
73 array $options,
74 $endpointProvider = null
75 ) {
76 $this->pathStyleByDefault = isset($options['path_style'])
77 ? (bool) $options['path_style'] : false;
78 $this->dualStackByDefault = isset($options['dual_stack'])
79 ? (bool) $options['dual_stack'] : false;
80 $this->accelerateByDefault = isset($options['accelerate'])
81 ? (bool) $options['accelerate'] : false;
82 $this->region = (string) $region;
83 $this->endpoint = isset($options['endpoint'])
84 ? $options['endpoint'] : "";
85 $this->endpointProvider = is_null($endpointProvider)
86 ? PartitionEndpointProvider::defaultProvider()
87 : $endpointProvider;
88 $this->nextHandler = $nextHandler;
89 }
90
91 public function __invoke(CommandInterface $command, RequestInterface $request)
92 {
93 if (!empty($this->endpoint)) {
94 $request = $this->applyEndpoint($command, $request);
95 } else {
96 switch ($this->endpointPatternDecider($command, $request)) {
97 case self::HOST_STYLE:
98 $request = $this->applyHostStyleEndpoint($command, $request);
99 break;
100 case self::NO_PATTERN:
101 break;
102 case self::PATH_STYLE:
103 $request = $this->applyPathStyleEndpointCustomizations($command, $request);
104 break;
105 case self::DUALSTACK:
106 $request = $this->applyDualStackEndpoint($command, $request);
107 break;
108 case self::ACCELERATE:
109 $request = $this->applyAccelerateEndpoint(
110 $command,
111 $request,
112 's3-accelerate'
113 );
114 break;
115 case self::ACCELERATE_DUALSTACK:
116 $request = $this->applyAccelerateEndpoint(
117 $command,
118 $request,
119 's3-accelerate.dualstack'
120 );
121 break;
122 }
123 }
124 $nextHandler = $this->nextHandler;
125 return $nextHandler($command, $request);
126 }
127
128 private static function isRequestHostStyleCompatible(
129 CommandInterface $command,
130 RequestInterface $request
131 ) {
132 return S3Client::isBucketDnsCompatible($command['Bucket'])
133 && (
134 $request->getUri()->getScheme() === 'http'
135 || strpos($command['Bucket'], '.') === false
136 )
137 && filter_var($request->getUri()->getHost(), FILTER_VALIDATE_IP) === false;
138 }
139
140 private function endpointPatternDecider(
141 CommandInterface $command,
142 RequestInterface $request
143 ) {
144 $accelerate = isset($command['@use_accelerate_endpoint'])
145 ? $command['@use_accelerate_endpoint'] : $this->accelerateByDefault;
146 $dualStack = isset($command['@use_dual_stack_endpoint'])
147 ? $command['@use_dual_stack_endpoint'] : $this->dualStackByDefault;
148 $pathStyle = isset($command['@use_path_style_endpoint'])
149 ? $command['@use_path_style_endpoint'] : $this->pathStyleByDefault;
150
151 if ($accelerate && $dualStack) {
152 // When try to enable both for operations excluded from s3-accelerate,
153 // only dualstack endpoints will be enabled.
154 return $this->canAccelerate($command)
155 ? self::ACCELERATE_DUALSTACK
156 : self::DUALSTACK;
157 }
158
159 if ($accelerate && $this->canAccelerate($command)) {
160 return self::ACCELERATE;
161 }
162
163 if ($dualStack) {
164 return self::DUALSTACK;
165 }
166
167 if (!$pathStyle
168 && self::isRequestHostStyleCompatible($command, $request)
169 ) {
170 return self::HOST_STYLE;
171 }
172
173 return self::PATH_STYLE;
174 }
175
176 private function canAccelerate(CommandInterface $command)
177 {
178 return empty(self::$exclusions[$command->getName()])
179 && S3Client::isBucketDnsCompatible($command['Bucket']);
180 }
181
182 private function getBucketStyleHost(CommandInterface $command, $host)
183 {
184 // For operations on the base host (e.g. ListBuckets)
185 if (!isset($command['Bucket'])) {
186 return $host;
187 }
188
189 return "{$command['Bucket']}.{$host}";
190 }
191
192 private function applyHostStyleEndpoint(
193 CommandInterface $command,
194 RequestInterface $request
195 ) {
196 $uri = $request->getUri();
197 $request = $request->withUri(
198 $uri->withHost($this->getBucketStyleHost(
199 $command,
200 $uri->getHost()
201 ))
202 ->withPath($this->getBucketlessPath(
203 $uri->getPath(),
204 $command
205 ))
206 );
207 return $request;
208 }
209
210 private function applyPathStyleEndpointCustomizations(
211 CommandInterface $command,
212 RequestInterface $request
213 ) {
214 if ($command->getName() == 'WriteGetObjectResponse') {
215 $dnsSuffix = $this->endpointProvider
216 ->getPartition($this->region, 's3')
217 ->getDnsSuffix();
218 $fips = \Aws\is_fips_pseudo_region($this->region) ? "-fips" : "";
219 $region = \Aws\strip_fips_pseudo_regions($this->region);
220 $host =
221 "{$command['RequestRoute']}.s3-object-lambda{$fips}.{$region}.{$dnsSuffix}";
222
223 $uri = $request->getUri();
224 $request = $request->withUri(
225 $uri->withHost($host)
226 ->withPath($this->getBucketlessPath(
227 $uri->getPath(),
228 $command
229 ))
230 );
231 }
232 return $request;
233 }
234
235
236 private function applyDualStackEndpoint(
237 CommandInterface $command,
238 RequestInterface $request
239 ) {
240 $request = $request->withUri(
241 $request->getUri()->withHost($this->getDualStackHost())
242 );
243
244 if (empty($command['@use_path_style_endpoint'])
245 && !$this->pathStyleByDefault
246 && self::isRequestHostStyleCompatible($command, $request)
247 ) {
248 $request = $this->applyHostStyleEndpoint($command, $request);
249 }
250 return $request;
251 }
252
253 private function getDualStackHost()
254 {
255 $dnsSuffix = $this->endpointProvider
256 ->getPartition($this->region, 's3')
257 ->getDnsSuffix();
258 return "s3.dualstack.{$this->region}.{$dnsSuffix}";
259 }
260
261 private function applyAccelerateEndpoint(
262 CommandInterface $command,
263 RequestInterface $request,
264 $pattern
265 ) {
266 $request = $request->withUri(
267 $request->getUri()
268 ->withHost($this->getAccelerateHost($command, $pattern))
269 ->withPath($this->getBucketlessPath(
270 $request->getUri()->getPath(),
271 $command
272 ))
273 );
274 return $request;
275 }
276
277 private function getAccelerateHost(CommandInterface $command, $pattern)
278 {
279 $dnsSuffix = $this->endpointProvider
280 ->getPartition($this->region, 's3')
281 ->getDnsSuffix();
282 return "{$command['Bucket']}.{$pattern}.{$dnsSuffix}";
283 }
284
285 private function getBucketlessPath($path, CommandInterface $command)
286 {
287 $pattern = '/^\\/' . preg_quote($command['Bucket'], '/') . '/';
288 $path = preg_replace($pattern, '', $path) ?: '/';
289 if (substr($path, 0 , 1) !== '/') {
290 $path = '/' . $path;
291 }
292 return $path;
293 }
294
295 private function applyEndpoint(
296 CommandInterface $command,
297 RequestInterface $request
298 ) {
299 $dualStack = isset($command['@use_dual_stack_endpoint'])
300 ? $command['@use_dual_stack_endpoint'] : $this->dualStackByDefault;
301 if (ArnParser::isArn($command['Bucket'])) {
302 $arn = ArnParser::parse($command['Bucket']);
303 $outpost = $arn->getService() == 's3-outposts';
304 if ($outpost && $dualStack) {
305 throw new InvalidArgumentException("Outposts + dualstack is not supported");
306 }
307 if ($arn instanceof ObjectLambdaAccessPointArn) {
308 return $request;
309 }
310 }
311 if ($dualStack) {
312 throw new InvalidArgumentException("Custom Endpoint + Dualstack not supported");
313 }
314 if ($command->getName() == 'WriteGetObjectResponse') {
315 $host = "{$command['RequestRoute']}.{$this->endpoint}";
316 $uri = $request->getUri();
317 return $request = $request->withUri(
318 $uri->withHost($host)
319 ->withPath($this->getBucketlessPath(
320 $uri->getPath(),
321 $command
322 ))
323 );
324 }
325 $host = ($this->pathStyleByDefault) ?
326 $this->endpoint :
327 $this->getBucketStyleHost(
328 $command,
329 $this->endpoint
330 );
331 $uri = $request->getUri();
332 $scheme = $uri->getScheme();
333 if(empty($scheme)){
334 $request = $request->withUri(
335 $uri->withHost($host)
336 );
337 } else {
338 $request = $request->withUri($uri);
339 }
340
341 return $request;
342 }
343 }
344