Package sqs :: Module connection
[hide private]
[frames] | no frames]

Source Code for Module sqs.connection

  1  import re 
  2  import sha 
  3  import hmac 
  4  import time 
  5  import base64 
  6  import socket 
  7  import urllib 
  8  import httplib 
  9   
 10  import sqs 
 11  from sqs.parsers import parseError 
 12   
 13   
 14  DEFAULT_CONTENT_TYPE = 'text/plain' 
 15  PORTS_BY_SECURITY = { True: 443, False: 80 } 
 16   
17 -class SQSConnection(object):
18 """SQS Connection class. 19 20 You shoud never use this class directly. User SQSService instead. 21 """
22 - def __init__(self, pub_key, priv_key, host=sqs.DEFAULT_HOST, port=None, secure=True, debug=0):
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 self._secure = secure 31 if (secure): 32 self._conn = httplib.HTTPSConnection("%s:%d" % (self._host, self._port)) 33 else: 34 self._conn = httplib.HTTPConnection("%s:%d" % (self._host, self._port)) 35 self._set_debug(debug)
36 37
38 - def _set_debug(self, debug):
39 self._debug = debug 40 self._conn.set_debuglevel(debug)
41 42
43 - def clone(self):
44 """C.clone() -> new connection to sqs""" 45 return SQSConnection(self._pub_key, self._priv_key, self._host, self._port, self._secure, self._debug)
46 47
48 - def _auth_header_value(self, method, path, headers):
49 path = path.split('?')[0] 50 # ...unless there is an acl parameter 51 if re.search("[&?]acl($|=|&)", path): 52 path += "?acl" 53 auth_parts = [method, 54 headers.get("Content-MD5", ""), 55 headers.get("Content-Type", DEFAULT_CONTENT_TYPE), 56 headers.get("Date", time.strftime("%a, %d %b %Y %X GMT", time.gmtime())), 57 path] 58 auth_str = "\n".join(auth_parts) 59 auth_str = base64.encodestring( 60 hmac.new(self._priv_key, auth_str, sha).digest()).strip() 61 return "AWS %s:%s" % (self._pub_key, auth_str)
62 63
64 - def _headers(self, method, path, length=None, headers=None):
65 if not headers: 66 headers = {} 67 if not headers.has_key('Date'): 68 headers["Date"] = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime()) 69 if not headers.has_key('AWS-Version'): 70 headers['AWS-Version'] = sqs.VERSION 71 if not headers.has_key('Content-Type'): 72 headers['Content-Type'] = DEFAULT_CONTENT_TYPE 73 if not headers.has_key('Content-MD5'): 74 headers['Content-MD5'] = '' 75 if not headers.has_key('Content-Length'): 76 if length is not None: 77 headers['Content-Length'] = length 78 else: 79 headers['Content-Length'] = 0 80 headers["Authorization"] = self._auth_header_value(method, path, headers) 81 return headers
82
83 - def _params(self, params):
84 p = '' 85 if params: 86 p = '?' + urllib.urlencode(params) 87 return p
88
89 - def _path(self, queue=None, message=None):
90 if queue is None: 91 return "/" 92 queue = '/' + queue 93 if message is None: 94 return queue 95 return queue + "/" + message
96
97 - def _io_len(self, io):
98 if hasattr(io, "len"): 99 return io.len 100 o_pos = io.tell() 101 io.seek(0, 2) 102 length = io.tell() - o_pos 103 io.seek(o_pos, 0) 104 return length
105 106
107 - def __getattr__(self, attr):
108 method = attr.upper() 109 def f(queue=None, message=None, send_io=None, params=None, headers=None): 110 path = self._path(queue, message) 111 length = None 112 if isinstance(headers, dict) and headers.has_key("Content-Length"): 113 length = headers["Content-Length"] 114 elif send_io is not None: 115 length = self._io_len(send_io) 116 117 headers = self._headers(method, path, length=length, headers=headers) 118 119 def do_conn(): 120 self._conn.putrequest(method, path + self._params(params)) 121 for k,v in headers.items(): 122 self._conn.putheader(k, v) 123 self._conn.endheaders()
124 125 retry = False 126 try: 127 do_conn() 128 except socket.error, e: 129 # if broken pipe (timed out/server closed connection) 130 # open new connection and try again 131 if e[0] == 32: 132 retry = True 133 if retry: 134 do_conn() 135 136 if send_io is not None: 137 data = send_io.read(httplib.MAXAMOUNT) 138 while len(data) > 0: 139 self._conn.send(data) 140 data = send_io.read(httplib.MAXAMOUNT) 141 send_io.read() # seems to be needed to finish the response 142 try: 143 r = self._conn.getresponse() 144 except httplib.ResponseNotReady, e: 145 e.args += ('You are probably overlapping SQS ops',) 146 raise e 147 if r.status < 200 or r.status > 299: 148 raise parseError(r.read()) 149 return r
150 return f 151