diff options
author | Michael Krotscheck <krotscheck@gmail.com> | 2015-11-02 12:05:17 -0800 |
---|---|---|
committer | Michael Krotscheck <krotscheck@gmail.com> | 2015-11-16 17:26:51 -0800 |
commit | 4e7bb27895f6876ada3a8b19272422af29e75d22 (patch) | |
tree | 31240dcaed7163a7d23c79628187788c1ca5e2ad | |
parent | 6121b6782c7c588515030ebf418c1e5b262d237b (diff) | |
download | oslo-middleware-4e7bb27895f6876ada3a8b19272422af29e75d22.tar.gz |
Enable latent CORS configuration via pastedeploy
In the case where paste deployment and oslo are used in concert,
it is not possible for an application to easily ship required
configuraton properties, such as custom headers, with their
release artifact. This patch adds parameters which expose
set_latent to paste.ini users, permitting the above.
Tests and documentation have been updated.
Change-Id: Id98002f6813055efe698f0b96a3e0d408c58ed7c
-rw-r--r-- | doc/source/cors.rst | 6 | ||||
-rw-r--r-- | oslo_middleware/cors.py | 15 | ||||
-rw-r--r-- | oslo_middleware/tests/test_cors.py | 23 |
3 files changed, 43 insertions, 1 deletions
diff --git a/doc/source/cors.rst b/doc/source/cors.rst index 11cb043..368b248 100644 --- a/doc/source/cors.rst +++ b/doc/source/cors.rst @@ -115,6 +115,12 @@ configuration, this may be done as follows.:: # Optional field, in case the program name is different from the project: oslo_config_program = oslo_project_name-api + # This method also permits setting latent properties, for any origins set + # in oslo config. + latent_allow_headers=X-Auth-Token + latent_expose_headers=X-Auth-Token + latent_methods=GET,PUT,POST + Configuration Options --------------------- diff --git a/oslo_middleware/cors.py b/oslo_middleware/cors.py index 65d7be0..3735d9c 100644 --- a/oslo_middleware/cors.py +++ b/oslo_middleware/cors.py @@ -55,6 +55,7 @@ CORS_OPTS = [ class InvalidOriginError(Exception): """Exception raised when Origin is invalid.""" + def __init__(self, origin): self.origin = origin super(InvalidOriginError, self).__init__( @@ -87,6 +88,18 @@ class CORS(base.ConfigurableMiddleware): self.allowed_origins = {} self._init_conf() + def sanitize(csv_list): + try: + return [str.strip(x) for x in csv_list.split(',')] + except Exception: + return None + + self.set_latent( + allow_headers=sanitize(self.conf.get('latent_allow_headers')), + expose_headers=sanitize(self.conf.get('latent_expose_headers')), + allow_methods=sanitize(self.conf.get('latent_allow_methods')) + ) + @classmethod def factory(cls, global_conf, **local_conf): """factory method for paste.deploy @@ -99,7 +112,7 @@ class CORS(base.ConfigurableMiddleware): allow_headers: List of HTTP headers to permit from the client. """ if ('allowed_origin' not in local_conf - and 'oslo_config_project' not in local_conf): + and 'oslo_config_project' not in local_conf): raise TypeError("allowed_origin or oslo_config_project " "is required") return super(CORS, cls).factory(global_conf, **local_conf) diff --git a/oslo_middleware/tests/test_cors.py b/oslo_middleware/tests/test_cors.py index d1c1885..7037459 100644 --- a/oslo_middleware/tests/test_cors.py +++ b/oslo_middleware/tests/test_cors.py @@ -152,6 +152,29 @@ class CORSTestFilterFactory(test_base.BaseTestCase): '''Assert that a filter factory with oslo_config_project succeed.''' cors.filter_factory(global_conf=None, oslo_config_project='foobar') + def test_factory_latent_properties(self): + '''Assert latent properties in paste.ini config. + + If latent_* properties are added to a paste.ini config, assert that + they are persisted in the middleware. + ''' + + # Spaces in config are deliberate to frobb the config parsing. + filter = cors.filter_factory(global_conf=None, + oslo_config_project='foobar', + latent_expose_headers=' X-Header-1 , X-2', + latent_allow_headers='X-Header-1 , X-2', + latent_allow_methods='GET,PUT, POST') + app = filter(test_application) + + # Ensure that the properties are in latent configuration. + self.assertEqual(['X-Header-1', 'X-2'], + app._latent_configuration['expose_headers']) + self.assertEqual(['X-Header-1', 'X-2'], + app._latent_configuration['allow_headers']) + self.assertEqual(['GET', 'PUT', 'POST'], + app._latent_configuration['methods']) + class CORSRegularRequestTest(CORSTestBase): """CORS Specification Section 6.1 |