summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Krotscheck <krotscheck@gmail.com>2015-11-02 12:05:17 -0800
committerMichael Krotscheck <krotscheck@gmail.com>2015-11-16 17:26:51 -0800
commit4e7bb27895f6876ada3a8b19272422af29e75d22 (patch)
tree31240dcaed7163a7d23c79628187788c1ca5e2ad
parent6121b6782c7c588515030ebf418c1e5b262d237b (diff)
downloadoslo-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.rst6
-rw-r--r--oslo_middleware/cors.py15
-rw-r--r--oslo_middleware/tests/test_cors.py23
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