Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
namespace Aws\Sqs;
3
 
4
use Aws\AwsClient;
5
use Aws\CommandInterface;
6
use Aws\Sqs\Exception\SqsException;
7
use GuzzleHttp\Psr7\Uri;
8
use GuzzleHttp\Psr7\UriResolver;
9
use Psr\Http\Message\RequestInterface;
10
 
11
/**
12
 * Client used to interact Amazon Simple Queue Service (Amazon SQS)
13
 *
14
 * @method \Aws\Result addPermission(array $args = [])
15
 * @method \GuzzleHttp\Promise\Promise addPermissionAsync(array $args = [])
16
 * @method \Aws\Result cancelMessageMoveTask(array $args = [])
17
 * @method \GuzzleHttp\Promise\Promise cancelMessageMoveTaskAsync(array $args = [])
18
 * @method \Aws\Result changeMessageVisibility(array $args = [])
19
 * @method \GuzzleHttp\Promise\Promise changeMessageVisibilityAsync(array $args = [])
20
 * @method \Aws\Result changeMessageVisibilityBatch(array $args = [])
21
 * @method \GuzzleHttp\Promise\Promise changeMessageVisibilityBatchAsync(array $args = [])
22
 * @method \Aws\Result createQueue(array $args = [])
23
 * @method \GuzzleHttp\Promise\Promise createQueueAsync(array $args = [])
24
 * @method \Aws\Result deleteMessage(array $args = [])
25
 * @method \GuzzleHttp\Promise\Promise deleteMessageAsync(array $args = [])
26
 * @method \Aws\Result deleteMessageBatch(array $args = [])
27
 * @method \GuzzleHttp\Promise\Promise deleteMessageBatchAsync(array $args = [])
28
 * @method \Aws\Result deleteQueue(array $args = [])
29
 * @method \GuzzleHttp\Promise\Promise deleteQueueAsync(array $args = [])
30
 * @method \Aws\Result getQueueAttributes(array $args = [])
31
 * @method \GuzzleHttp\Promise\Promise getQueueAttributesAsync(array $args = [])
32
 * @method \Aws\Result getQueueUrl(array $args = [])
33
 * @method \GuzzleHttp\Promise\Promise getQueueUrlAsync(array $args = [])
34
 * @method \Aws\Result listDeadLetterSourceQueues(array $args = [])
35
 * @method \GuzzleHttp\Promise\Promise listDeadLetterSourceQueuesAsync(array $args = [])
36
 * @method \Aws\Result listMessageMoveTasks(array $args = [])
37
 * @method \GuzzleHttp\Promise\Promise listMessageMoveTasksAsync(array $args = [])
38
 * @method \Aws\Result listQueueTags(array $args = [])
39
 * @method \GuzzleHttp\Promise\Promise listQueueTagsAsync(array $args = [])
40
 * @method \Aws\Result listQueues(array $args = [])
41
 * @method \GuzzleHttp\Promise\Promise listQueuesAsync(array $args = [])
42
 * @method \Aws\Result purgeQueue(array $args = [])
43
 * @method \GuzzleHttp\Promise\Promise purgeQueueAsync(array $args = [])
44
 * @method \Aws\Result receiveMessage(array $args = [])
45
 * @method \GuzzleHttp\Promise\Promise receiveMessageAsync(array $args = [])
46
 * @method \Aws\Result removePermission(array $args = [])
47
 * @method \GuzzleHttp\Promise\Promise removePermissionAsync(array $args = [])
48
 * @method \Aws\Result sendMessage(array $args = [])
49
 * @method \GuzzleHttp\Promise\Promise sendMessageAsync(array $args = [])
50
 * @method \Aws\Result sendMessageBatch(array $args = [])
51
 * @method \GuzzleHttp\Promise\Promise sendMessageBatchAsync(array $args = [])
52
 * @method \Aws\Result setQueueAttributes(array $args = [])
53
 * @method \GuzzleHttp\Promise\Promise setQueueAttributesAsync(array $args = [])
54
 * @method \Aws\Result startMessageMoveTask(array $args = [])
55
 * @method \GuzzleHttp\Promise\Promise startMessageMoveTaskAsync(array $args = [])
56
 * @method \Aws\Result tagQueue(array $args = [])
57
 * @method \GuzzleHttp\Promise\Promise tagQueueAsync(array $args = [])
58
 * @method \Aws\Result untagQueue(array $args = [])
59
 * @method \GuzzleHttp\Promise\Promise untagQueueAsync(array $args = [])
60
 */
