diff options
author | Michael Krotscheck <krotscheck@gmail.com> | 2016-03-09 07:27:39 -0800 |
---|---|---|
committer | Michael Krotscheck <krotscheck@gmail.com> | 2016-03-09 07:27:39 -0800 |
commit | 6a897ab40c468748e9cce40debf73fbdf4d2d5ee (patch) | |
tree | 09c849f3267c0d006ccfd41449420e7fc8b31744 | |
parent | 83b79fd527e9e7dd694e8067a3be8403414ac223 (diff) | |
download | oslo-middleware-6a897ab40c468748e9cce40debf73fbdf4d2d5ee.tar.gz |
CORS Middleware now honors upstream Vary header
If an upstream middleware or server returns a 'Vary' header, the
CORS middleware will honor that header and append its own,
rather than overwriting it.
https://tools.ietf.org/html/rfc7231#section-7.1.4
Change-Id: I422cf1723dca7e1ecf0ce863b389f125d4f813bb
-rw-r--r-- | oslo_middleware/cors.py | 5 | ||||
-rw-r--r-- | oslo_middleware/tests/test_cors.py | 35 |
2 files changed, 37 insertions, 3 deletions
diff --git a/oslo_middleware/cors.py b/oslo_middleware/cors.py index 7fbe2d2..4fb8101 100644 --- a/oslo_middleware/cors.py +++ b/oslo_middleware/cors.py @@ -391,7 +391,10 @@ class CORS(base.ConfigurableMiddleware): return # Set the default origin permission headers. (Sections 6.1.3 & 6.4) - response.headers['Vary'] = 'Origin' + if 'Vary' in response.headers: + response.headers['Vary'] += ',Origin' + else: + response.headers['Vary'] = 'Origin' response.headers['Access-Control-Allow-Origin'] = origin # Does this CORS configuration permit credentials? (Section 6.1.3) diff --git a/oslo_middleware/tests/test_cors.py b/oslo_middleware/tests/test_cors.py index 1d7d3ab..c94b416 100644 --- a/oslo_middleware/tests/test_cors.py +++ b/oslo_middleware/tests/test_cors.py @@ -31,6 +31,12 @@ def test_application(req): response.headers['X-Server-Generated-Response'] = '1' return response + if req.path_info == '/server_cors_vary': + # Mirror back the origin in the request. + response = webob.Response(status=200) + response.headers['Vary'] = 'Custom-Vary' + return response + if req.path_info == '/server_no_cors': # Send a response with no CORS headers. response = webob.Response(status=200) @@ -63,7 +69,8 @@ class CORSTestBase(test_base.BaseTestCase): allow_methods=None, allow_headers=None, allow_credentials=None, - expose_headers=None): + expose_headers=None, + vary='Origin'): """Test helper for CORS response headers. Assert all the headers in a given response. By default, we assume @@ -107,7 +114,7 @@ class CORSTestBase(test_base.BaseTestCase): # Vary: Origin header is set, since this implementation of the CORS # specification permits multiple origin domains. if allow_origin: - self.assertHeader(response, 'Vary', 'Origin') + self.assertHeader(response, 'Vary', vary) def assertHeader(self, response, header, value=None): if value: @@ -494,6 +501,30 @@ class CORSRegularRequestTest(CORSTestBase): self.assertEqual(response.headers['X-Server-Generated-Response'], '1') + def test_application_vary_respected(self): + """Assert that an application's provided Vary header is persisted. + + If the underlying application, via middleware or other, provides a + Vary header, its response should be honored. + """ + + request = webob.Request.blank('/server_cors_vary') + request.method = "GET" + request.headers['Origin'] = 'http://valid.example.com' + request.headers['Access-Control-Request-Method'] = 'GET' + + response = request.get_response(self.application) + + self.assertCORSResponse(response, + status='200 OK', + allow_origin='http://valid.example.com', + max_age=None, + allow_methods=None, + allow_headers=None, + allow_credentials=None, + expose_headers=None, + vary='Custom-Vary,Origin') + class CORSPreflightRequestTest(CORSTestBase): """CORS Specification Section 6.2 |