Beispiel #1
0
    def _validate_headers(self):
        if 'CONTENT_LENGTH' in self.environ:
            try:
                if self.content_length < 0:
                    raise InvalidArgument('Content-Length',
                                          self.content_length)
            except (ValueError, TypeError):
                raise InvalidArgument('Content-Length',
                                      self.environ['CONTENT_LENGTH'])

        self._validate_dates()

        if 'Content-MD5' in self.headers:
            value = self.headers['Content-MD5']
            if not re.match('^[A-Za-z0-9+/]+={0,2}$', value):
                # Non-base64-alphabet characters in value.
                raise InvalidDigest(content_md5=value)
            try:
                self.headers['ETag'] = value.decode('base64').encode('hex')
            except Exception:
                raise InvalidDigest(content_md5=value)

            if len(self.headers['ETag']) != 32:
                raise InvalidDigest(content_md5=value)

        if self.method == 'PUT' and any(
                h in self.headers
                for h in ('If-Match', 'If-None-Match', 'If-Modified-Since',
                          'If-Unmodified-Since')):
            raise OssNotImplemented(
                'Conditional object PUTs are not supported.')

        if 'X-Oss-Copy-Source' in self.headers:
            try:
                check_path_header(self, 'X-Oss-Copy-Source', 2, '')
            except swob.HTTPException:
                msg = 'Copy Source must mention the source bucket and key: ' \
                      'sourcebucket/sourcekey'
                raise InvalidArgument('x-oss-copy-source',
                                      self.headers['X-Oss-Copy-Source'], msg)

        if 'x-oss-metadata-directive' in self.headers:
            value = self.headers['x-oss-metadata-directive']
            if value not in ('COPY', 'REPLACE'):
                err_msg = 'Unknown metadata directive.'
                raise InvalidArgument('x-oss-metadata-directive', value,
                                      err_msg)

        if 'x-oss-storage-class' in self.headers:
            # Only STANDARD is supported now.
            if self.headers['x-oss-storage-class'] != 'STANDARD':
                raise InvalidStorageClass()

        if 'x-oss-mfa' in self.headers:
            raise OssNotImplemented('MFA Delete is not supported.')

        if 'x-oss-server-side-encryption' in self.headers:
            raise OssNotImplemented('Server-side encryption is not supported.')
Beispiel #2
0
    def PUT(self, req):
        """
        Handles PUT Bucket acl and PUT Object acl.
        """
        if req.is_object_request:
            # Handle Object ACL
            raise OssNotImplemented()
        else:
            # Handle Bucket ACL
            xml = req.xml(MAX_ACL_BODY_SIZE)
            if 'HTTP_X_OSS_ACL' in req.environ and xml:
                # Oss doesn't allow to give ACL with both ACL header and body.
                raise UnexpectedContent()
            elif xml and 'HTTP_X_OSS_ACL' not in req.environ:
                # We very likely have an XML-based ACL request.
                try:
                    translated_acl = swift_acl_translate(xml, xml=True)
                except ACLError:
                    raise MalformedACLError()

                for header, acl in translated_acl:
                    req.headers[header] = acl

            resp = req.get_response(self.app, 'POST')
            resp.status = HTTP_OK
            resp.headers.update({'Location': req.container_name})

            return resp
Beispiel #3
0
    def _gen_error_body(self, error, elem, delete_list):
        for key, version in delete_list:
            if version is not None:
                # TODO: delete the specific version of the object
                raise OssNotImplemented()

            error_elem = SubElement(elem, 'Error')
            SubElement(error_elem, 'Key').text = key
            SubElement(error_elem, 'Code').text = error.__class__.__name__
            SubElement(error_elem, 'Message').text = error._msg

        return tostring(elem)
