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

Source Code for Module s3.connection

  1  import base64 
  2  import hmac 
  3  import httplib 
  4  import sha 
  5  import socket 
  6  import urllib 
  7  from time import gmtime, strftime 
  8   
  9  import s3 
 10  from s3.parsers import parseError 
 11   
 12  PORTS_BY_SECURITY = { True: 443, False: 80 } 
 13   
14 -class S3Connection(object):
15 - def __init__(self, pub_key, priv_key, secure=True, host=s3.DEFAULT_HOST, port=None, debug=0):
16 self._pub_key = pub_key 17 self._priv_key = priv_key 18 self._host = host 19 if not port: 20 self._port = PORTS_BY_SECURITY[secure] 21 else: 22 self._port = port 23 self._secure = secure 24 25 if (secure): 26 self._conn = httplib.HTTPSConnection("%s:%d" % (self._host, self._port)) 27 else: 28 self._conn = httplib.HTTPConnection("%s:%d" % (self._host, self._port)) 29 self._set_debug(debug)
30
31 - def _set_debug(self, debug):
32 self._debug = debug 33 self._conn.set_debuglevel(debug)
34 35
36 - def clone(self):
37 """C.clone() -> new connection to s3""" 38 return S3Connection(self._pub_key, self._priv_key, secure=self._secure, host=self._host, port=self._port, debug=self._debug)
39 40
41 - def _auth_header_value(self, method, path, headers):
42 xamzs = [k for k in headers.keys() if k.startswith("x-amz-")] 43 xamzs.sort() 44 auth_parts = [method, 45 headers.get("Content-MD5", ""), 46 headers.get("Content-Type", ""), 47 headers.get("Date", ""),] 48 auth_parts.extend([k + ":" + headers[k].strip() for k in xamzs]) 49 # hmmm fali mi ona perverzija za ?acl i ?torrent 50 auth_parts.append(path) 51 auth_str = "\n".join(auth_parts) 52 auth_str = base64.encodestring( 53 hmac.new(self._priv_key, auth_str, sha).digest()).strip() 54 return "AWS %s:%s" % (self._pub_key, auth_str)
55
56 - def _headers(self, method, path, length=None, headers=None):
57 if not headers: 58 headers = {} 59 headers["Date"] = strftime("%a, %d %b %Y %H:%M:%S GMT", gmtime()) 60 if length is not None: 61 headers["Content-Length"] = length 62 headers["Authorization"] = self._auth_header_value(method, path, headers) 63 return headers
64
65 - def _params(self, params):
66 p = '' 67 if params: 68 p = '?' + urllib.urlencode(params) 69 return p
70
71 - def _path(self, bucket=None, obj=None):
72 if bucket is None: 73 return "/" 74 bucket = "/" + bucket 75 if obj is None: 76 return bucket 77 return bucket + "/" + urllib.quote(obj)
78
79 - def _io_len(self, io):
80 if hasattr(io, "len"): 81 return io.len 82 o_pos = io.tell() 83 io.seek(0, 2) 84 length = io.tell() - o_pos 85 io.seek(o_pos, 0) 86 return length
87
88 - def __getattr__(self, attr):
89 method = attr.upper() 90 def f(bucket=None, obj=None, send_io=None, params=None, headers=None): 91 path = self._path(bucket, obj) 92 length = None 93 if isinstance(headers, dict) and headers.has_key("Content-Length"): 94 length = headers["Content-Length"] 95 elif send_io is not None: 96 length = self._io_len(send_io) 97 headers = self._headers(method, path, length=length, headers=headers) 98 99 def do_c(): 100 self._conn.putrequest(method, path + self._params(params)) 101 for k,v in headers.items(): 102 self._conn.putheader(k, v) 103 self._conn.endheaders()
104 105 retry = False 106 try: 107 do_c() 108 except socket.error, e: 109 # if broken pipe (timed out/server closed connection) 110 # open new connection and try again 111 if e[0] == 32: 112 retry = True 113 if retry: 114 do_c() 115 116 if send_io is not None: 117 data = send_io.read(httplib.MAXAMOUNT) 118 while len(data) > 0: 119 self._conn.send(data) 120 data = send_io.read(httplib.MAXAMOUNT) 121 send_io.read() # seems to be needed to finish the response 122 try: 123 r = self._conn.getresponse() 124 except httplib.ResponseNotReady, e: 125 e.args += ('You are probably overlapping S3 ops, like doing f = bucket.get(k); bucket.keys(); f.read(). Try using bucket.clone() such as f = bucket.clone().get(k)',) 126 raise e 127 if r.status < 200 or r.status > 299: 128 raise parseError(r.read()) 129 if not method == "GET": 130 r.read() 131 return r
132 return f 133