Exemple #1
0
    def PUT(self, env, start_response):
        """
        Handle PUT Object and PUT Object (Copy) request
        """
        if 'QUERY_STRING' in env:
            args = dict(urlparse.parse_qsl(env['QUERY_STRING'], True))
        else:
            args = {}

        acl = 'acl' in args
        if acl:
            res = acp_to_headers(env, 'object')
            if res:
                return res
            env['QUERY_STRING'] = 'acl'
            env['REQUEST_METHOD'] = 'POST'
        else:
            for key, value in env.items():
                if key.startswith('HTTP_X_AMZ_META_'):
                    del env[key]
                    env['HTTP_X_OBJECT_META_' + key[16:]] = value
                elif key == 'HTTP_CONTENT_MD5':
                    if value == '':
                        return get_err_response('InvalidDigest')
                    try:
                        env['HTTP_ETAG'] = value.decode('base64').encode('hex')
                    except:
                        return get_err_response('InvalidDigest')
                    if env['HTTP_ETAG'] == '':
                        return get_err_response('SignatureDoesNotMatch')
                elif key == 'HTTP_X_AMZ_COPY_SOURCE':
                    env['HTTP_X_COPY_FROM'] = value

        body_iter = self._app_call(env)
        status = self._get_status_int()

        success_status = HTTP_ACCEPTED if acl else HTTP_CREATED

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

        if not acl and 'HTTP_X_COPY_FROM' in env:
            body = '<CopyObjectResult>' \
                   '<ETag>"%s"</ETag>' \
                   '</CopyObjectResult>' % self._response_header_value('etag')
            return Response(status=HTTP_OK, body=body)

        kwargs = {'status': HTTP_OK}
        if not acl:
            kwargs['etag'] = self._response_header_value('etag')

        return Response(**kwargs)
Exemple #2
0
    def PUT(self, env, start_response):
        """
        Handle PUT Bucket request
        """
        if 'CONTENT_LENGTH' in env:
            try:
                content_length = int(env['CONTENT_LENGTH'])
            except (ValueError, TypeError):
                return get_err_response('InvalidArgument')
            if content_length < 0:
                return get_err_response('InvalidArgument')

        if 'QUERY_STRING' in env:
            args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1))
        else:
            args = {}

        acl = 'acl' in args
        if acl:
            res = acp_to_headers(env, 'container')
            if res:
                return res
            env['REQUEST_METHOD'] = 'POST'

        versioning = 'versioning' in args
        if versioning:
            if 'wsgi.input' not in env:
                return get_err_response(
                    'IllegalVersioningConfigurationException')
            versioning_conf = env['wsgi.input'].read()
            if 'Enabled' in versioning_conf:
                env['HTTP_X_CONTAINER_VERSIONING'] = 'enabled'
            elif 'Suspended' in versioning_conf:
                env['HTTP_X_CONTAINER_VERSIONING'] = 'suspended'
            else:
                return get_err_response(
                    'IllegalVersioningConfigurationException')
            env['REQUEST_METHOD'] = 'POST'

        if not acl and not versioning:
            if 'HTTP_X_AMZ_ACL' in env:
                amz_acl = env['HTTP_X_AMZ_ACL']
                # Translate the Amazon ACL to something that can be
                # implemented in Swift, 501 otherwise. Swift uses POST
                # for ACLs, whereas S3 uses PUT.
                del env['HTTP_X_AMZ_ACL']
                if 'QUERY_STRING' in env:
                    del env['QUERY_STRING']

                translated_acl = swift_acl_translate(amz_acl)
                if translated_acl == 'Unsupported':
                    return get_err_response('Unsupported')
                elif translated_acl == 'InvalidArgument':
                    return get_err_response('InvalidArgument')

                for header, acl in translated_acl:
                    env[header] = acl

            if 'CONTENT_LENGTH' in env:
                content_length = env['CONTENT_LENGTH']
                try:
                    content_length = int(content_length)
                except (ValueError, TypeError):
                    return get_err_response('InvalidArgument')
                if content_length < 0:
                    return get_err_response('InvalidArgument')

            if 'QUERY_STRING' in env:
                args = dict(urlparse.parse_qsl(env['QUERY_STRING'], 1))
                if 'acl' in args:
                    # We very likely have an XML-based ACL request.
                    body = env['wsgi.input'].readline().decode()
                    translated_acl = swift_acl_translate(body, xml=True)
                    if translated_acl == 'Unsupported':
                        return get_err_response('Unsupported')
                    elif translated_acl == 'InvalidArgument':
                        return get_err_response('InvalidArgument')
                    for header, acl in translated_acl:
                        env[header] = acl
                    env['REQUEST_METHOD'] = 'POST'

        body_iter = self._app_call(env)
        status = self._get_status_int()

        if status != HTTP_CREATED and status != HTTP_NO_CONTENT:
            if status in (HTTP_UNAUTHORIZED, HTTP_FORBIDDEN):
                return get_err_response('AccessDenied')
            elif status == HTTP_ACCEPTED:
                return get_err_response('BucketAlreadyExists')
            else:
                return get_err_response('InvalidURI')

        resp = Response()
        if not versioning:
            resp.headers['Location'] = self.container_name
        resp.status = HTTP_OK
        return resp