Merge "Enable cluster-wide CORS Expose-Headers setting"

This commit is contained in:
Jenkins 2017-03-13 19:24:20 +00:00 committed by Gerrit Code Review
commit 1e9b8888bf
6 changed files with 86 additions and 0 deletions

View File

@ -143,6 +143,8 @@ This is very useful when one is managing more than one swift cluster.
Use a comma separated list of full URL (http://foo.bar:1234,https://foo.bar)
.IP \fBstrict_cors_mode\fR
The default is true.
.IP \fBcors_expose_headers\fR
Comma separated list of headers to expose through Access-Control-Expose-Headers
.IP \fBnice_priority\fR
Modify scheduling priority of server processes. Niceness values range from -20
(most favorable to the process) to 19 (least favorable to the process).

View File

@ -1573,6 +1573,11 @@ cors_allow_origin This is a list o
header in addition to what
the container has set.
strict_cors_mode True
cors_expose_headers This is a list of headers that
are included in the header
Access-Control-Expose-Headers
in addition to what the container
has set.
client_timeout 60
trans_id_suffix This optional suffix (default is empty)
that would be appended to the swift

View File

@ -73,6 +73,9 @@ bind_port = 8080
# cors_allow_origin =
# strict_cors_mode = True
#
# Comma separated list of headers to expose through Access-Control-Expose-Headers
# cors_expose_headers =
#
# client_timeout = 60
# eventlet_debug = false
#

View File

@ -232,6 +232,7 @@ def cors_validation(func):
# - simple response headers,
# http://www.w3.org/TR/cors/#simple-response-header
# - swift specific: etag, x-timestamp, x-trans-id
# - headers provided by the operator in cors_expose_headers
# - user metadata headers
# - headers provided by the user in
# x-container-meta-access-control-expose-headers
@ -240,6 +241,7 @@ def cors_validation(func):
'cache-control', 'content-language', 'content-type',
'expires', 'last-modified', 'pragma', 'etag',
'x-timestamp', 'x-trans-id', 'x-openstack-request-id'])
expose_headers.update(controller.app.cors_expose_headers)
for header in resp.headers:
if header.startswith('X-Container-Meta') or \
header.startswith('X-Object-Meta'):

View File

@ -147,6 +147,10 @@ class Application(object):
a.strip()
for a in conf.get('cors_allow_origin', '').split(',')
if a.strip()]
self.cors_expose_headers = [
a.strip()
for a in conf.get('cors_expose_headers', '').split(',')
if a.strip()]
self.strict_cors_mode = config_true_value(
conf.get('strict_cors_mode', 't'))
self.node_timings = {}

View File

@ -5348,6 +5348,76 @@ class TestObjectController(ECTestMixin, unittest.TestCase):
self.assertEqual('x-trans-id',
resp.headers['access-control-expose-headers'])
def test_CORS_expose_headers(self):
default_expected_exposed = set([
'cache-control', 'content-language', 'content-type', 'expires',
'last-modified', 'pragma', 'etag', 'x-timestamp', 'x-trans-id',
'x-openstack-request-id'])
def objectGET(controller, req):
return Response(headers={
'X-Custom-Operator': 'hush',
'X-Custom-User': 'hush',
})
# test default expose_headers
self.app.cors_expose_headers = []
container_cors = {'allow_origin': 'http://foo.bar'}
resp = self._get_CORS_response(container_cors=container_cors,
strict_mode=False, object_get=objectGET)
self.assertEqual(200, resp.status_int)
self.assertIn('access-control-expose-headers', resp.headers)
exposed = set(
h.strip() for h in
resp.headers['access-control-expose-headers'].split(','))
self.assertEqual(default_expected_exposed, exposed)
# test operator expose_headers
self.app.cors_expose_headers = ['x-custom-operator', ]
container_cors = {'allow_origin': 'http://foo.bar'}
resp = self._get_CORS_response(container_cors=container_cors,
strict_mode=False, object_get=objectGET)
self.assertEqual(200, resp.status_int)
self.assertIn('access-control-expose-headers', resp.headers)
exposed = set(
h.strip() for h in
resp.headers['access-control-expose-headers'].split(','))
self.assertEqual(default_expected_exposed | set(['x-custom-operator']),
exposed)
# test user expose_headers
self.app.cors_expose_headers = []
container_cors = {'allow_origin': 'http://foo.bar',
'expose_headers': 'x-custom-user'}
resp = self._get_CORS_response(container_cors=container_cors,
strict_mode=False, object_get=objectGET)
self.assertEqual(200, resp.status_int)
self.assertIn('access-control-expose-headers', resp.headers)
exposed = set(
h.strip() for h in
resp.headers['access-control-expose-headers'].split(','))
self.assertEqual(default_expected_exposed | set(['x-custom-user']),
exposed)
# test user and operator expose_headers
self.app.cors_expose_headers = ['x-custom-operator', ]
container_cors = {'allow_origin': 'http://foo.bar',
'expose_headers': 'x-custom-user'}
resp = self._get_CORS_response(container_cors=container_cors,
strict_mode=False, object_get=objectGET)
self.assertEqual(200, resp.status_int)
self.assertIn('access-control-expose-headers', resp.headers)
exposed = set(
h.strip() for h in
resp.headers['access-control-expose-headers'].split(','))
self.assertEqual(default_expected_exposed | set(['x-custom-user',
'x-custom-operator']),
exposed)
def _gather_x_container_headers(self, controller_call, req, *connect_args,
**kwargs):
header_list = kwargs.pop('header_list', ['X-Container-Device',