diff --git a/oslo_middleware/base.py b/oslo_middleware/base.py index ca998f7..6a6c3f5 100644 --- a/oslo_middleware/base.py +++ b/oslo_middleware/base.py @@ -18,6 +18,8 @@ from inspect import getargspec import webob.dec +from oslo_config import cfg + class Middleware(object): """Base WSGI middleware wrapper. @@ -30,10 +32,36 @@ class Middleware(object): @classmethod def factory(cls, global_conf, **local_conf): """Factory method for paste.deploy.""" - return cls + conf = global_conf.copy() if global_conf else {} + conf.update(local_conf) - def __init__(self, application): + def middleware_filter(app): + return cls(app, conf) + + return middleware_filter + + def __init__(self, application, conf=None): self.application = application + # NOTE(sileht): If the configuration come from oslo.config + # just use it. + if isinstance(conf, cfg.ConfigOpts): + self.conf = [] + self.oslo_conf = conf + else: + self.conf = conf or [] + if "oslo_config_project" in self.conf: + if 'oslo_config_file' in self.conf: + default_config_files = [self.conf['oslo_config_file']] + else: + default_config_files = None + self.oslo_conf = cfg.ConfigOpts() + self.oslo_conf([], project=self.conf['oslo_config_project'], + default_config_files=default_config_files, + validate_default_values=True) + + else: + # Fallback to global object + self.oslo_conf = cfg.CONF def process_request(self, req): """Called on each request. diff --git a/oslo_middleware/cors.py b/oslo_middleware/cors.py index 8ea6a88..e2f00c5 100644 --- a/oslo_middleware/cors.py +++ b/oslo_middleware/cors.py @@ -54,38 +54,6 @@ CORS_OPTS = [ ] -def filter_factory(global_conf, - allowed_origin, - allow_credentials=True, - expose_headers=None, - max_age=None, - allow_methods=None, - allow_headers=None): - '''Factory to support paste.deploy - - :param global_conf: The paste.ini global configuration object (not used). - :param allowed_origin: Protocol, host, and port for the allowed origin. - :param allow_credentials: Whether to permit credentials. - :param expose_headers: A list of headers to expose. - :param max_age: Maximum cache duration. - :param allow_methods: List of HTTP methods to permit. - :param allow_headers: List of HTTP headers to permit from the client. - :return: - ''' - - def filter(app): - cors_app = CORS(app) - cors_app.add_origin(allowed_origin=allowed_origin, - allow_credentials=allow_credentials, - expose_headers=expose_headers, - max_age=max_age, - allow_methods=allow_methods, - allow_headers=allow_headers) - return cors_app - - return filter - - class CORS(base.Middleware): """CORS Middleware. @@ -105,15 +73,39 @@ class CORS(base.Middleware): ] def __init__(self, application, conf=None): - super(CORS, self).__init__(application) - + super(CORS, self).__init__(application, conf) # Begin constructing our configuration hash. self.allowed_origins = {} - # Sanity check. Do we have an oslo.config? If so, load it. Else, assume - # that we'll use add_config. - if conf: - self._init_from_oslo(conf) + self._init_from_oslo(self.oslo_conf) + self._init_from_conf() + + @classmethod + def factory(cls, global_conf, allowed_origin, **local_conf): + # Ensures allowed_origin config exists + return super(CORS, cls).factory(global_conf, + allowed_origin=allowed_origin, + **local_conf) + + def _init_from_conf(self): + """Load configuration from paste.deploy + + allowed_origin: Protocol, host, and port for the allowed origin. + allow_credentials: Whether to permit credentials. + expose_headers: A list of headers to expose. + max_age: Maximum cache duration. + allow_methods: List of HTTP methods to permit. + allow_headers: List of HTTP headers to permit from the client. + """ + + if 'allowed_origin' in self.conf: + self.add_origin( + allowed_origin=self.conf['allowed_origin'], + allow_credentials=self.conf.get('allow_credentials', True), + expose_headers=self.conf.get('expose_headers'), + max_age=self.conf.get('max_age'), + allow_methods=self.conf.get('allow_methods'), + allow_headers=self.conf.get('allow_headers')) def _init_from_oslo(self, conf): '''Initialize this middleware from an oslo.config instance.''' @@ -327,3 +319,7 @@ class CORS(base.Middleware): if cors_config['expose_headers']: response.headers['Access-Control-Expose-Headers'] = \ ','.join(cors_config['expose_headers']) + + +# NOTE(sileht): Shortcut for backwards compatibility +filter_factory = CORS.factory diff --git a/oslo_middleware/healthcheck/__init__.py b/oslo_middleware/healthcheck/__init__.py index 39291f6..8c89564 100644 --- a/oslo_middleware/healthcheck/__init__.py +++ b/oslo_middleware/healthcheck/__init__.py @@ -72,16 +72,6 @@ class Healthcheck(base.Middleware): NAMESPACE = "oslo.middleware.healthcheck" - @classmethod - def factory(cls, global_conf, **local_conf): - """Factory method for paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def healthcheck_filter(app): - return cls(app, conf) - return healthcheck_filter - def __init__(self, application, conf): super(Healthcheck, self).__init__(application) self._path = conf.get('path', '/healthcheck') diff --git a/oslo_middleware/sizelimit.py b/oslo_middleware/sizelimit.py index d4f1ca9..2a82bf8 100644 --- a/oslo_middleware/sizelimit.py +++ b/oslo_middleware/sizelimit.py @@ -18,7 +18,6 @@ Request Body limiting middleware. """ from oslo_config import cfg -from oslo_config import cfgfilter import webob.dec import webob.exc @@ -40,9 +39,6 @@ _opts = [ deprecated_opts=_oldopts) ] -CONF = cfgfilter.ConfigFilter(cfg.CONF) -CONF.register_opts(_opts, group='oslo_middleware') - class LimitingReader(object): """Reader to limit the size of an incoming request.""" @@ -82,9 +78,13 @@ class LimitingReader(object): class RequestBodySizeLimiter(base.Middleware): """Limit the size of incoming requests.""" + def __init__(self, application, conf=None): + super(RequestBodySizeLimiter, self).__init__(application, conf) + self.oslo_conf.register_opts(_opts, group='oslo_middleware') + @webob.dec.wsgify def __call__(self, req): - max_size = CONF.oslo_middleware.max_request_body_size + max_size = self.oslo_conf.oslo_middleware.max_request_body_size if (req.content_length is not None and req.content_length > max_size): msg = _("Request is too large.") diff --git a/oslo_middleware/ssl.py b/oslo_middleware/ssl.py index 6ac530b..835a8f2 100644 --- a/oslo_middleware/ssl.py +++ b/oslo_middleware/ssl.py @@ -21,7 +21,6 @@ OPTS = [ "the original request protocol scheme was, even if it was " "hidden by an SSL termination proxy.") ] -cfg.CONF.register_opts(OPTS, group='oslo_middleware') class SSLMiddleware(base.Middleware): @@ -32,12 +31,13 @@ class SSLMiddleware(base.Middleware): termination proxy. """ - def __init__(self, application): - super(SSLMiddleware, self).__init__(application) - self.header_name = 'HTTP_{0}'.format( - cfg.CONF.oslo_middleware.secure_proxy_ssl_header.upper() - .replace('-', '_')) + def __init__(self, application, conf=None): + super(SSLMiddleware, self).__init__(application, conf) + self.oslo_conf.register_opts(OPTS, group='oslo_middleware') def process_request(self, req): + self.header_name = 'HTTP_{0}'.format( + self.oslo_conf.oslo_middleware.secure_proxy_ssl_header.upper() + .replace('-', '_')) req.environ['wsgi.url_scheme'] = req.environ.get( self.header_name, req.environ['wsgi.url_scheme']) diff --git a/oslo_middleware/tests/test_cors.py b/oslo_middleware/tests/test_cors.py index d078d14..8eebf5b 100644 --- a/oslo_middleware/tests/test_cors.py +++ b/oslo_middleware/tests/test_cors.py @@ -115,6 +115,9 @@ class CORSTestFilterFactory(test_base.BaseTestCase): """Test the CORS filter_factory method.""" def test_filter_factory(self): + config = self.useFixture(fixture.Config()) + config.conf([]) + # Test a valid filter. filter = cors.filter_factory(None, allowed_origin='http://valid.example.com', diff --git a/oslo_middleware/tests/test_sizelimit.py b/oslo_middleware/tests/test_sizelimit.py index 2a24659..dc29cd0 100644 --- a/oslo_middleware/tests/test_sizelimit.py +++ b/oslo_middleware/tests/test_sizelimit.py @@ -78,15 +78,15 @@ class TestRequestBodySizeLimiter(test_base.BaseTestCase): def setUp(self): super(TestRequestBodySizeLimiter, self).setUp() - fixture = self.useFixture(config.Config(sizelimit.CONF)) - self.MAX_REQUEST_BODY_SIZE = \ - fixture.conf.oslo_middleware.max_request_body_size + self.useFixture(config.Config()) @webob.dec.wsgify() def fake_app(req): return webob.Response(req.body) self.middleware = sizelimit.RequestBodySizeLimiter(fake_app) + self.MAX_REQUEST_BODY_SIZE = ( + self.middleware.oslo_conf.oslo_middleware.max_request_body_size) self.request = webob.Request.blank('/', method='POST') def test_content_length_acceptable(self): diff --git a/oslo_middleware/tests/test_ssl.py b/oslo_middleware/tests/test_ssl.py index 7314260..a94e4c4 100644 --- a/oslo_middleware/tests/test_ssl.py +++ b/oslo_middleware/tests/test_ssl.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -from oslo_config import cfg from oslo_config import fixture as config from oslotest import base import webob @@ -27,8 +26,12 @@ class SSLMiddlewareTest(base.BaseTestCase): super(SSLMiddlewareTest, self).setUp() self.useFixture(config.Config()) - def _test_scheme(self, expected, headers): + def _test_scheme(self, expected, headers, config=None): middleware = ssl.SSLMiddleware(None) + if config: + middleware.oslo_conf.set_override( + 'secure_proxy_ssl_header', config, + group='oslo_middleware') request = webob.Request.blank('http://example.com/', headers=headers) # Ensure ssl middleware does not stop pipeline execution @@ -44,13 +47,9 @@ class SSLMiddlewareTest(base.BaseTestCase): self._test_scheme('https', headers) def test_with_custom_header(self): - cfg.CONF.set_override('secure_proxy_ssl_header', 'X-My-Header', - group='oslo_middleware') headers = {'X-Forwarded-Proto': 'https'} - self._test_scheme('http', headers) + self._test_scheme('http', headers, config='X-My-Header') def test_with_custom_header_and_forwarded_protocol(self): - cfg.CONF.set_override('secure_proxy_ssl_header', 'X-My-Header', - group='oslo_middleware') headers = {'X-My-Header': 'https'} - self._test_scheme('https', headers) + self._test_scheme('https', headers, config='X-My-Header') diff --git a/tests/test_sizelimit.py b/tests/test_sizelimit.py index 37f5c69..b985f76 100644 --- a/tests/test_sizelimit.py +++ b/tests/test_sizelimit.py @@ -78,15 +78,15 @@ class TestRequestBodySizeLimiter(test_base.BaseTestCase): def setUp(self): super(TestRequestBodySizeLimiter, self).setUp() - fixture = self.useFixture(config.Config(sizelimit.CONF)) - self.MAX_REQUEST_BODY_SIZE = \ - fixture.conf.oslo_middleware.max_request_body_size + self.useFixture(config.Config()) @webob.dec.wsgify() def fake_app(req): return webob.Response(req.body) self.middleware = sizelimit.RequestBodySizeLimiter(fake_app) + self.MAX_REQUEST_BODY_SIZE = ( + self.middleware.oslo_conf.oslo_middleware.max_request_body_size) self.request = webob.Request.blank('/', method='POST') def test_content_length_acceptable(self):