diff options
author | Michael Krotscheck <krotscheck@gmail.com> | 2016-03-10 11:45:13 -0800 |
---|---|---|
committer | Michael Krotscheck <krotscheck@gmail.com> | 2016-05-04 06:53:04 -0700 |
commit | 396f430d64a6588f476c220578b7262a661676d6 (patch) | |
tree | a91494543b5d9529ba069fb3f73e35d373622325 | |
parent | 1e5f746ac4d991d76505dd43b0da9594da5005c7 (diff) | |
download | oslo-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.py | 35 | ||||
-rw-r--r-- | oslo_middleware/tests/test_cors.py | 88 |
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.""" |