diff --git a/swift3/middleware.py b/swift3/middleware.py index 4aa4540f..55195e92 100644 --- a/swift3/middleware.py +++ b/swift3/middleware.py @@ -94,12 +94,15 @@ def validate_bucket_name(name): class Swift3Middleware(object): """Swift3 S3 compatibility midleware""" - def __init__(self, app, *args, **kwargs): + def __init__(self, app, conf, *args, **kwargs): self.app = app + self.slo_enabled = True + + self.check_pipeline(conf) def __call__(self, env, start_response): try: - req = Request(env) + req = Request(env, self.slo_enabled) resp = self.handle_request(req) except NotS3Request: resp = self.app @@ -131,6 +134,45 @@ class Swift3Middleware(object): return res + def check_pipeline(self, conf): + """ + Check that proxy-server.conf has an appropriate pipeline for swift3. + """ + if conf.get('__file__', None) is None: + return + + ctx = loadcontext(loadwsgi.APP, conf.__file__) + pipeline = str(PipelineWrapper(ctx)).split(' ') + + # Add compatible with 3rd party middleware. + if check_filter_order(pipeline, ['swift3', 'proxy-server']): + + auth_pipeline = pipeline[pipeline.index('swift3') + 1: + pipeline.index('proxy-server')] + + # Check SLO middleware + if 'slo' not in auth_pipeline: + self.slo_enabled = False + LOGGER.debug('swift3 middleware is required SLO middleware ' + 'to support multi-part upload, please add it ' + 'in pipline') + + if 'tempauth' in auth_pipeline: + LOGGER.debug('Use tempauth middleware.') + return + elif 'keystoneauth' in auth_pipeline: + if check_filter_order(auth_pipeline, ['s3token', + 'authtoken', + 'keystoneauth']): + LOGGER.debug('Use keystone middleware.') + return + + elif len(auth_pipeline): + LOGGER.debug('Use third party(unknown) auth middleware.') + return + + raise ValueError('Invalid proxy pipeline: %s' % pipeline) + def check_filter_order(pipeline, required_filters): """ @@ -145,36 +187,6 @@ def check_filter_order(pipeline, required_filters): return indexes == sorted(indexes) -def check_pipeline(): - """ - Check that proxy-server.conf has an appropriate pipeline for swift3. - """ - ctx = loadcontext(loadwsgi.APP, CONF.__file__) - pipeline = str(PipelineWrapper(ctx)).split(' ') - - # Add compatible with 3rd party middleware. - if check_filter_order(pipeline, ['swift3', 'proxy-server']): - - auth_pipeline = pipeline[pipeline.index('swift3') + 1: - pipeline.index('proxy-server')] - - if 'tempauth' in auth_pipeline: - LOGGER.debug('Use tempauth middleware.') - return - elif 'keystoneauth' in auth_pipeline: - if check_filter_order(auth_pipeline, ['s3token', - 'authtoken', - 'keystoneauth']): - LOGGER.debug('Use keystone middleware.') - return - - elif len(auth_pipeline): - LOGGER.debug('Use third party(unknown) auth middleware.') - return - - raise ValueError('Invalid proxy pipeline: %s' % pipeline) - - def filter_factory(global_conf, **local_conf): """Standard filter factory to use the middleware with paste.deploy""" CONF.update(global_conf) @@ -184,6 +196,7 @@ def filter_factory(global_conf, **local_conf): global LOGGER LOGGER = get_logger(CONF, log_route='swift3') - check_pipeline() + def swift3_filter(app): + return Swift3Middleware(app, CONF) - return Swift3Middleware + return swift3_filter diff --git a/swift3/request.py b/swift3/request.py index db89e262..59c50e9c 100644 --- a/swift3/request.py +++ b/swift3/request.py @@ -61,7 +61,7 @@ class Request(swob.Request): """ S3 request object. """ - def __init__(self, env): + def __init__(self, env, slo_enabled=True): swob.Request.__init__(self, env) self.access_key, self.signature = self._parse_authorization() @@ -70,6 +70,7 @@ class Request(swob.Request): self._validate_headers() self.token = base64.urlsafe_b64encode(self._canonical_string()) self.user_id = None + self.slo_enabled = slo_enabled # Avoids that swift.swob.Response replaces Location header value # by full URL when absolute path given. See swift.swob for more detail. @@ -295,6 +296,11 @@ class Request(swob.Request): 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]): + raise S3NotImplemented("Multi-part feature isn't support") + if 'acl' in self.params: return AclController if 'delete' in self.params: diff --git a/swift3/test/unit/__init__.py b/swift3/test/unit/__init__.py index 687905d3..15d39e25 100644 --- a/swift3/test/unit/__init__.py +++ b/swift3/test/unit/__init__.py @@ -58,7 +58,7 @@ class Swift3TestCase(unittest.TestCase): def setUp(self): self.app = FakeApp() self.swift = self.app.swift - self.swift3 = Swift3Middleware(self.app) + self.swift3 = Swift3Middleware(self.app, CONF) self.swift.register('HEAD', '/v1/AUTH_test/bucket', swob.HTTPNoContent, {}, None) diff --git a/swift3/test/unit/test_middleware.py b/swift3/test/unit/test_middleware.py index 27ef0ca1..99b11171 100644 --- a/swift3/test/unit/test_middleware.py +++ b/swift3/test/unit/test_middleware.py @@ -27,7 +27,6 @@ from swift.common.swob import Request from swift3.test.unit import Swift3TestCase from swift3.request import Request as S3Request from swift3.etree import fromstring -from swift3.middleware import check_pipeline class TestSwift3Middleware(Swift3TestCase): @@ -318,24 +317,27 @@ class TestSwift3Middleware(Swift3TestCase): conf.__file__ = '' pipeline.return_value = 'swift3 tempauth proxy-server' - check_pipeline() + self.swift3.check_pipeline(conf) pipeline.return_value = 'swift3 s3token authtoken keystoneauth ' \ 'proxy-server' - check_pipeline() + self.swift3.check_pipeline(conf) pipeline.return_value = 'swift3 swauth proxy-server' - check_pipeline() + self.swift3.check_pipeline(conf) pipeline.return_value = 'swift3 authtoken s3token keystoneauth ' \ 'proxy-server' - self.assertRaises(ValueError, check_pipeline) + with self.assertRaises(ValueError): + self.swift3.check_pipeline(conf) pipeline.return_value = 'swift3 proxy-server' - self.assertRaises(ValueError, check_pipeline) + with self.assertRaises(ValueError): + self.swift3.check_pipeline(conf) pipeline.return_value = 'proxy-server' - self.assertRaises(ValueError, check_pipeline) + with self.assertRaises(ValueError): + self.swift3.check_pipeline(conf) if __name__ == '__main__':