a932a022319e3367e03f253dbd4ef1f136f9e8db
[pithos] / pithos / api / public.py
1 # Copyright 2011 GRNET S.A. All rights reserved.
2
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
5 # conditions are met:
6
7 #   1. Redistributions of source code must retain the above
8 #      copyright notice, this list of conditions and the following
9 #      disclaimer.
10
11 #   2. Redistributions in binary form must reproduce the above
12 #      copyright notice, this list of conditions and the following
13 #      disclaimer in the documentation and/or other materials
14 #      provided with the distribution.
15
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
28
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
33
34 import logging
35
36 from django.http import HttpResponse
37
38 from pithos.api.faults import (Fault, BadRequest, ItemNotFound)
39 from pithos.api.util import (put_object_headers, update_manifest_meta,
40     validate_modification_preconditions, validate_matching_preconditions,
41     object_data_response, api_method)
42 from pithos.api.short_url import decode_url
43
44
45 logger = logging.getLogger(__name__)
46
47
48 def public_demux(request, v_public):
49     if request.method == 'HEAD':
50         return public_meta(request, v_public)
51     elif request.method == 'GET':
52         return public_read(request, v_public)
53     else:
54         return method_not_allowed(request)
55
56 @api_method('HEAD', user_required=False)
57 def public_meta(request, v_public):
58     # Normal Response Codes: 204
59     # Error Response Codes: serviceUnavailable (503),
60     #                       itemNotFound (404),
61     #                       badRequest (400)
62     
63     try:
64         v_account, v_container, v_object = request.backend.get_public(request.user_uniq,
65                                                     decode_url(v_public))
66         meta = request.backend.get_object_meta(request.user_uniq, v_account,
67                                                     v_container, v_object, 'pithos')
68         public = request.backend.get_object_public(request.user_uniq, v_account,
69                                                     v_container, v_object)
70     except:
71         raise ItemNotFound('Object does not exist')
72     
73     if not public:
74         raise ItemNotFound('Object does not exist')
75     update_manifest_meta(request, v_account, meta)
76     
77     response = HttpResponse(status=200)
78     put_object_headers(response, meta, True)
79     return response
80
81 @api_method('GET', user_required=False)
82 def public_read(request, v_public):
83     # Normal Response Codes: 200, 206
84     # Error Response Codes: serviceUnavailable (503),
85     #                       rangeNotSatisfiable (416),
86     #                       preconditionFailed (412),
87     #                       itemNotFound (404),
88     #                       badRequest (400),
89     #                       notModified (304)
90     
91     try:
92         v_account, v_container, v_object = request.backend.get_public(request.user_uniq,
93                                                     decode_url(v_public))
94         meta = request.backend.get_object_meta(request.user_uniq, v_account,
95                                                     v_container, v_object, 'pithos')
96         public = request.backend.get_object_public(request.user_uniq, v_account,
97                                                     v_container, v_object)
98     except:
99         raise ItemNotFound('Object does not exist')
100     
101     if not public:
102         raise ItemNotFound('Object does not exist')
103     update_manifest_meta(request, v_account, meta)
104     
105     # Evaluate conditions.
106     validate_modification_preconditions(request, meta)
107     try:
108         validate_matching_preconditions(request, meta)
109     except NotModified:
110         response = HttpResponse(status=304)
111         response['ETag'] = meta['ETag']
112         return response
113     
114     sizes = []
115     hashmaps = []
116     if 'X-Object-Manifest' in meta:
117         try:
118             src_container, src_name = split_container_object_string('/' + meta['X-Object-Manifest'])
119             objects = request.backend.list_objects(request.user_uniq, v_account,
120                                 src_container, prefix=src_name, virtual=False)
121         except:
122             raise ItemNotFound('Object does not exist')
123         
124         try:
125             for x in objects:
126                 s, h = request.backend.get_object_hashmap(request.user_uniq,
127                                         v_account, src_container, x[0], x[1])
128                 sizes.append(s)
129                 hashmaps.append(h)
130         except:
131             raise ItemNotFound('Object does not exist')
132     else:
133         try:
134             s, h = request.backend.get_object_hashmap(request.user_uniq, v_account,
135                                                         v_container, v_object)
136             sizes.append(s)
137             hashmaps.append(h)
138         except:
139             raise ItemNotFound('Object does not exist')
140     
141     if 'Content-Disposition' not in meta:
142         name = v_object.rstrip('/').split('/')[-1]
143         if not name:
144             name = v_public
145         meta['Content-Disposition'] = 'attachment; filename=%s' % (name,)
146     
147     return object_data_response(request, sizes, hashmaps, meta, True)
148
149 @api_method(user_required=False)
150 def method_not_allowed(request, **v_args):
151     raise ItemNotFound('Object does not exist')