Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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->appendSign($this->validateMd5(), 'sqs.md5');
68
    }
69
 
70
    /**
71
     * Converts a queue URL into a queue ARN.
72
     *
73
     * @param string $queueUrl The queue URL to perform the action on.
74
     *                         Retrieved when the queue is first created.
75
     *
76
     * @return string An ARN representation of the queue URL.
77
     */
78
    public function getQueueArn($queueUrl)
79
    {
80
        $queueArn = strtr($queueUrl, [
81
            'http://'        => 'arn:aws:',
82
            'https://'       => 'arn:aws:',
83
            '.amazonaws.com' => '',
84
            '/'              => ':',
85
            '.'              => ':',
86
        ]);
87
 
88
        // Cope with SQS' .fifo / :fifo arn inconsistency
89
        if (substr($queueArn, -5) === ':fifo') {
90
            $queueArn = substr_replace($queueArn, '.fifo', -5);
91
        }
92
        return $queueArn;
93
    }
94
 
95
    /**
96
     * Calculates the expected md5 hash of message attributes according to the encoding
97
     * scheme detailed in SQS documentation.
98
     *
99
     * @param array $message Message containing attributes for validation.
100
     *                       Retrieved when using MessageAttributeNames on
101
     *                       ReceiveMessage.
102
     *
103
     * @return string|null The md5 hash of the message attributes according to
104
     *                     the encoding scheme. Returns null when there are no
105
     *                     attributes.
106
     * @link http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-attributes.html#message-attributes-items-validation
107
     */
108
    private static function calculateMessageAttributesMd5($message)
109
    {
110
        if (empty($message['MessageAttributes'])
111
            || !is_array($message['MessageAttributes'])
112
        ) {
113
            return null;
114
        }
115
 
116
        ksort($message['MessageAttributes']);
117
        $attributeValues = "";
118
        foreach ($message['MessageAttributes'] as $name => $details) {
119
            $attributeValues .= self::getEncodedStringPiece($name);
120
            $attributeValues .= self::getEncodedStringPiece($details['DataType']);
121
            if (substr($details['DataType'], 0, 6) === 'Binary') {
122
                $attributeValues .= pack('c', 0x02);
123
                $attributeValues .= self::getEncodedBinaryPiece(
124
                    $details['BinaryValue']
125
                );
126
            } else {
127
                $attributeValues .= pack('c', 0x01);
128
                $attributeValues .= self::getEncodedStringPiece(
129
                    $details['StringValue']
130
                );
131
            }
132
        }
133
 
134
        return md5($attributeValues);
135
    }
136
 
137
    private static function calculateBodyMd5($message)
138
    {
139
        return md5($message['Body']);
140
    }
141
 
142
    private static function getEncodedStringPiece($piece)
143
    {
144
        $utf8Piece = iconv(
145
            mb_detect_encoding($piece, mb_detect_order(), true),
146
            "UTF-8",
147
            $piece
148
        );
149
        return self::getFourBytePieceLength($utf8Piece) . $utf8Piece;
150
    }
151
 
152
    private static function getEncodedBinaryPiece($piece)
153
    {
154
        return self::getFourBytePieceLength($piece) . $piece;
155
    }
156
 
157
    private static function getFourBytePieceLength($piece)
158
    {
159
        return pack('N', (int)strlen($piece));
160
    }
161
 
162
    /**
163
     * Validates ReceiveMessage body and message attribute MD5s.
164
     *
165
     * @return callable
166
     */
167
    private function validateMd5()
168
    {
169
        return static function (callable $handler) {
170
            return function (
171
                CommandInterface $c,
1441 ariadna 172
                ?RequestInterface $r = null
1 efrain 173
            ) use ($handler) {
174
                if ($c->getName() !== 'ReceiveMessage') {
175
                    return $handler($c, $r);
176
                }
177
 
178
                return $handler($c, $r)
179
                    ->then(
180
                        function ($result) use ($c, $r) {
181
                            foreach ((array) $result['Messages'] as $msg) {
182
                                $bodyMd5 = self::calculateBodyMd5($msg);
183
                                if (isset($msg['MD5OfBody'])
184
                                    && $bodyMd5 !== $msg['MD5OfBody']
185
                                ) {
186
                                    throw new SqsException(
187
                                        sprintf(
188
                                            'MD5 mismatch. Expected %s, found %s',
189
                                            $msg['MD5OfBody'],
190
                                            $bodyMd5
191
                                        ),
192
                                        $c,
193
                                        [
194
                                            'code' => 'ClientChecksumMismatch',
195
                                            'request' => $r
196
                                        ]
197
                                    );
198
                                }
199
 
200
                                if (isset($msg['MD5OfMessageAttributes'])) {
201
                                    $messageAttributesMd5 = self::calculateMessageAttributesMd5($msg);
202
                                    if ($messageAttributesMd5 !== $msg['MD5OfMessageAttributes']) {
203
                                        throw new SqsException(
204
                                            sprintf(
205
                                                'Attribute MD5 mismatch. Expected %s, found %s',
206
                                                $msg['MD5OfMessageAttributes'],
207
                                                $messageAttributesMd5
208
                                                    ? $messageAttributesMd5
209
                                                    : 'No Attributes'
210
                                            ),
211
                                            $c,
212
                                            [
213
                                                'code' => 'ClientChecksumMismatch',
214
                                                'request' => $r
215
                                            ]
216
                                        );
217
                                    }
1441 ariadna 218
                                } else if (!empty($msg['MessageAttributes'])) {
1 efrain 219
                                    throw new SqsException(
220
                                        sprintf(
221
                                            'No Attribute MD5 found. Expected %s',
222
                                            self::calculateMessageAttributesMd5($msg)
223
                                        ),
224
                                        $c,
225
                                        [
226
                                            'code' => 'ClientChecksumMismatch',
227
                                            'request' => $r
228
                                        ]
229
                                    );
230
                                }
231
                            }
232
                            return $result;
233
                        }
234
                    );
235
            };
236
        };
237
    }
238
}