Beispiel #1
0
    def GETorHEAD(self, env, start_response):
        if env['REQUEST_METHOD'] == 'HEAD':
            head = True
            env['REQUEST_METHOD'] = 'GET'
        else:
            head = False
        if 'QUERY_STRING' in env:
            args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1))
        else:
            args = {}

        # Let s3multi handle it.
        if 'uploadId' in args:
            return self.app(env, start_response)

        env['QUERY_STRING'] = ''
        if 'acl' in args:
            env['QUERY_STRING'] += 'acl'
            env['REQUEST_METHOD'] = 'HEAD'
        if 'versionId' in args:
            env['QUERY_STRING'] += 'versionId=%s' % args['versionId']

        app_iter = self._app_call(env)

        if head:
            app_iter = None

        if 'acl' in args and not head:
            env['REQUEST_METHOD'] = 'GET'  # recover HTTP method

        status = self._get_status_int()
        headers = dict(self._response_headers)

        if is_success(status):
            if 'QUERY_STRING' in env:
                args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1))
            else:
                args = {}
            if 'acl' in args:
                resp = get_s3_acl(headers, obj_server.ACL_HEADERS, 'object')
                return resp

            new_hdrs = {}
            for key, val in headers.iteritems():
                _key = key.lower()
                if _key.startswith('x-object-meta-'):
                    new_hdrs['x-amz-meta-' + key[14:]] = val
                elif _key in ('content-length', 'content-type',
                              'content-range', 'content-encoding',
                              'etag', 'last-modified'):
                    new_hdrs[key] = val
            return Response(status=status, headers=new_hdrs, app_iter=app_iter)
        elif status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN):
            return get_err_response('AccessDenied')
        elif status == HTTP_NOT_FOUND:
            return get_err_response('NoSuchKey')
        else:
            return get_err_response('InvalidURI')
