summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Krotscheck <krotscheck@gmail.com>2016-03-10 11:45:13 -0800
committerMichael Krotscheck <krotscheck@gmail.com>2016-05-04 06:53:04 -0700
commit396f430d64a6588f476c220578b7262a661676d6 (patch)
treea91494543b5d9529ba069fb3f73e35d373622325
parent1e5f746ac4d991d76505dd43b0da9594da5005c7 (diff)
downloadoslo-middleware-396f430d64a6588f476c220578b7262a661676d6.tar.gz
Added set_defaults method to oslo_middleware.cors
This patch adds a set_defaults method to the CORS middleware. It allows overriding the configuration defaults, both for runtime execution and for config generation. Change-Id: Iffc20a09c455fa73239d8fe41491daa309858da9
-rw-r--r--oslo_middleware/cors.py35
-rw-r--r--oslo_middleware/tests/test_cors.py88
2 files changed, 123 insertions, 0 deletions
diff --git a/oslo_middleware/cors.py b/oslo_middleware/cors.py
index 71edde3..dde6482 100644
--- a/oslo_middleware/cors.py
+++ b/oslo_middleware/cors.py
@@ -55,6 +55,41 @@ CORS_OPTS = [
]
+def set_defaults(**kwargs):
+ """Override the default values for configuration options.
+
+ This method permits a project to override the default CORS option values.
+ For example, it may wish to offer a set of sane default headers which
+ allow it to function with only minimal additional configuration.
+
+ :param allow_credentials: Whether to permit credentials.
+ :type allow_credentials: bool
+ :param expose_headers: A list of headers to expose.
+ :type expose_headers: List of Strings
+ :param max_age: Maximum cache duration in seconds.
+ :type max_age: Int
+ :param allow_methods: List of HTTP methods to permit.
+ :type allow_methods: List of Strings
+ :param allow_headers: List of HTTP headers to permit from the client.
+ :type allow_headers: List of Strings
+ """
+ # Since 'None' is a valid config override, we have to use kwargs. Else
+ # there's no good way for a user to override only one option, because all
+ # the others would be overridden to 'None'.
+
+ valid_params = set(k.name for k in CORS_OPTS
+ if k.name != 'allowed_origin')
+ passed_params = set(k for k in kwargs)
+
+ wrong_params = passed_params - valid_params
+ if wrong_params:
+ raise AttributeError('Parameter(s) [%s] invalid, please only use [%s]'
+ % (wrong_params, valid_params))
+
+ # Set global defaults.
+ cfg.set_defaults(CORS_OPTS, **kwargs)
+
+
class InvalidOriginError(Exception):
"""Exception raised when Origin is invalid."""
diff --git a/oslo_middleware/tests/test_cors.py b/oslo_middleware/tests/test_cors.py
index e07a85b..5e0822f 100644
--- a/oslo_middleware/tests/test_cors.py
+++ b/oslo_middleware/tests/test_cors.py
@@ -130,6 +130,94 @@ class CORSTestBase(test_base.BaseTestCase):
self.assertNotIn(header, response.headers)
+class CORSTestDefaultOverrides(CORSTestBase):
+ def setUp(self):
+ super(CORSTestDefaultOverrides, self).setUp()
+
+ fixture = self.config_fixture # Line length accommodation
+
+ fixture.load_raw_values(group='cors',
+ allowed_origin='http://valid.example.com')
+
+ fixture.load_raw_values(group='cors.override_creds',
+ allowed_origin='http://creds.example.com',
+ allow_credentials='True')
+
+ fixture.load_raw_values(group='cors.override_headers',
+ allowed_origin='http://headers.example.com',
+ expose_headers='X-Header-1,X-Header-2',
+ allow_headers='X-Header-1,X-Header-2')
+
+ self.override_opts = {
+ 'expose_headers': ['X-Header-1'],
+ 'allow_headers': ['X-Header-2'],
+ 'allow_methods': ['GET', 'DELETE'],
+ 'allow_credentials': False,
+ 'max_age': 10
+ }
+
+ def test_config_defaults(self):
+ """Assert that using set_defaults overrides the appropriate values."""
+
+ cors.set_defaults(**self.override_opts)
+
+ for opt in cors.CORS_OPTS:
+ if opt.dest in self.override_opts:
+ self.assertEqual(opt.default, self.override_opts[opt.dest])
+
+ def test_invalid_default_option(self):
+ """Assert that using set_defaults only permits valid options."""
+
+ self.assertRaises(AttributeError,
+ cors.set_defaults,
+ allowed_origin='test')
+
+ def test_cascading_override(self):
+ """Assert that using set_defaults overrides cors.* config values."""
+
+ # set defaults
+ cors.set_defaults(**self.override_opts)
+
+ # Now that the config is set up, create our application.
+ self.application = cors.CORS(test_application, self.config)
+
+ # Check the global configuration for expected values:
+ gc = self.config.cors
+ self.assertEqual(gc.allowed_origin, ['http://valid.example.com'])
+ self.assertEqual(gc.allow_credentials,
+ self.override_opts['allow_credentials'])
+ self.assertEqual(gc.expose_headers,
+ self.override_opts['expose_headers'])
+ self.assertEqual(gc.max_age, 10)
+ self.assertEqual(gc.allow_methods,
+ self.override_opts['allow_methods'])
+ self.assertEqual(gc.allow_headers,
+ self.override_opts['allow_headers'])
+
+ # Check the child configuration for expected values:
+ cc = self.config['cors.override_creds']
+ self.assertEqual(cc.allowed_origin, ['http://creds.example.com'])
+ self.assertTrue(cc.allow_credentials)
+ self.assertEqual(cc.expose_headers,
+ self.override_opts['expose_headers'])
+ self.assertEqual(cc.max_age, 10)
+ self.assertEqual(cc.allow_methods,
+ self.override_opts['allow_methods'])
+ self.assertEqual(cc.allow_headers,
+ self.override_opts['allow_headers'])
+
+ # Check the other child configuration for expected values:
+ ec = self.config['cors.override_headers']
+ self.assertEqual(ec.allowed_origin, ['http://headers.example.com'])
+ self.assertEqual(ec.allow_credentials,
+ self.override_opts['allow_credentials'])
+ self.assertEqual(ec.expose_headers, ['X-Header-1', 'X-Header-2'])
+ self.assertEqual(ec.max_age, 10)
+ self.assertEqual(ec.allow_methods,
+ self.override_opts['allow_methods'])
+ self.assertEqual(ec.allow_headers, ['X-Header-1', 'X-Header-2'])
+
+
class CORSTestFilterFactory(CORSTestBase):
"""Test the CORS filter_factory method."""