Use format for uploaded blocks hash lists at the container level.
[pithos] / pithos / api / util.py
index 7893c27..5e80dec 100644 (file)
@@ -41,6 +41,7 @@ from urllib import quote, unquote
 
 from django.conf import settings
 from django.http import HttpResponse
+from django.template.loader import render_to_string
 from django.utils import simplejson as json
 from django.utils.http import http_date, parse_etags
 from django.utils.encoding import smart_unicode, smart_str
@@ -51,7 +52,7 @@ from pithos.lib.compat import parse_http_date_safe, parse_http_date
 
 from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, Forbidden, ItemNotFound,
                                 Conflict, LengthRequired, PreconditionFailed, RequestEntityTooLarge,
-                                RangeNotSatisfiable, ServiceUnavailable)
+                                RangeNotSatisfiable, InternalServerError, NotImplemented)
 from pithos.api.short_url import encode_url
 from pithos.backends import connect_backend
 from pithos.backends.base import NotAllowedError, QuotaError
@@ -302,6 +303,8 @@ def split_container_object_string(s):
 def copy_or_move_object(request, src_account, src_container, src_name, dest_account, dest_container, dest_name, move=False):
     """Copy or move an object."""
     
+    if 'ignore_content_type' in request.GET and 'CONTENT_TYPE' in request.META:
+        del(request.META['CONTENT_TYPE'])
     meta, permissions, public = get_object_headers(request)
     src_version = request.META.get('HTTP_X_SOURCE_VERSION')
     try:
@@ -320,7 +323,7 @@ def copy_or_move_object(request, src_account, src_container, src_name, dest_acco
     except ValueError:
         raise BadRequest('Invalid sharing header')
     except AttributeError, e:
-        raise Conflict('\n'.join(e.data) + '\n')
+        raise Conflict(simple_list_response(request, e.data))
     except QuotaError:
         raise RequestEntityTooLarge('Quota exceeded')
     if public is not None:
@@ -497,7 +500,7 @@ def raw_input_socket(request):
         return request._req
     if 'wsgi.input' in request.environ:
         return request.environ['wsgi.input']
-    raise ServiceUnavailable('Unknown server software')
+    raise NotImplemented('Unknown server software')
 
 MAX_UPLOAD_SIZE = 5 * (1024 * 1024 * 1024) # 5GB
 
@@ -756,6 +759,14 @@ def hashmap_md5(request, hashmap, size):
         md5.update(data + ('\x00' * pad))
     return md5.hexdigest().lower()
 
+def simple_list_response(request, l):
+    if request.serialization == 'text':
+        return '\n'.join(l) + '\n'
+    if request.serialization == 'xml':
+        return render_to_string('items.xml', {'items': l})
+    if request.serialization == 'json':
+        return json.dumps(l)
+
 def get_backend():
     backend = connect_backend(db_module=settings.BACKEND_DB_MODULE,
                               db_connection=settings.BACKEND_DB_CONNECTION,
@@ -810,11 +821,13 @@ def update_response_headers(request, response):
         response['Date'] = format_date_time(time())
 
 def render_fault(request, fault):
-    if settings.DEBUG or settings.TEST:
+    if isinstance(fault, InternalServerError) and (settings.DEBUG or settings.TEST):
         fault.details = format_exc(fault)
     
     request.serialization = 'text'
-    data = '\n'.join((fault.message, fault.details)) + '\n'
+    data = fault.message + '\n'
+    if fault.details:
+        data += '\n' + fault.details
     response = HttpResponse(data, status=fault.code)
     update_response_headers(request, response)
     return response
@@ -875,7 +888,7 @@ def api_method(http_method=None, format_allowed=False, user_required=True):
                 return render_fault(request, fault)
             except BaseException, e:
                 logger.exception('Unexpected error: %s' % e)
-                fault = ServiceUnavailable('Unexpected error')
+                fault = InternalServerError('Unexpected error')
                 return render_fault(request, fault)
             finally:
                 if getattr(request, 'backend', None) is not None: