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.')
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
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)
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
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
def PUT(self, req): """ Handles PUT Bucket logging. """ raise OssNotImplemented()
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)
def POST(self, req): raise OssNotImplemented()
def POST(self, req): """ Handle POST Bucket request """ raise OssNotImplemented()
def __init__(self, app, **kwargs): raise OssNotImplemented('The requested resource is not implemented')