61
class SqsClient extends AwsClient
62
{
63
    public function __construct(array $config)
64
    {
65
        parent::__construct($config);
66
        $list = $this->getHandlerList();
67
        $list->appendBuild($this->queueUrl(), 'sqs.queue_url');
68
        $list->appendSign($this->validateMd5(), 'sqs.md5');
69
    }
70
 
71
    /**
72
     * Converts a queue URL into a queue ARN.
73
     *
74
     * @param string $queueUrl The queue URL to perform the action on.
75
     *                         Retrieved when the queue is first created.
76
     *
77
     * @return string An ARN representation of the queue URL.
78
     */
79
    public function getQueueArn($queueUrl)
80
    {
81
        $queueArn = strtr($queueUrl, [
82
            'http://'        => 'arn:aws:',
83
            'https://'       => 'arn:aws:',
84
            '.amazonaws.com' => '',
85
            '/'              => ':',
86
            '.'              => ':',
87
        ]);
88
 
89
        // Cope with SQS' .fifo / :fifo arn inconsistency
90
        if (substr($queueArn, -5) === ':fifo') {
91
            $queueArn = substr_replace($queueArn, '.fifo', -5);
92
        }
93
        return $queueArn;
94
    }
95
 
96
    /**
97
     * Moves the URI of the queue to the URI in the input parameter.
98
     *
99
     * @return callable
100
     */
101
    private function queueUrl()
102
    {
103
        return static function (callable $handler) {
104
            return function (
105
                CommandInterface $c,
106
                RequestInterface $r = null
107
            ) use ($handler) {
108
                if ($c->hasParam('QueueUrl')) {
109
                    $r = $r->withUri(UriResolver::resolve(
110
                        $r->getUri(),
111
                        new Uri($c['QueueUrl'])
112
                    ));
113
                }
114
                return $handler($c, $r);
115
            };
116
        };
117
    }
118
 
119
    /**
120
     * Calculates the expected md5 hash of message attributes according to the encoding
121
     * scheme detailed in SQS documentation.
122
     *
123
     * @param array $message Message containing attributes for validation.
124
     *                       Retrieved when using MessageAttributeNames on
125
     *                       ReceiveMessage.
126
     *
127
     * @return string|null The md5 hash of the message attributes according to
128
     *                     the encoding scheme. Returns null when there are no
129
     *                     attributes.
130
     * @link http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-attributes.html#message-attributes-items-validation
131
     */
132
    private static function calculateMessageAttributesMd5($message)
133
    {
134
        if (empty($message['MessageAttributes'])
135
            || !is_array($message['MessageAttributes'])
136
        ) {
137
            return null;
138
        }
139
 
140
        ksort($message['MessageAttributes']);
141
        $attributeValues = "";
142
        foreach ($message['MessageAttributes'] as $name => $details) {
143
            $attributeValues .= self::getEncodedStringPiece($name);
144
            $attributeValues .= self::getEncodedStringPiece($details['DataType']);
145
            if (substr($details['DataType'], 0, 6) === 'Binary') {
146
                $attributeValues .= pack('c', 0x02);
147
                $attributeValues .= self::getEncodedBinaryPiece(
148
                    $details['BinaryValue']
149
                );
150
            } else {
151
                $attributeValues .= pack('c', 0x01);
152
                $attributeValues .= self::getEncodedStringPiece(
153
                    $details['StringValue']
154
                );
155
            }
156
        }
157
 
158
        return md5($attributeValues);
159
    }
160
 
161
    private static function calculateBodyMd5($message)
162
    {
163
        return md5($message['Body']);
164
    }
165
 
166
    private static function getEncodedStringPiece($piece)
167
    {
168
        $utf8Piece = iconv(
169
            mb_detect_encoding($piece, mb_detect_order(), true),
170
            "UTF-8",
171
            $piece
172
        );
173
        return self::getFourBytePieceLength($utf8Piece) . $utf8Piece;
174
    }
175
 
176
    private static function getEncodedBinaryPiece($piece)
177
    {
178
        return self::getFourBytePieceLength($piece) . $piece;
179
    }
180
 
181
    private static function getFourBytePieceLength($piece)
182
    {
183
        return pack('N', (int)strlen($piece));
184
    }
185
 
186
    /**
187
     * Validates ReceiveMessage body and message attribute MD5s.
188
     *
189
     * @return callable
190
     */
191
    private function validateMd5()
192
    {
193
        return static function (callable $handler) {
194
            return function (
195
                CommandInterface $c,
196
                RequestInterface $r = null
197
            ) use ($handler) {
198
                if ($c->getName() !== 'ReceiveMessage') {
199
                    return $handler($c, $r);
200
                }
201
 
202
                return $handler($c, $r)
203
                    ->then(
204
                        function ($result) use ($c, $r) {
205
                            foreach ((array) $result['Messages'] as $msg) {
206
                                $bodyMd5 = self::calculateBodyMd5($msg);
207
                                if (isset($msg['MD5OfBody'])
208
                                    && $bodyMd5 !== $msg['MD5OfBody']
209
                                ) {
210
                                    throw new SqsException(
211
                                        sprintf(
212
                                            'MD5 mismatch. Expected %s, found %s',
213
                                            $msg['MD5OfBody'],
214
                                            $bodyMd5
215
                                        ),
216
                                        $c,
217
                                        [
218
                                            'code' => 'ClientChecksumMismatch',
219
                                            'request' => $r
220
                                        ]
221
                                    );
222
                                }
223
 
224
                                if (isset($msg['MD5OfMessageAttributes'])) {
225
                                    $messageAttributesMd5 = self::calculateMessageAttributesMd5($msg);
226
                                    if ($messageAttributesMd5 !== $msg['MD5OfMessageAttributes']) {
227
                                        throw new SqsException(
228
                                            sprintf(
229
                                                'Attribute MD5 mismatch. Expected %s, found %s',
230
                                                $msg['MD5OfMessageAttributes'],
231
                                                $messageAttributesMd5
232
                                                    ? $messageAttributesMd5
233
                                                    : 'No Attributes'
234
                                            ),
235
                                            $c,
236
                                            [
237
                                                'code' => 'ClientChecksumMismatch',
238
                                                'request' => $r
239
                                            ]
240
                                        );
241
                                    }
242
                                } else if (isset($msg['MessageAttributes'])) {
243
                                    throw new SqsException(
244
                                        sprintf(
245
                                            'No Attribute MD5 found. Expected %s',
246
                                            self::calculateMessageAttributesMd5($msg)
247
                                        ),
248
                                        $c,
249
                                        [
250
                                            'code' => 'ClientChecksumMismatch',
251
                                            'request' => $r
252
                                        ]
253
                                    );
254
                                }
255
                            }
256
                            return $result;
257
                        }
258
                    );
259
            };
260
        };
261
    }
262
}