def _handle_copy_put_from_swift3(self, req): if req.headers['X-Amz-Metadata-Directive'] != 'REPLACE': raise swob.HTTPNotImplemented( 'X-Amz-Metadata-Directive was not "REPLACE"; ' 'only object-overwrite copying is supported.') raw_path = urllib.unquote(req.environ['RAW_PATH_INFO']) copy_from = urllib.unquote(req.headers['x-copy-from']) if raw_path != copy_from: raise swob.HTTPNotImplemented( 'X-Amz-Copy-Source != object path; ' 'only object-overwrite copying is supported.') return self._provider_fn_with_fallback( 'post_object', self.object_name.decode('utf8'), req.headers)
def POST(self, req): # NOTE: obj metadata update via S3 API (`swift3` middleware) is # implemented in the PUT method. s3_key = self.local_to_me_provider.get_s3_name(self.object_name) if 'uploads' in req.params: # Multipart upload initiation return self._handle_create_multipart_upload(s3_key, req) elif 'uploadId' in req.params: # Multipart upload completion return self._handle_complete_multipart_upload(s3_key, req) return swob.HTTPNotImplemented()
def get_controller(self, req): # Maybe handle /info specially here, like our superclass' # get_controller() does? # Note: the only difference I can see between doing # "split_path(req.path, ...)" vs. req.split_path() is that req.path # will quote the path string with urllib.quote() prior to # splititng it. Unlike our superclass' similarly-named method, we're # going to leave the acct/cont/obj values UTF8-encoded and unquoted. ver, acct, cont, obj = req.split_path(1, 4, True) if not obj and not cont: # We've decided to not support any actions on accounts... raise swob.HTTPForbidden(body="Account operations are not " "supported.") if not obj and req.method not in ('GET', 'HEAD'): # We've decided to only support container listings (GET) raise swob.HTTPForbidden(body="The only supported container " "operations are GET and HEAD.") profile_key1, profile_key2 = (acct, cont), (acct, '/*') profile = self.sync_profiles.get( profile_key1, self.sync_profiles.get(profile_key2, None)) if not profile: self.logger.debug('No matching sync profile for %r or %r', profile_key1, profile_key2) raise swob.HTTPForbidden(body="No matching sync profile.") # Cook up a Provider "profile" here that can talk to the onprem Swift # cluster (the "profile" details will depend on whether or not this # request came into cloud-connector via S3 API or Swift API because of # the differences in authentication between the two APIs. # For now, only S3 API access is supported. if S3_IDENTITY_ENV_KEY in req.environ: # We got a S3 API request s3_identity = req.environ[S3_IDENTITY_ENV_KEY] onprem_swift_profile = { # Other code will expect Unicode strings in here "account": acct.decode('utf8'), "container": profile['container'], # All the "aws_*" stuff will be pointing to the onprem Swift # cluster "aws_bucket": profile['container'], "aws_endpoint": self.swift_baseurl, "aws_identity": s3_identity['access_key'], # already Unicode "aws_secret": s3_identity['secret_key'], # already Unicode "protocol": "s3", "custom_prefix": "", # "native" access } else: raise swob.HTTPNotImplemented( 'UNEXPECTED: only S3 access supported, but ' 'S3_IDENTITY_ENV_KEY missing??') d = dict(local_to_me_profile=profile, remote_to_me_profile=onprem_swift_profile, version=ver, account_name=acct, container_name=cont, object_name=obj) return CloudConnectorController, d
def OPTIONS(self, req): # TODO: implement this (or not) return swob.HTTPNotImplemented()