Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws;
3
 
4
use Aws\Api\Service;
5
use Aws\Api\Validator;
6
use Aws\Credentials\CredentialsInterface;
7
use Aws\EndpointV2\EndpointProviderV2;
8
use Aws\Exception\AwsException;
9
use Aws\Token\TokenAuthorization;
10
use Aws\Token\TokenInterface;
11
use GuzzleHttp\Promise;
12
use GuzzleHttp\Psr7;
13
use GuzzleHttp\Psr7\LazyOpenStream;
14
use Psr\Http\Message\RequestInterface;
15
 
16
final class Middleware
17
{
18
    /**
19
     * Middleware used to allow a command parameter (e.g., "SourceFile") to
20
     * be used to specify the source of data for an upload operation.
21
     *
22
     * @param Service $api
23
     * @param string  $bodyParameter
24
     * @param string  $sourceParameter
25
     *
26
     * @return callable
27
     */
28
    public static function sourceFile(
29
        Service $api,
30
        $bodyParameter = 'Body',
31
        $sourceParameter = 'SourceFile'
32
    ) {
33
        return function (callable $handler) use (
34
            $api,
35
            $bodyParameter,
36
            $sourceParameter
37
        ) {
38
            return function (
39
                CommandInterface $command,
40
                RequestInterface $request = null)
41
            use (
42
                $handler,
43
                $api,
44
                $bodyParameter,
45
                $sourceParameter
46
            ) {
47
                $operation = $api->getOperation($command->getName());
48
                $source = $command[$sourceParameter];
49
 
50
                if ($source !== null
51
                    && $operation->getInput()->hasMember($bodyParameter)
52
                ) {
53
                    $command[$bodyParameter] = new LazyOpenStream($source, 'r');
54
                    unset($command[$sourceParameter]);
55
                }
56
 
57
                return $handler($command, $request);
58
            };
59
        };
60
    }
61
 
62
    /**
63
     * Adds a middleware that uses client-side validation.
64
     *
65
     * @param Service $api API being accessed.
66
     *
67
     * @return callable
68
     */
69
    public static function validation(Service $api, Validator $validator = null)
70
    {
71
        $validator = $validator ?: new Validator();
72
        return function (callable $handler) use ($api, $validator) {
73
            return function (
74
                CommandInterface $command,
75
                RequestInterface $request = null
76
            ) use ($api, $validator, $handler) {
77
                if ($api->isModifiedModel()) {
78
                    $api = new Service(
79
                        $api->getDefinition(),
80
                        $api->getProvider()
81
                    );
82
                }
83
                $operation = $api->getOperation($command->getName());
84
                $validator->validate(
85
                    $command->getName(),
86
                    $operation->getInput(),
87
                    $command->toArray()
88
                );
89
                return $handler($command, $request);
90
            };
91
        };
92
    }
93
 
94
    /**
95
     * Builds an HTTP request for a command.
96
     *
97
     * @param callable $serializer Function used to serialize a request for a
98
     *                             command.
99
     * @param EndpointProviderV2 | null $endpointProvider
100
     * @param array $providerArgs
101
     * @return callable
102
     */
103
    public static function requestBuilder(
104
        $serializer,
105
        $endpointProvider = null,
106
        array $providerArgs = null
107
    )
108
    {
109
        return function (callable $handler) use ($serializer, $endpointProvider, $providerArgs) {
110
            return function (CommandInterface $command) use ($serializer, $handler, $endpointProvider, $providerArgs) {
111
                return $handler($command, $serializer($command, $endpointProvider, $providerArgs));
112
            };
113
        };
114
    }
115
 
116
    /**
117
     * Creates a middleware that signs requests for a command.
118
     *
119
     * @param callable $credProvider      Credentials provider function that
120
     *                                    returns a promise that is resolved
121
     *                                    with a CredentialsInterface object.
122
     * @param callable $signatureFunction Function that accepts a Command
123
     *                                    object and returns a
124
     *                                    SignatureInterface.
125
     *
126
     * @return callable
127
     */
128
    public static function signer(callable $credProvider, callable $signatureFunction, $tokenProvider = null)
129
    {
130
        return function (callable $handler) use ($signatureFunction, $credProvider, $tokenProvider) {
131
            return function (
132
                CommandInterface $command,
133
                RequestInterface $request
134
            ) use ($handler, $signatureFunction, $credProvider, $tokenProvider) {
135
                $signer = $signatureFunction($command);
136
                if ($signer instanceof TokenAuthorization) {
137
                    return $tokenProvider()->then(
138
                        function (TokenInterface $token)
139
                        use ($handler, $command, $signer, $request) {
140
                            return $handler(
141
                                $command,
142
                                $signer->authorizeRequest($request, $token)
143
                            );
144
                        }
145
                    );
146
                } else {
147
                    return $credProvider()->then(
148
                        function (CredentialsInterface $creds)
149
                        use ($handler, $command, $signer, $request) {
150
                            return $handler(
151
                                $command,
152
                                $signer->signRequest($request, $creds)
153
                            );
154
                        }
155
                    );
156
                }
157
            };
158
        };
159
    }
160
 
161
    /**
162
     * Creates a middleware that invokes a callback at a given step.
163
     *
164
     * The tap callback accepts a CommandInterface and RequestInterface as
165
     * arguments but is not expected to return a new value or proxy to
166
     * downstream middleware. It's simply a way to "tap" into the handler chain
167
     * to debug or get an intermediate value.
168
     *
169
     * @param callable $fn Tap function
170
     *
171
     * @return callable
172
     */
173
    public static function tap(callable $fn)
174
    {
175
        return function (callable $handler) use ($fn) {
176
            return function (
177
                CommandInterface $command,
178
                RequestInterface $request = null
179
            ) use ($handler, $fn) {
180
                $fn($command, $request);
181
                return $handler($command, $request);
182
            };
183
        };
184
    }
185
 
186
    /**
187
     * Middleware wrapper function that retries requests based on the boolean
188
     * result of invoking the provided "decider" function.
189
     *
190
     * If no delay function is provided, a simple implementation of exponential
191
     * backoff will be utilized.
192
     *
193
     * @param callable $decider Function that accepts the number of retries,
194
     *                          a request, [result], and [exception] and
195
     *                          returns true if the command is to be retried.
196
     * @param callable $delay   Function that accepts the number of retries and
197
     *                          returns the number of milliseconds to delay.
198
     * @param bool $stats       Whether to collect statistics on retries and the
199
     *                          associated delay.
200
     *
201
     * @return callable
202
     */
203
    public static function retry(
204
        callable $decider = null,
205
        callable $delay = null,
206
        $stats = false
207
    ) {
208
        $decider = $decider ?: RetryMiddleware::createDefaultDecider();
209
        $delay = $delay ?: [RetryMiddleware::class, 'exponentialDelay'];
210
 
211
        return function (callable $handler) use ($decider, $delay, $stats) {
212
            return new RetryMiddleware($decider, $delay, $handler, $stats);
213
        };
214
    }
215
    /**
216
     * Middleware wrapper function that adds an invocation id header to
217
     * requests, which is only applied after the build step.
218
     *
219
     * This is a uniquely generated UUID to identify initial and subsequent
220
     * retries as part of a complete request lifecycle.
221
     *
222
     * @return callable
223
     */
224
    public static function invocationId()
225
    {
226
        return function (callable $handler) {
227
            return function (
228
                CommandInterface $command,
229
                RequestInterface $request
230
            ) use ($handler){
231
                return $handler($command, $request->withHeader(
232
                    'aws-sdk-invocation-id',
233
                    md5(uniqid(gethostname(), true))
234
                ));
235
            };
236
        };
237
    }
238
    /**
239
     * Middleware wrapper function that adds a Content-Type header to requests.
240
     * This is only done when the Content-Type has not already been set, and the
241
     * request body's URI is available. It then checks the file extension of the
242
     * URI to determine the mime-type.
243
     *
244
     * @param array $operations Operations that Content-Type should be added to.
245
     *
246
     * @return callable
247
     */
248
    public static function contentType(array $operations)
249
    {
250
        return function (callable $handler) use ($operations) {
251
            return function (
252
                CommandInterface $command,
253
                RequestInterface $request = null
254
            ) use ($handler, $operations) {
255
                if (!$request->hasHeader('Content-Type')
256
                    && in_array($command->getName(), $operations, true)
257
                    && ($uri = $request->getBody()->getMetadata('uri'))
258
                ) {
259
                    $request = $request->withHeader(
260
                        'Content-Type',
261
                        Psr7\MimeType::fromFilename($uri) ?: 'application/octet-stream'
262
                    );
263
                }
264
 
265
                return $handler($command, $request);
266
            };
267
        };
268
    }
269
    /**
270
     * Middleware wrapper function that adds a trace id header to requests
271
     * from clients instantiated in supported Lambda runtime environments.
272
     *
273
     * The purpose for this header is to track and stop Lambda functions
274
     * from being recursively invoked due to misconfigured resources.
275
     *
276
     * @return callable
277
     */
278
    public static function recursionDetection()
279
    {
280
        return function (callable $handler) {
281
            return function (
282
                CommandInterface $command,
283
                RequestInterface $request
284
            ) use ($handler){
285
                $isLambda = getenv('AWS_LAMBDA_FUNCTION_NAME');
286
                $traceId = str_replace('\e', '\x1b', getenv('_X_AMZN_TRACE_ID'));
287
 
288
                if ($isLambda && $traceId) {
289
                    if (!$request->hasHeader('X-Amzn-Trace-Id')) {
290
                        $ignoreChars = ['=', ';', ':', '+', '&', '[', ']', '{', '}', '"', '\'', ','];
291
                        $traceIdEncoded = rawurlencode(stripcslashes($traceId));
292
 
293
                        foreach($ignoreChars as $char) {
294
                            $encodedChar = rawurlencode($char);
295
                            $traceIdEncoded = str_replace($encodedChar, $char,  $traceIdEncoded);
296
                        }
297
 
298
                        return $handler($command, $request->withHeader(
299
                            'X-Amzn-Trace-Id',
300
                            $traceIdEncoded
301
                        ));
302
                    }
303
                }
304
                return $handler($command, $request);
305
            };
306
        };
307
    }
308
    /**
309
     * Tracks command and request history using a history container.
310
     *
311
     * This is useful for testing.
312
     *
313
     * @param History $history History container to store entries.
314
     *
315
     * @return callable
316
     */
317
    public static function history(History $history)
318
    {
319
        return function (callable $handler) use ($history) {
320
            return function (
321
                CommandInterface $command,
322
                RequestInterface $request = null
323
            ) use ($handler, $history) {
324
                $ticket = $history->start($command, $request);
325
                return $handler($command, $request)
326
                    ->then(
327
                        function ($result) use ($history, $ticket) {
328
                            $history->finish($ticket, $result);
329
                            return $result;
330
                        },
331
                        function ($reason) use ($history, $ticket) {
332
                            $history->finish($ticket, $reason);
333
                            return Promise\Create::rejectionFor($reason);
334
                        }
335
                    );
336
            };
337
        };
338
    }
339
 
340
    /**
341
     * Creates a middleware that applies a map function to requests as they
342
     * pass through the middleware.
343
     *
344
     * @param callable $f Map function that accepts a RequestInterface and
345
     *                    returns a RequestInterface.
346
     *
347
     * @return callable
348
     */
349
    public static function mapRequest(callable $f)
350
    {
351
        return function (callable $handler) use ($f) {
352
            return function (
353
                CommandInterface $command,
354
                RequestInterface $request = null
355
            ) use ($handler, $f) {
356
                return $handler($command, $f($request));
357
            };
358
        };
359
    }
360
 
361
    /**
362
     * Creates a middleware that applies a map function to commands as they
363
     * pass through the middleware.
364
     *
365
     * @param callable $f Map function that accepts a command and returns a
366
     *                    command.
367
     *
368
     * @return callable
369
     */
370
    public static function mapCommand(callable $f)
371
    {
372
        return function (callable $handler) use ($f) {
373
            return function (
374
                CommandInterface $command,
375
                RequestInterface $request = null
376
            ) use ($handler, $f) {
377
                return $handler($f($command), $request);
378
            };
379
        };
380
    }
381
 
382
    /**
383
     * Creates a middleware that applies a map function to results.
384
     *
385
     * @param callable $f Map function that accepts an Aws\ResultInterface and
386
     *                    returns an Aws\ResultInterface.
387
     *
388
     * @return callable
389
     */
390
    public static function mapResult(callable $f)
391
    {
392
        return function (callable $handler) use ($f) {
393
            return function (
394
                CommandInterface $command,
395
                RequestInterface $request = null
396
            ) use ($handler, $f) {
397
                return $handler($command, $request)->then($f);
398
            };
399
        };
400
    }
401
 
402
    public static function timer()
403
    {
404
        return function (callable $handler) {
405
            return function (
406
                CommandInterface $command,
407
                RequestInterface $request = null
408
            ) use ($handler) {
409
                $start = microtime(true);
410
                return $handler($command, $request)
411
                    ->then(
412
                        function (ResultInterface $res) use ($start) {
413
                            if (!isset($res['@metadata'])) {
414
                                $res['@metadata'] = [];
415
                            }
416
                            if (!isset($res['@metadata']['transferStats'])) {
417
                                $res['@metadata']['transferStats'] = [];
418
                            }
419
 
420
                            $res['@metadata']['transferStats']['total_time']
421
                                = microtime(true) - $start;
422
 
423
                            return $res;
424
                        },
425
                        function ($err) use ($start) {
426
                            if ($err instanceof AwsException) {
427
                                $err->setTransferInfo([
428
                                    'total_time' => microtime(true) - $start,
429
                                ] + $err->getTransferInfo());
430
                            }
431
                            return Promise\Create::rejectionFor($err);
432
                        }
433
                    );
434
            };
435
        };
436
    }
437
}