Revision 02c0c3fa pithos/api/util.py
b/pithos/api/util.py | ||
---|---|---|
42 | 42 |
from django.utils.http import http_date, parse_etags |
43 | 43 |
|
44 | 44 |
from pithos.api.compat import parse_http_date_safe |
45 |
from pithos.api.faults import (Fault, NotModified, BadRequest, ItemNotFound, LengthRequired, |
|
46 |
PreconditionFailed, RangeNotSatisfiable, ServiceUnavailable) |
|
45 |
from pithos.api.faults import (Fault, NotModified, BadRequest, Unauthorized, ItemNotFound, |
|
46 |
LengthRequired, PreconditionFailed, RangeNotSatisfiable, |
|
47 |
ServiceUnavailable) |
|
47 | 48 |
from pithos.backends import backend |
48 | 49 |
from pithos.backends.base import NotAllowedError |
49 | 50 |
|
... | ... | |
57 | 58 |
logger = logging.getLogger(__name__) |
58 | 59 |
|
59 | 60 |
|
60 |
def printable_meta_dict(d):
|
|
61 |
def printable_header_dict(d):
|
|
61 | 62 |
"""Format a meta dictionary for printing out json/xml. |
62 | 63 |
|
63 | 64 |
Convert all keys to lower case and replace dashes to underscores. |
... | ... | |
69 | 70 |
del(d['modified']) |
70 | 71 |
return dict([(k.lower().replace('-', '_'), v) for k, v in d.iteritems()]) |
71 | 72 |
|
72 |
def format_meta_key(k):
|
|
73 |
def format_header_key(k):
|
|
73 | 74 |
"""Convert underscores to dashes and capitalize intra-dash strings.""" |
74 | 75 |
|
75 | 76 |
return '-'.join([x.capitalize() for x in k.replace('_', '-').split('-')]) |
76 | 77 |
|
77 |
def get_meta_prefix(request, prefix):
|
|
78 |
"""Get all prefix-* request headers in a dict. Reformat keys with format_meta_key()."""
|
|
78 |
def get_header_prefix(request, prefix):
|
|
79 |
"""Get all prefix-* request headers in a dict. Reformat keys with format_header_key()."""
|
|
79 | 80 |
|
80 | 81 |
prefix = 'HTTP_' + prefix.upper().replace('-', '_') |
81 |
return dict([(format_meta_key(k[5:]), v) for k, v in request.META.iteritems() if k.startswith(prefix) and len(k) > len(prefix)]) |
|
82 |
|
|
83 |
def get_account_meta(request): |
|
84 |
"""Get metadata from an account request.""" |
|
85 |
|
|
86 |
meta = get_meta_prefix(request, 'X-Account-Meta-') |
|
87 |
return meta |
|
88 |
|
|
89 |
def put_account_meta(response, meta): |
|
90 |
"""Put metadata in an account response.""" |
|
91 |
|
|
82 |
return dict([(format_header_key(k[5:]), v.replace('_', '')) for k, v in request.META.iteritems() if k.startswith(prefix) and len(k) > len(prefix)]) |
|
83 |
|
|
84 |
def get_account_headers(request): |
|
85 |
meta = get_header_prefix(request, 'X-Account-Meta-') |
|
86 |
groups = {} |
|
87 |
for k, v in get_header_prefix(request, 'X-Account-Group-').iteritems(): |
|
88 |
n = k[16:].lower() |
|
89 |
if '-' in n or '_' in n: |
|
90 |
raise BadRequest('Bad characters in group name') |
|
91 |
groups[n] = v.replace(' ', '').split(',') |
|
92 |
if '' in groups[n]: |
|
93 |
groups[n].remove('') |
|
94 |
return meta, groups |
|
95 |
|
|
96 |
def put_account_headers(response, meta, groups): |
|
92 | 97 |
response['X-Account-Container-Count'] = meta['count'] |
93 | 98 |
response['X-Account-Bytes-Used'] = meta['bytes'] |
94 | 99 |
if 'modified' in meta: |
... | ... | |
97 | 102 |
response[k.encode('utf-8')] = meta[k].encode('utf-8') |
98 | 103 |
if 'until_timestamp' in meta: |
99 | 104 |
response['X-Account-Until-Timestamp'] = http_date(int(meta['until_timestamp'])) |
105 |
for k, v in groups.iteritems(): |
|
106 |
response[format_header_key('X-Account-Group-' + k).encode('utf-8')] = (','.join(v)).encode('utf-8') |
|
100 | 107 |
|
101 |
def get_container_meta(request): |
|
102 |
"""Get metadata from a container request.""" |
|
103 |
|
|
104 |
meta = get_meta_prefix(request, 'X-Container-Meta-') |
|
108 |
def get_container_headers(request): |
|
109 |
meta = get_header_prefix(request, 'X-Container-Meta-') |
|
105 | 110 |
return meta |
106 | 111 |
|
107 |
def put_container_meta(response, meta): |
|
108 |
"""Put metadata in a container response.""" |
|
109 |
|
|
112 |
def put_container_headers(response, meta): |
|
110 | 113 |
response['X-Container-Object-Count'] = meta['count'] |
111 | 114 |
response['X-Container-Bytes-Used'] = meta['bytes'] |
112 | 115 |
response['Last-Modified'] = http_date(int(meta['modified'])) |
... | ... | |
118 | 121 |
if 'until_timestamp' in meta: |
119 | 122 |
response['X-Container-Until-Timestamp'] = http_date(int(meta['until_timestamp'])) |
120 | 123 |
|
121 |
def get_object_meta(request): |
|
122 |
"""Get metadata from an object request.""" |
|
123 |
|
|
124 |
meta = get_meta_prefix(request, 'X-Object-Meta-') |
|
124 |
def get_object_headers(request): |
|
125 |
meta = get_header_prefix(request, 'X-Object-Meta-') |
|
125 | 126 |
if request.META.get('CONTENT_TYPE'): |
126 | 127 |
meta['Content-Type'] = request.META['CONTENT_TYPE'] |
127 | 128 |
if request.META.get('HTTP_CONTENT_ENCODING'): |
... | ... | |
132 | 133 |
meta['X-Object-Manifest'] = request.META['HTTP_X_OBJECT_MANIFEST'] |
133 | 134 |
return meta |
134 | 135 |
|
135 |
def put_object_meta(response, meta, public=False): |
|
136 |
"""Put metadata in an object response.""" |
|
137 |
|
|
136 |
def put_object_headers(response, meta, public=False): |
|
138 | 137 |
response['ETag'] = meta['hash'] |
139 | 138 |
response['Content-Length'] = meta['bytes'] |
140 | 139 |
response['Content-Type'] = meta.get('Content-Type', 'application/octet-stream') |
... | ... | |
237 | 236 |
def copy_or_move_object(request, v_account, src_container, src_name, dest_container, dest_name, move=False): |
238 | 237 |
"""Copy or move an object.""" |
239 | 238 |
|
240 |
meta = get_object_meta(request)
|
|
239 |
meta = get_object_headers(request)
|
|
241 | 240 |
permissions = get_sharing(request) |
242 | 241 |
src_version = request.META.get('HTTP_X_SOURCE_VERSION') |
243 | 242 |
try: |
... | ... | |
370 | 369 |
return ret |
371 | 370 |
for perm in (x for x in permissions.split(';')): |
372 | 371 |
if perm.startswith('read='): |
373 |
ret['read'] = [v.replace(' ','') for v in perm[5:].split(',')] |
|
374 |
ret['read'].remove('') |
|
372 |
ret['read'] = [v.replace(' ','').lower() for v in perm[5:].split(',')] |
|
373 |
if '' in ret['read']: |
|
374 |
ret['read'].remove('') |
|
375 | 375 |
if '*' in ret['read']: |
376 | 376 |
ret['read'] = ['*'] |
377 | 377 |
if len(ret['read']) == 0: |
378 | 378 |
raise BadRequest('Bad X-Object-Sharing header value') |
379 | 379 |
elif perm.startswith('write='): |
380 |
ret['write'] = [v.replace(' ','') for v in perm[6:].split(',')] |
|
381 |
ret['write'].remove('') |
|
380 |
ret['write'] = [v.replace(' ','').lower() for v in perm[6:].split(',')] |
|
381 |
if '' in ret['write']: |
|
382 |
ret['write'].remove('') |
|
382 | 383 |
if '*' in ret['write']: |
383 | 384 |
ret['write'] = ['*'] |
384 | 385 |
if len(ret['write']) == 0: |
... | ... | |
562 | 563 |
boundary = '' |
563 | 564 |
wrapper = ObjectWrapper(ranges, sizes, hashmaps, boundary) |
564 | 565 |
response = HttpResponse(wrapper, status=ret) |
565 |
put_object_meta(response, meta, public)
|
|
566 |
put_object_headers(response, meta, public)
|
|
566 | 567 |
if ret == 206: |
567 | 568 |
if len(ranges) == 1: |
568 | 569 |
offset, length = ranges[0] |
Also available in: Unified diff