1 import sqs
2 import re
3 import sha
4 import hmac
5 import time
6 import base64
7 import urllib
8
9
10 DEFAULT_CONTENT_TYPE = 'text/plain'
11 PORTS_BY_SECURITY = { True: 443, False: 80 }
12
13 DEFAULT_EXPIRES_IN = 60
14
16 """
17 Generator class
18
19 Objects of this class are used for generating authenticated URLs for accessing
20 Amazon's SQS service.
21 """
23 self._pub_key = pub_key
24 self._priv_key = priv_key
25 self._host = host
26 if not port:
27 self._port = PORTS_BY_SECURITY[secure]
28 else:
29 self._port = port
30 if (secure):
31 self.protocol = 'https'
32 else:
33 self.protocol = 'http'
34 self._secure = secure
35 self.server_name = "%s:%d" % (self._host, self._port)
36 self._expires_in = DEFAULT_EXPIRES_IN
37 self._expires = None
38
39
41 """
42 Set relative expiration time from the url creation moment.
43
44 @param expires_in: Relative expiration time
45 @type expires_in: int
46 """
47 self._expires_in = expires_in
48 self._expires = None
49
50
52 """
53 Set absolute expiration time.
54
55 @param expires: Absolute expiration time
56 @type expires: time.time()
57 """
58 self._expires = expires
59 self._expires_in = None
60
61
63 auth_str = "%s%s" % (action, timestamp)
64 auth_str = base64.encodestring(
65 hmac.new(self._priv_key, auth_str, sha).digest()).strip()
66 return urllib.quote_plus(auth_str)
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
85 if not headers:
86 headers = {}
87 if not headers.has_key('Date'):
88 headers["Date"] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime())
89 if not headers.has_key('AWS-Version'):
90 headers['AWS-Version'] = sqs.VERSION
91 if not headers.has_key('Content-Type'):
92 headers['Content-Type'] = DEFAULT_CONTENT_TYPE
93 if not headers.has_key('Content-MD5'):
94 headers['Content-MD5'] = ''
95 if not headers.has_key('Content-Length'):
96 if length is not None:
97 headers['Content-Length'] = length
98 else:
99 headers['Content-Length'] = 0
100 return headers
101
102
103 - def _params(self, params, acl=False):
104 p = ''
105 if params:
106 if acl:
107 arg_div = '&'
108 else:
109 arg_div = '?'
110 p = arg_div + urllib.urlencode(params)
111 return p
112
113
114 - def _path(self, queue=None, message=None, acl=False):
115 if queue is None:
116 path = "/"
117 else:
118 path = '/' + queue
119 if message is not None:
120 path += '/' + message
121 if acl:
122 path += '?acl'
123 return path
124
125
127 if hasattr(io, "len"):
128 return io.len
129 o_pos = io.tell()
130 io.seek(0, 2)
131 length = io.tell() - o_pos
132 io.seek(o_pos, 0)
133 return length
134
135
136 - def _generate(self, method, queue=None, message=None, send_io=None, params=None, headers=None, acl=False):
137 expires = 0
138 if self._expires_in != None:
139 expires = int(time.time() + self._expires_in)
140 elif self._expires != None:
141 expires = int(self._expires)
142 expires_str = time.strftime("%Y-%m-%dT%XZ", time.gmtime(expires))
143 path = self._path(queue, message, acl)
144 length = None
145 if isinstance(headers, dict) and headers.has_key("Content-Length"):
146 length = headers["Content-Length"]
147 elif send_io is not None:
148 length = self._io_len(send_io)
149 headers = self._headers(headers=headers, length=length)
150 signature = self._auth_header_value(params['Action'], expires_str)
151 path += self._params(params, acl)
152 if '?' in path:
153 arg_div = '&'
154 else:
155 arg_div = '?'
156 query_part = "Expires=%s&AWSAccessKeyId=%s&Version=%s&Signature=%s" % \
157 (expires_str, self._pub_key, sqs.VERSION, signature)
158
159 return self.protocol + '://' + self.server_name + path + arg_div + query_part
160
161
163 """
164 Create a queue.
165
166 @param name: The name to use for the Queue created.
167 The Queue name must be unique for all queues created by
168 the given Access Key ID.
169 @type name: string
170 @param timeout: Default visibility timeout for this Queue.
171 If this parameter is not included, the default value is
172 set to 30 seconds
173 @type timeout: int
174 @return: Authenticated URL for creating a new Queue.
175 @rtype: string
176 """
177 params = {
178 'Action' : 'CreateQueue',
179 'QueueName' : name
180 }
181 if timeout:
182 params['DefaultVisibilityTimeout'] = timeout
183 return self._generate('GET', params=params)
184
185
187 """
188 List all queues or queues with a certan prefix.
189
190 @param prefix: This parameter can be used to filter results returned.
191 When specified, only queues with queue names beginning
192 with the specified string are returned.
193 @type prefix: string
194 @return: Authenticated URL for listing Queues.
195 @rtype: string
196 """
197 params = { 'Action' : 'ListQueues' }
198 if prefix:
199 params['QueueNamePrefix'] = prefix
200 return self._generate('GET', params=params)
201
202
204 """
205 Delete a queue.
206
207 @param queue_url: Queue url
208 @type queue_url: string
209 @return: Authenticated URL for deleting queue
210 @rtype: string
211 """
212 params = { 'Action' : 'DeleteQueue' }
213 return self._generate('GET', queue=queue_url, params=params)
214
215
217 """
218 Save a message into Queue.
219
220 @param queue_url: URL for the Queue in which the message should be saved
221 @type queue_url: string
222 @param message: Message body
223 @type message: string
224 @return: Authenticated URL for saving message into Queue
225 @rtype: string
226 """
227 params = {
228 'Action' : 'SendMessage',
229 'MessageBody' : urllib.quote(message)
230 }
231 return self._generate('GET', queue=queue_url, params=params)
232
234 """
235 Get message(s) from Queue.
236
237 @param queue_url: URL for the Queue from which the message should be
238 relatived
239 @type queue_url: string
240 @param number: Maximum number of messages to return.
241 If the number of messages in the queue is less than
242 value specified by NumberOfMessages, then the number
243 of messages returned is up to the number of messages
244 in the queue. Not necessarily all the messages in the
245 queue will be returned. If no value is provided, the
246 default value of 1 is used.
247 @type number: int
248 @param timeout: The duration, in seconds, that the messages are
249 visible in the queue. If no value is specified, the
250 default value for the queue is used
251 @type timeout: int
252 @return: Authenticated URL for retreaving messages from Queue
253 @rtype: string
254 """
255 params = { 'Action' : 'ReceiveMessage' }
256 if number: params['NumberOfMessages'] = number
257 if timeout: params['VisibilityTimeout'] = timeout
258 return self._generate('GET', queue=queue_url, params=params)
259
260
262 """
263 Delete a message from Queue.
264
265 @param queue_url: URL for the Queue from which the message should be deleted
266 @type queue_url: string
267 @param message_id: The ID of the message to delete
268 @type message_id: string
269 @return: Authenticated URL for deleting message from Queue
270 @rtype: string
271 """
272 params = {
273 'Action' : 'DeleteMessage',
274 'MessageId' : message_id
275 }
276 return self._generate('GET', queue=queue_url, params=params)
277
279 """
280 Returns a preview of the message specified in the MessageId parameter.
281
282 The message is returned regardless of the VisibilityTimeout state on the
283 queue. The visibility state is not modified when PeekMessage is used,
284 thereby not affecting which messages get returned from a subsequent
285 ReceiveMessage request.
286
287 @param queue_url: URL for the Queue from which the message should be peeked
288 @type queue_url: string
289 @param message_id: The ID of the message to retreave
290 @type message_id: string
291 @return: Authenticated URL for retreaveing a message
292 @rtype: string
293 """
294 params = {
295 'Action' : 'PeekMessage',
296 'MessageId' : message_id
297 }
298 return self._generate('GET', queue=queue_url, params=params)
299
301 pass
302
303
305 pass
306
307
309 pass
310
311
313 pass
314
315
317 pass
318