Beispiel #2
0
    def GET(self, env, start_response):
        """
        Handle GET Bucket (List Objects) request
        """
        if 'QUERY_STRING' in env:
            args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1))
        else:
            args = {}

        if 'max-keys' in args:
            if args.get('max-keys').isdigit() is False:
                return get_err_response('InvalidArgument')

        max_keys = min(int(args.get('max-keys', MAX_BUCKET_LISTING)),
                       MAX_BUCKET_LISTING)

        if 'acl' in args:
            env['REQUEST_METHOD'] = 'HEAD'
        else:
            # acl request sent with format=json etc confuses swift
            env['QUERY_STRING'] = 'format=json&limit=%s' % (max_keys + 1)
        if 'versions' in args:
            env['QUERY_STRING'] += '&versions'
        if 'marker' in args:
            env['QUERY_STRING'] += '&marker=%s' % quote(args['marker'])
        if 'prefix' in args:
            env['QUERY_STRING'] += '&prefix=%s' % quote(args['prefix'])
        if 'delimiter' in args:
            env['QUERY_STRING'] += '&delimiter=%s' % quote(args['delimiter'])

        body_iter = self._app_call(env)
        status = self._get_status_int()
        headers = dict(self._response_headers)

        if 'acl' in args:
            env['REQUEST_METHOD'] = 'GET'  # recover HTTP method

        if is_success(status) and 'acl' in args:
            return get_s3_acl(headers, container_server.ACL_HEADERS,
                              'container')

        if status != HTTP_OK:
            if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN):
                return get_err_response('AccessDenied')
            elif status == HTTP_NOT_FOUND:
                return get_err_response('NoSuchBucket')
            else:
                return get_err_response('InvalidURI')

        if 'location' in args:
            body = ('<?xml version="1.0" encoding="UTF-8"?>'
                    '<LocationConstraint '
                    'xmlns="http://s3.amazonaws.com/doc/2006-03-01/"')
            if self.location == 'US':
                body += '/>'
            else:
                body += ('>%s</LocationConstraint>' % self.location)
            return Response(body=body, content_type='application/xml')

        if 'versioning' in args:
            vers = self._response_header_value('x-container-versioning') or ''
            body = (
                '<VersioningConfiguration '
                'xmlns="http://s3.amazonaws.com/doc/2006-03-01/">'
                '<Status>%s</Status></VersioningConfiguration>' %
                vers.capitalize())
            return Response(body=body, content_type='application/xml')

        if 'logging' in args:
            # logging disabled
            body = ('<?xml version="1.0" encoding="UTF-8"?>'
                    '<BucketLoggingStatus '
                    'xmlns="http://doc.s3.amazonaws.com/2006-03-01" />')
            return Response(body=body, content_type='application/xml')

        objects = loads(''.join(list(body_iter)))
        if 'versions' in args:
            obj_list = []
            for obj in objects:
                if 'subdir' not in obj:
                    if obj['deleted']:
                        name = xml_escape(unquote(obj['name'].encode('utf-8')))
                        obj_list.append(
                            '<DeleteMarker>'
                            '<Key>%s</Key>'
                            '<VersionId>%s</VersionId>'
                            '<IsLatest>%s</IsLatest>'
                            '<LastModified>%s</LastModified>'
                            '</DeleteMarker>' % (
                                name, obj['version_id'],
                                'true' if obj['is_latest'] else 'false',
                                obj['last_modified']))
                    else:
                        name = xml_escape(unquote(obj['name'].encode('utf-8')))
                        obj_list.append(
                            '<Version>'
                            '<Key>%s</Key>'
                            '<VersionId>%s</VersionId>'
                            '<IsLatest>%s</IsLatest>'
                            '<LastModified>%s</LastModified>'
                            '<ETag>&quot;%s&quot;</ETag>'
                            '<Size>%s</Size>'
                            '<StorageClass>STANDARD</StorageClass>'
                            '<Owner>'
                            '<ID>%s</ID>'
                            '<DisplayName>%s</DisplayName>'
                            '</Owner>'
                            '</Version>' % (
                                name, obj['version_id'],
                                'true' if obj['is_latest'] else 'false',
                                obj['last_modified'], obj['hash'],
                                obj['bytes'], obj['owner'], obj['owner']))
            body = ('<?xml version="1.0" encoding="UTF-8"?>'
                    '<ListVersionsResult '
                    'xmlns="http://s3.amazonaws.com/doc/2006-03-01">'
                    '<Prefix>%s</Prefix>'
                    '<KeyMarker>%s</KeyMarker>'
                    '<VersionIdMarker>%s</VersionIdMarker>'
                    '<Delimiter>%s</Delimiter>'
                    '<IsTruncated>%s</IsTruncated>'
                    '<MaxKeys>%s</MaxKeys>'
                    '<Name>%s</Name>'
                    '%s'
                    '%s'
                    '</ListVersionsResult>' % (
                    xml_escape(args.get('prefix', '')),
                    xml_escape(args.get('key-marker', '')),
                    xml_escape(args.get('version-id-marker', '')),
                    xml_escape(args.get('delimiter', '')),
                    'true' if len(objects) == (max_keys + 1) else 'false',
                    max_keys,
                    xml_escape(self.container_name),
                    "".join(obj_list),
                    "".join([
                        '<CommonPrefixes><Prefix>%s</Prefix></CommonPrefixes>'
                        % xml_escape(i['subdir'])
                        for i in objects[:max_keys] if 'subdir' in i])))
        else:
            obj_list = []
            prefixes = []
            for i in objects:
                if 'subdir' in i:
                    name = xml_escape(unquote(i['subdir'].encode('utf-8')))
                    prefixes.append('<CommonPrefixes>'
                                    '<Prefix>%s</Prefix>'
                                    '</CommonPrefixes>' % name)
                else:
                    name = xml_escape(unquote(i['name'].encode('utf-8')))
                    owner = i.get('owner', self.account_name)
                    obj_list.append(
                        '<Contents>'
                        '<Key>%s</Key>'
                        '<LastModified>%sZ</LastModified>'
                        '<ETag>%s</ETag>'
                        '<Size>%s</Size>'
                        '<StorageClass>STANDARD</StorageClass>'
                        '<Owner>'
                        '<ID>%s</ID>'
                        '<DisplayName>%s</DisplayName>'
                        '</Owner>'
                        '</Contents>' %
                        (name, i['last_modified'], i['hash'], i['bytes'],
                         owner, owner))
            body = ('<?xml version="1.0" encoding="UTF-8"?>'
                    '<ListBucketResult '
                    'xmlns="http://s3.amazonaws.com/doc/2006-03-01">'
                    '<Prefix>%s</Prefix>'
                    '<Marker>%s</Marker>'
                    '<Delimiter>%s</Delimiter>'
                    '<IsTruncated>%s</IsTruncated>'
                    '<MaxKeys>%s</MaxKeys>'
                    '<Name>%s</Name>'
                    '%s'
                    '%s'
                    '</ListBucketResult>' % (
                    xml_escape(args.get('prefix', '')),
                    xml_escape(args.get('marker', '')),
                    xml_escape(args.get('delimiter', '')),
                    'true' if (max_keys > 0 and
                               len(objects) == (max_keys + 1)) else 'false',
                    max_keys,
                    xml_escape(self.container_name),
                    ''.join(obj_list),
                    ''.join(prefixes)))
        return Response(body=body, content_type='application/xml')