-# Copyright 2011 GRNET S.A. All rights reserved.
+# Copyright 2011-2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
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
from django.core.files.uploadedfile import UploadedFile
from pithos.lib.compat import parse_http_date_safe, parse_http_date
-from pithos.lib.hashmap import HashMap
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
return meta, get_sharing(request), get_public(request)
def put_object_headers(response, meta, restricted=False):
- response['ETag'] = meta['ETag'] if 'ETag' in meta else meta['hash']
+ if 'ETag' in meta:
+ response['ETag'] = meta['ETag']
response['Content-Length'] = meta['bytes']
response['Content-Type'] = meta.get('Content-Type', 'application/octet-stream')
response['Last-Modified'] = http_date(int(meta['modified']))
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:
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:
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
hashmap.append(request.backend.put_block(('\x00' * bo) + data[:bl]))
return bl # Return ammount of data written.
-#def hashmap_hash(request, hashmap):
-# """Produce the root hash, treating the hashmap as a Merkle-like tree."""
-#
-# map = HashMap(request.backend.block_size, request.backend.hash_algorithm)
-# map.extend([unhexlify(x) for x in hashmap])
-# return hexlify(map.hash())
-
def hashmap_md5(request, hashmap, size):
"""Produce the MD5 sum from the data in the hashmap."""
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,
+ block_module=settings.BACKEND_BLOCK_MODULE,
+ block_path=settings.BACKEND_BLOCK_PATH)
+ backend.default_policy['quota'] = settings.BACKEND_QUOTA
+ backend.default_policy['versioning'] = settings.BACKEND_VERSIONING
+ return backend
+
def update_request_headers(request):
# Handle URL-encoded keys and values.
# Handle URL-encoded keys and values.
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
# Fill in custom request variables.
request.serialization = request_serialization(request, format_allowed)
- request.backend = connect_backend()
+ request.backend = get_backend()
response = func(request, *args, **kwargs)
update_response_headers(request, response)
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: