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)
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