--- /dev/null
+#!/usr/bin/python2.6
+
+"""A simple test API for accessing Windows Azure blob storage.
+
+Parts of the code are modeled after boto (a library for accessing Amazon Web
+Services), but this code is far less general and is meant only as a
+proof-of-concept."""
+
+import base64, hashlib, hmac, httplib, os, time
+
+# The version of the Azure API we implement; sent in the x-ms-version header.
+API_VERSION = '2009-09-19'
+
+def uri_decode(s):
+ # TODO
+ return s
+
+def add_auth_header(headers, method, path):
+ header_order = ['Content-Encoding', 'Content-Language', 'Content-Length',
+ 'Content-MD5', 'Content-Type', 'Date', 'If-Modified-Since',
+ 'If-Match', 'If-None-Match', 'If-Unmodified-Since',
+ 'Range']
+
+ if not headers.has_key('Date'):
+ headers['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S GMT",
+ time.gmtime())
+ if not headers.has_key('x-ms-version'):
+ headers['x-ms-version'] = API_VERSION
+
+ StringToSign = method + "\n"
+ for h in header_order:
+ if h in headers:
+ StringToSign += headers[h] + "\n"
+ else:
+ StringToSign += "\n"
+
+ # Add Canonicalized Headers
+ canonized = []
+ for (k, v) in headers.items():
+ k = k.lower()
+ if k.startswith('x-ms-'):
+ canonized.append((k, v))
+ canonized.sort()
+ for (k, v) in canonized:
+ StringToSign += "%s:%s\n" % (k, v)
+
+ # Add CanonicalizedHeaders Resource
+ account_name = os.environ['AZURE_ACCOUNT_NAME']
+ account_name = 'bluesky'
+ resource = "/" + account_name
+ if '?' not in path:
+ resource += path
+ else:
+ (path, params) = path.split('?', 1)
+ params = [p.split('=') for p in params.split("&")]
+ params = dict((k.lower(), uri_decode(v)) for (k, v) in params)
+ resource += path
+ for k in sorted(params):
+ resource += "\n%s:%s" % (k, params[k])
+ StringToSign += resource
+
+ # print "String to sign:", repr(StringToSign)
+
+ secret_key = os.environ['AZURE_SECRET_KEY']
+ secret_key = base64.b64decode(secret_key)
+ h = hmac.new(secret_key, digestmod=hashlib.sha256)
+ h.update(StringToSign)
+
+ signature = base64.b64encode(h.digest())
+ headers['Authorization'] = "SharedKey %s:%s" % (account_name, signature)
+
+def generate_request(path, method='GET', body="", headers={}):
+ host = os.environ['AZURE_ACCOUNT_NAME'] + ".blob.core.windows.net"
+ #auth_path = conn.calling_format.build_auth_path(self.bucket, key)
+
+ headers = headers.copy()
+ headers['Content-Length'] = str(len(body))
+ if len(body) > 0:
+ headers['Content-MD5'] = base64.b64encode(hashlib.md5(body).digest())
+ add_auth_header(headers, method, path)
+
+ req = "%s %s HTTP/1.1\r\nHost: %s\r\n" % (method, path, host)
+ req = req + ''.join("%s: %s\r\n" % h for h in headers.items()) + "\r\n"
+ print req
+
+ conn = httplib.HTTPConnection(host)
+ conn.request(method, path, body, headers)
+ response = conn.getresponse()
+ print "Response:", response.status
+ print "Headers:", response.getheaders()
+ print "Body:", response.read()
+
+if False:
+ generate_request("/?comp=list")