Revision 9fefc052
b/pithos/api/util.py | ||
---|---|---|
37 | 37 |
from wsgiref.handlers import format_date_time |
38 | 38 |
from binascii import hexlify, unhexlify |
39 | 39 |
from datetime import datetime, tzinfo, timedelta |
40 |
from urllib import quote, unquote |
|
40 | 41 |
|
41 | 42 |
from django.conf import settings |
42 | 43 |
from django.http import HttpResponse |
... | ... | |
758 | 759 |
h = [subhash(h[x] + h[x + 1]) for x in range(0, len(h), 2)] |
759 | 760 |
return hexlify(h[0]) |
760 | 761 |
|
762 |
def update_request_headers(request): |
|
763 |
# Handle URL-encoded keys and values. |
|
764 |
meta = request.META |
|
765 |
for k, v in meta.copy().iteritems(): |
|
766 |
if ((k.startswith('HTTP_X_ACCOUNT_META_') or k.startswith('HTTP_X_ACCOUNT_GROUP_') or |
|
767 |
k.startswith('HTTP_X_CONTAINER_META_') or k.startswith('HTTP_X_OBJECT_META_') or |
|
768 |
k in ('HTTP_X_OBJECT_MANIFEST', 'HTTP_X_OBJECT_SHARING', |
|
769 |
'HTTP_X_COPY_FROM', 'HTTP_X_MOVE_FROM', |
|
770 |
'HTTP_X_SOURCE_ACCOUNT', 'HTTP_X_SOURCE_OBJECT', |
|
771 |
'HTTP_DESTINATION_ACCOUNT', 'HTTP_DESTINATION')) and |
|
772 |
('%' in k or '%' in v)): |
|
773 |
del(meta[k]) |
|
774 |
meta[unquote(k)] = unquote(v) |
|
775 |
|
|
761 | 776 |
def update_response_headers(request, response): |
762 | 777 |
if request.serialization == 'xml': |
763 | 778 |
response['Content-Type'] = 'application/xml; charset=UTF-8' |
... | ... | |
766 | 781 |
elif not response['Content-Type']: |
767 | 782 |
response['Content-Type'] = 'text/plain; charset=UTF-8' |
768 | 783 |
|
769 |
if not response.has_header('Content-Length') and not (response.has_header('Content-Type') and response['Content-Type'].startswith('multipart/byteranges')): |
|
784 |
if (not response.has_header('Content-Length') and |
|
785 |
not (response.has_header('Content-Type') and |
|
786 |
response['Content-Type'].startswith('multipart/byteranges'))): |
|
770 | 787 |
response['Content-Length'] = len(response.content) |
771 | 788 |
|
789 |
# URL-encode unicode in headers. |
|
790 |
meta = response.items() |
|
791 |
for k, v in meta: |
|
792 |
if (k.startswith('X-Account-Meta-') or k.startswith('X-Account-Group-') or |
|
793 |
k.startswith('X-Container-Meta-') or k.startswith('X-Object-Meta-') or |
|
794 |
k in ('X-Container-Object-Meta', 'X-Object-Manifest', 'X-Object-Sharing', 'X-Object-Shared-By')): |
|
795 |
del(response[k]) |
|
796 |
response[quote(k)] = quote(v) |
|
797 |
|
|
772 | 798 |
if settings.TEST: |
773 | 799 |
response['Date'] = format_date_time(time()) |
774 | 800 |
|
... | ... | |
824 | 850 |
if len(args) > 2 and len(args[2]) > 1024: |
825 | 851 |
raise BadRequest('Object name too large.') |
826 | 852 |
|
853 |
# Format and check headers. |
|
854 |
update_request_headers(request) |
|
855 |
meta = dict([(k, v) for k, v in request.META.iteritems() if k.startswith('HTTP_')]) |
|
856 |
if len(meta) > 90: |
|
857 |
raise BadRequest('Too many headers.') |
|
858 |
for k, v in meta.iteritems(): |
|
859 |
if len(k) > 128: |
|
860 |
raise BadRequest('Header name too large.') |
|
861 |
if len(v) > 256: |
|
862 |
raise BadRequest('Header value too large.') |
|
863 |
|
|
827 | 864 |
# Fill in custom request variables. |
828 | 865 |
request.serialization = request_serialization(request, format_allowed) |
829 | 866 |
request.backend = connect_backend() |
b/pithos/middleware/__init__.py | ||
---|---|---|
1 | 1 |
from log import LoggingConfigMiddleware |
2 |
from header import URLEncodedHeadersMiddleware |
|
3 | 2 |
from auth import AuthMiddleware |
/dev/null | ||
---|---|---|
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 |
from urllib import unquote |
|
35 |
|
|
36 |
|
|
37 |
class URLEncodedHeadersMiddleware(object): |
|
38 |
def process_request(self, request): |
|
39 |
meta = request.META |
|
40 |
for k, v in meta.copy().iteritems(): |
|
41 |
if k.startswith('HTTP_') and ('%' in k or '%' in v): |
|
42 |
del(meta[k]) |
|
43 |
meta[unquote(k)] = unquote(v) |
b/pithos/settings.d/00-apps.conf | ||
---|---|---|
6 | 6 |
|
7 | 7 |
MIDDLEWARE_CLASSES = ( |
8 | 8 |
'django.middleware.common.CommonMiddleware', |
9 |
'pithos.middleware.URLEncodedHeadersMiddleware', |
|
10 | 9 |
'pithos.middleware.LoggingConfigMiddleware', |
11 | 10 |
'pithos.middleware.AuthMiddleware' |
12 | 11 |
) |
Also available in: Unified diff