Fix chunked transfers in client lib.
[pithos] / pithos / lib / client.py
index 16cfabc..dff5da3 100644 (file)
 # interpreted as representing official policies, either expressed
 # or implied, of GRNET S.A.
 
-from httplib import HTTPConnection, HTTP
+from httplib import HTTPConnection, HTTPSConnection, HTTP
 from sys import stdin
 from xml.dom import minidom
 from StringIO import StringIO
 from urllib import quote, unquote
+from urlparse import urlparse
 
 import json
 import types
@@ -54,8 +55,8 @@ ERROR_CODES = {304:'Not Modified',
                413:'Request Entity Too Large',
                416:'Range Not Satisfiable',
                422:'Unprocessable Entity',
-               503:'Service Unavailable',
-               }
+               500:'Internal Server Error',
+               501:'Not Implemented'}
 
 class Fault(Exception):
     def __init__(self, data='', status=None):
@@ -66,20 +67,26 @@ class Fault(Exception):
         self.status = status
 
 class Client(object):
-    def __init__(self, host, token, account, api='v1', verbose=False, debug=False):
-        """`host` can also include a port, e.g '127.0.0.1:8000'."""
+    def __init__(self, url, token, account, verbose=False, debug=False):
+        """`url` can also include a port, e.g '127.0.0.1:8000'."""
         
-        self.host = host
+        self.url = url
         self.account = account
-        self.api = api
         self.verbose = verbose or debug
         self.debug = debug
         self.token = token
     
     def _req(self, method, path, body=None, headers={}, format='text', params={}):
-        full_path = _prepare_path(path, self.api, format, params)
+        p = urlparse(self.url)
+        if p.scheme == 'http':
+            conn = HTTPConnection(p.netloc)
+        elif p.scheme == 'https':
+            conn = HTTPSConnection(p.netloc)
+        else:
+            raise Exception('Unknown URL scheme')
+        
+        full_path = _prepare_path(p.path + path, format, params)
         
-        conn = HTTPConnection(self.host)
         kwargs = {}
         kwargs['headers'] = _prepare_headers(headers)
         kwargs['headers']['X-Auth-Token'] = self.token
@@ -100,9 +107,16 @@ class Client(object):
     def _chunked_transfer(self, path, method='PUT', f=stdin, headers=None,
                           blocksize=1024, params={}):
         """perfomrs a chunked request"""
-        full_path = _prepare_path(path, self.api, params=params)
+        p = urlparse(self.url)
+        if p.scheme == 'http':
+            conn = HTTPConnection(p.netloc)
+        elif p.scheme == 'https':
+            conn = HTTPSConnection(p.netloc)
+        else:
+            raise Exception('Unknown URL scheme')
+        
+        full_path = _prepare_path(p.path + path, params=params)
         
-        conn = HTTPConnection(self.host)
         conn.putrequest(method, full_path)
         conn.putheader('x-auth-token', self.token)
         conn.putheader('content-type', 'application/octet-stream')
@@ -448,6 +462,7 @@ class OOS_Client(Client):
         account = account or self.account
         path = '/%s/%s/%s' % (account, dst_container, dst_object)
         headers = {} if not headers else headers
+        params = {}
         for k, v in meta.items():
             headers['x-object-meta-%s' % k] = v
         if remove:
@@ -456,8 +471,10 @@ class OOS_Client(Client):
             headers['x-copy-from'] = '/%s/%s' % (src_container, src_object)
         headers['content_length'] = 0
         if content_type:
-            headers['content_type'] = content_type 
-        return self.put(path, headers=headers)
+            headers['content_type'] = content_type
+        else:
+            params['ignore_content_type'] = ''
+        return self.put(path, headers=headers, params=params)
     
     def copy_object(self, src_container, src_object, dst_container, dst_object,
                    meta={}, account=None, content_type=None, **headers):
@@ -916,9 +933,8 @@ class Pithos_Client(OOS_Client):
         sharing = '%s=%s' % (action, ','.join(l))
         self.update_object(container, object, f=None, x_object_sharing=sharing)
 
-def _prepare_path(path, api, format='text', params={}):
-    slash = '/' if api else ''
-    full_path = '%s%s%s?format=%s' % (slash, api, quote(path), format)
+def _prepare_path(path, format='text', params={}):
+    full_path = '%s?format=%s' % (quote(path), format)
     
     for k,v in params.items():
         value = quote(str(v)) if v else ''