Beispiel #4
0
    def controller(self):
        if self.is_service_request:
            return ServiceController

        if not self.slo_enabled:
            multi_part = ['partNumber', 'uploadId', 'uploads']
            if len([p for p in multi_part if p in self.params]):
                LOGGER.warning('multipart: No SLO middleware in pipeline')
                raise OssNotImplemented("Multi-part feature isn't support")
        # if 'objectMeta' in self.params:
        #     return ObjectController
        if 'acl' in self.params:
            return AclController
        if 'cors' in self.params:
            return CorsController
        if 'delete' in self.params:
            return MultiObjectDeleteController
        if 'location' in self.params:
            return LocationController
        if 'logging' in self.params:
            return LoggingStatusController
        if 'partNumber' in self.params:
            return PartController
        if 'uploadId' in self.params:
            return UploadController
        if 'uploads' in self.params:
            return UploadsController
        if 'versioning' in self.params:
            return VersioningController
        if 'lifecycle' in self.params:
            return LifecycleController
        if 'website' in self.params:
            return WebsiteController
        if 'referer' in self.params:
            return RefererController

        unsupported = ('notification', 'policy', 'requestPayment', 'torrent',
                       'tagging', 'restore')
        if set(unsupported) & set(self.params):
            return UnsupportedController

        if self.is_object_request:
            return ObjectController
        return BucketController
Beispiel #5
0
    def xml(self, max_length, check_md5=False):
        """
        Similar to swob.Request.body, but it checks the content length before
        creating a body string.
        """
        te = self.headers.get('transfer-encoding', '')
        te = [x.strip() for x in te.split(',') if x.strip()]
        if te and (len(te) > 1 or te[-1] != 'chunked'):
            raise OssNotImplemented(
                'A header you provided implies '
                'functionality that is not implemented',
                header='Transfer-Encoding')

        if self.message_length() > max_length:
            raise MalformedXML()

        # Limit the read similar to how SLO handles manifests
        body = self.body_file.read(max_length)

        if check_md5:
            self.check_md5(body)

        return body
Beispiel #6
0
 def PUT(self, req):
     """
     Handles PUT Bucket logging.
     """
     raise OssNotImplemented()
Beispiel #7
0
    def POST(self, req):
        """
        Handles Delete Multiple Objects.
        """
        def object_key_iter(elem):
            for obj in elem.iterchildren('Object'):
                key = obj.find('./Key').text
                if not key:
                    raise UserKeyMustBeSpecified()
                version = obj.find('./VersionId')
                if version is not None:
                    version = version.text

                yield key, version

        try:
            xml = req.xml(MAX_MULTI_DELETE_BODY_SIZE, check_md5=True)
            elem = fromstring(xml, 'Delete')

            quiet = elem.find('./Quiet')
            if quiet is not None and quiet.text.lower() == 'true':
                self.quiet = True
            else:
                self.quiet = False

            delete_list = list(object_key_iter(elem))
            if len(delete_list) > CONF.max_multi_delete_objects:
                raise MalformedXML()
        except (XMLSyntaxError, DocumentInvalid):
            raise MalformedXML()
        except ErrorResponse:
            raise
        except Exception as e:
            exc_type, exc_value, exc_traceback = sys.exc_info()
            LOGGER.error(e)
            raise exc_type, exc_value, exc_traceback

        elem = Element('DeleteResult')

        # check bucket existence
        try:
            req.get_response(self.app, 'HEAD')
        except AccessDenied as error:
            body = self._gen_error_body(error, elem, delete_list)
            return HTTPOk(body=body)

        for key, version in delete_list:
            if version is not None:
                # TODO: delete the specific version of the object
                raise OssNotImplemented()

            req.object_name = key

            try:
                query = req.gen_multipart_manifest_delete_query(self.app)
                req.get_response(self.app, method='DELETE', query=query)
            except NoSuchKey:
                pass
            except ErrorResponse as e:
                error = SubElement(elem, 'Error')
                SubElement(error, 'Key').text = key
                SubElement(error, 'Code').text = e.__class__.__name__
                SubElement(error, 'Message').text = e._msg
                continue

            if not self.quiet:
                deleted = SubElement(elem, 'Deleted')
                SubElement(deleted, 'Key').text = key

        body = tostring(elem)

        return HTTPOk(body=body)
Beispiel #8
0
 def POST(self, req):
     raise OssNotImplemented()
Beispiel #9
0
 def POST(self, req):
     """
     Handle POST Bucket request
     """
     raise OssNotImplemented()
Beispiel #10
0
 def __init__(self, app, **kwargs):
     raise OssNotImplemented('The requested resource is not implemented')