Revision ab2e317e pithos/api/functions.py
b/pithos/api/functions.py | ||
---|---|---|
597 | 597 |
copy_from = request.META.get('HTTP_X_COPY_FROM') |
598 | 598 |
move_from = request.META.get('HTTP_X_MOVE_FROM') |
599 | 599 |
if copy_from or move_from: |
600 |
# TODO: Why is this required? Copy this ammount? |
|
601 |
content_length = get_content_length(request) |
|
600 |
content_length = get_content_length(request) # Required by the API. |
|
602 | 601 |
|
603 | 602 |
if move_from: |
604 | 603 |
try: |
... | ... | |
745 | 744 |
if k in prev_meta: |
746 | 745 |
meta[k] = prev_meta[k] |
747 | 746 |
|
748 |
# A Content-Type header indicates data updates. |
|
749 |
if not content_type or content_type != 'application/octet-stream': |
|
747 |
# A Content-Type or X-Source-Object header indicates data updates. |
|
748 |
src_object = request.META.get('HTTP_X_SOURCE_OBJECT') |
|
749 |
if (not content_type or content_type != 'application/octet-stream') and not src_object: |
|
750 | 750 |
# Do permissions first, as it may fail easier. |
751 | 751 |
if permissions is not None: |
752 | 752 |
try: |
... | ... | |
783 | 783 |
ranges = get_content_range(request) |
784 | 784 |
if not ranges: |
785 | 785 |
raise RangeNotSatisfiable('Invalid Content-Range header') |
786 |
# Require either a Content-Length, or 'chunked' Transfer-Encoding. |
|
787 |
content_length = -1 |
|
788 |
if request.META.get('HTTP_TRANSFER_ENCODING') != 'chunked': |
|
789 |
content_length = get_content_length(request) |
|
790 | 786 |
|
791 | 787 |
try: |
792 | 788 |
size, hashmap = backend.get_object_hashmap(request.user, v_account, v_container, v_object) |
... | ... | |
800 | 796 |
offset = size |
801 | 797 |
elif offset > size: |
802 | 798 |
raise RangeNotSatisfiable('Supplied offset is beyond object limits') |
803 |
if length is None or content_length == -1: |
|
804 |
length = content_length # Nevermind the error. |
|
805 |
elif length != content_length: |
|
806 |
raise BadRequest('Content length does not match range length') |
|
799 |
if src_object: |
|
800 |
src_container, src_name = split_container_object_string(src_object) |
|
801 |
src_version = request.META.get('HTTP_X_SOURCE_VERSION') |
|
802 |
try: |
|
803 |
src_size, src_hashmap = backend.get_object_hashmap(request.user, v_account, src_container, src_name, src_version) |
|
804 |
except NotAllowedError: |
|
805 |
raise Unauthorized('Access denied') |
|
806 |
except NameError: |
|
807 |
raise ItemNotFound('Source object does not exist') |
|
808 |
|
|
809 |
if length is None: |
|
810 |
length = src_size |
|
811 |
elif length > src_size: |
|
812 |
raise BadRequest('Object length is smaller than range length') |
|
813 |
else: |
|
814 |
# Require either a Content-Length, or 'chunked' Transfer-Encoding. |
|
815 |
content_length = -1 |
|
816 |
if request.META.get('HTTP_TRANSFER_ENCODING') != 'chunked': |
|
817 |
content_length = get_content_length(request) |
|
818 |
|
|
819 |
if length is None: |
|
820 |
length = content_length |
|
821 |
else: |
|
822 |
if content_length == -1: |
|
823 |
# TODO: Get up to length bytes in chunks. |
|
824 |
length = content_length |
|
825 |
elif length != content_length: |
|
826 |
raise BadRequest('Content length does not match range length') |
|
807 | 827 |
if total is not None and (total != size or offset >= size or (length > 0 and offset + length >= size)): |
808 | 828 |
raise RangeNotSatisfiable('Supplied range will change provided object limits') |
809 | 829 |
|
810 |
sock = raw_input_socket(request) |
|
811 |
data = '' |
|
812 |
for d in socket_read_iterator(sock, length, backend.block_size): |
|
813 |
# TODO: Raise 408 (Request Timeout) if this takes too long. |
|
814 |
# TODO: Raise 499 (Client Disconnect) if a length is defined and we stop before getting this much data. |
|
815 |
data += d |
|
816 |
bytes = put_object_block(hashmap, data, offset) |
|
817 |
offset += bytes |
|
818 |
data = data[bytes:] |
|
819 |
if len(data) > 0: |
|
820 |
put_object_block(hashmap, data, offset) |
|
830 |
if src_object: |
|
831 |
if offset % backend.block_size == 0: |
|
832 |
# Update the hashes only. |
|
833 |
sbi = 0 |
|
834 |
while length > 0: |
|
835 |
bi = int(offset / backend.block_size) |
|
836 |
bl = min(length, backend.block_size) |
|
837 |
if bi < len(hashmap): |
|
838 |
if bl == backend.block_size: |
|
839 |
hashmap[bi] = src_hashmap[sbi] |
|
840 |
else: |
|
841 |
data = backend.get_block(src_hashmap[sbi]) |
|
842 |
hashmap[bi] = backend.update_block(hashmap[bi], data[:bl], 0) |
|
843 |
else: |
|
844 |
hashmap.append(src_hashmap[sbi]) |
|
845 |
offset += bl |
|
846 |
length -= bl |
|
847 |
sbi += 1 |
|
848 |
else: |
|
849 |
data = '' |
|
850 |
sbi = 0 |
|
851 |
while length > 0: |
|
852 |
data += backend.get_block(src_hashmap[sbi]) |
|
853 |
if length < backend.block_size: |
|
854 |
data = data[:length] |
|
855 |
bytes = put_object_block(hashmap, data, offset) |
|
856 |
offset += bytes |
|
857 |
data = data[bytes:] |
|
858 |
length -= bytes |
|
859 |
sbi += 1 |
|
860 |
else: |
|
861 |
sock = raw_input_socket(request) |
|
862 |
data = '' |
|
863 |
for d in socket_read_iterator(sock, length, backend.block_size): |
|
864 |
# TODO: Raise 408 (Request Timeout) if this takes too long. |
|
865 |
# TODO: Raise 499 (Client Disconnect) if a length is defined and we stop before getting this much data. |
|
866 |
data += d |
|
867 |
bytes = put_object_block(hashmap, data, offset) |
|
868 |
offset += bytes |
|
869 |
data = data[bytes:] |
|
870 |
if len(data) > 0: |
|
871 |
put_object_block(hashmap, data, offset) |
|
821 | 872 |
|
822 | 873 |
if offset > size: |
823 | 874 |
size = offset |
Also available in: Unified diff