diff options
author | Julien Danjou <julien@danjou.info> | 2016-03-09 13:55:12 +0100 |
---|---|---|
committer | Julien Danjou <julien@danjou.info> | 2016-03-14 15:51:18 +0100 |
commit | 3988776dba4789360d3ea6bddf4eaeb33eb35d7c (patch) | |
tree | d38e003313931182147cd7ae27a8f27c8d3fd39b | |
parent | 6a897ab40c468748e9cce40debf73fbdf4d2d5ee (diff) | |
download | oslo-middleware-3988776dba4789360d3ea6bddf4eaeb33eb35d7c.tar.gz |
cors: prevent WebOb setting a default Content-Type
This related to https://github.com/Pylons/webob/issues/205 upstream.
Change-Id: I18eb78d4206c20efc934fe8709881c2bd6972983
-rw-r--r-- | oslo_middleware/cors.py | 7 | ||||
-rw-r--r-- | oslo_middleware/tests/test_cors.py | 46 |
2 files changed, 38 insertions, 15 deletions
diff --git a/oslo_middleware/cors.py b/oslo_middleware/cors.py index 4fb8101..2e53741 100644 --- a/oslo_middleware/cors.py +++ b/oslo_middleware/cors.py @@ -65,6 +65,11 @@ class InvalidOriginError(Exception): 'CORS request from origin \'%s\' not permitted.' % origin) +class _NoContentTypeResponse(webob.response.Response): + + default_content_type = None # prevents webob assigning content type + + class CORS(base.ConfigurableMiddleware): """CORS Middleware. @@ -287,7 +292,7 @@ class CORS(base.ConfigurableMiddleware): # underlying middleware's response content needs to be persisted. # Otherwise, create a new response. if 200 > response.status_code or response.status_code >= 300: - response = webob.response.Response(status=webob.exc.HTTPOk.code) + response = _NoContentTypeResponse(status=webob.exc.HTTPOk.code) # Does the request have an origin header? (Section 6.2.1) if 'Origin' not in request.headers: diff --git a/oslo_middleware/tests/test_cors.py b/oslo_middleware/tests/test_cors.py index c94b416..e07a85b 100644 --- a/oslo_middleware/tests/test_cors.py +++ b/oslo_middleware/tests/test_cors.py @@ -70,7 +70,8 @@ class CORSTestBase(test_base.BaseTestCase): allow_headers=None, allow_credentials=None, expose_headers=None, - vary='Origin'): + vary='Origin', + has_content_type=False): """Test helper for CORS response headers. Assert all the headers in a given response. By default, we assume @@ -110,6 +111,10 @@ class CORSTestBase(test_base.BaseTestCase): 'Access-Control-Expose-Headers', expose_headers) + # Assert no Content-Type added. + if not has_content_type: + self.assertHeader(response, 'Content-Type') + # If we're expecting an origin response, also assert that the # Vary: Origin header is set, since this implementation of the CORS # specification permits multiple origin domains. @@ -344,7 +349,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers=None) + expose_headers=None, + has_content_type=True) def test_origin_headers(self): """CORS Specification Section 6.1.2 @@ -367,7 +373,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers=None) + expose_headers=None, + has_content_type=True) # Test origin header not present in configuration. for method in self.methods: @@ -382,7 +389,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers=None) + expose_headers=None, + has_content_type=True) # Test valid, but case-mismatched origin header. for method in self.methods: @@ -397,7 +405,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers=None) + expose_headers=None, + has_content_type=True) # Test valid header from list of duplicates. for method in self.methods: @@ -412,7 +421,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers=None) + expose_headers=None, + has_content_type=True) def test_supports_credentials(self): """CORS Specification Section 6.1.3 @@ -440,7 +450,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers=None) + expose_headers=None, + has_content_type=True) # Test valid origin header with credentials for method in self.methods: @@ -455,7 +466,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials="true", - expose_headers=None) + expose_headers=None, + has_content_type=True) def test_expose_headers(self): """CORS Specification Section 6.1.4 @@ -476,7 +488,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers='X-Header-1,X-Header-2') + expose_headers='X-Header-1,X-Header-2', + has_content_type=True) def test_application_options_response(self): """Assert that an application provided OPTIONS response is honored. @@ -523,7 +536,8 @@ class CORSRegularRequestTest(CORSTestBase): allow_headers=None, allow_credentials=None, expose_headers=None, - vary='Custom-Vary,Origin') + vary='Custom-Vary,Origin', + has_content_type=True) class CORSPreflightRequestTest(CORSTestBase): @@ -1058,7 +1072,8 @@ class CORSPreflightRequestTest(CORSTestBase): allow_methods='GET', allow_headers=None, allow_credentials=None, - expose_headers=None) + expose_headers=None, + has_content_type=True) class CORSTestWildcard(CORSTestBase): @@ -1139,7 +1154,8 @@ class CORSTestWildcard(CORSTestBase): max_age=None, allow_headers='', allow_credentials='true', - expose_headers=None) + expose_headers=None, + has_content_type=True) # Test invalid domain request = webob.Request.blank('/') @@ -1154,7 +1170,8 @@ class CORSTestWildcard(CORSTestBase): allow_methods='GET', allow_headers='', allow_credentials='true', - expose_headers=None) + expose_headers=None, + has_content_type=True) class CORSTestLatentProperties(CORSTestBase): @@ -1253,7 +1270,8 @@ class CORSTestLatentProperties(CORSTestBase): allow_headers=None, allow_credentials='true', expose_headers='X-Configured,' - 'X-Server-Generated-Response') + 'X-Server-Generated-Response', + has_content_type=True) def test_invalid_latent_expose_headers(self): """Assert that passing a non-list is caught in expose headers.""" |