Merge "Enable cluster-wide CORS Expose-Headers setting"
This commit is contained in:
commit
1e9b8888bf
@ -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)
|
Use a comma separated list of full URL (http://foo.bar:1234,https://foo.bar)
|
||||||
.IP \fBstrict_cors_mode\fR
|
.IP \fBstrict_cors_mode\fR
|
||||||
The default is true.
|
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
|
.IP \fBnice_priority\fR
|
||||||
Modify scheduling priority of server processes. Niceness values range from -20
|
Modify scheduling priority of server processes. Niceness values range from -20
|
||||||
(most favorable to the process) to 19 (least favorable to the process).
|
(most favorable to the process) to 19 (least favorable to the process).
|
||||||
|
@ -1573,6 +1573,11 @@ cors_allow_origin This is a list o
|
|||||||
header in addition to what
|
header in addition to what
|
||||||
the container has set.
|
the container has set.
|
||||||
strict_cors_mode True
|
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
|
client_timeout 60
|
||||||
trans_id_suffix This optional suffix (default is empty)
|
trans_id_suffix This optional suffix (default is empty)
|
||||||
that would be appended to the swift
|
that would be appended to the swift
|
||||||
|
@ -73,6 +73,9 @@ bind_port = 8080
|
|||||||
# cors_allow_origin =
|
# cors_allow_origin =
|
||||||
# strict_cors_mode = True
|
# strict_cors_mode = True
|
||||||
#
|
#
|
||||||
|
# Comma separated list of headers to expose through Access-Control-Expose-Headers
|
||||||
|
# cors_expose_headers =
|
||||||
|
#
|
||||||
# client_timeout = 60
|
# client_timeout = 60
|
||||||
# eventlet_debug = false
|
# eventlet_debug = false
|
||||||
#
|
#
|
||||||
|
@ -232,6 +232,7 @@ def cors_validation(func):
|
|||||||
# - simple response headers,
|
# - simple response headers,
|
||||||
# http://www.w3.org/TR/cors/#simple-response-header
|
# http://www.w3.org/TR/cors/#simple-response-header
|
||||||
# - swift specific: etag, x-timestamp, x-trans-id
|
# - swift specific: etag, x-timestamp, x-trans-id
|
||||||
|
# - headers provided by the operator in cors_expose_headers
|
||||||
# - user metadata headers
|
# - user metadata headers
|
||||||
# - headers provided by the user in
|
# - headers provided by the user in
|
||||||
# x-container-meta-access-control-expose-headers
|
# x-container-meta-access-control-expose-headers
|
||||||
@ -240,6 +241,7 @@ def cors_validation(func):
|
|||||||
'cache-control', 'content-language', 'content-type',
|
'cache-control', 'content-language', 'content-type',
|
||||||
'expires', 'last-modified', 'pragma', 'etag',
|
'expires', 'last-modified', 'pragma', 'etag',
|
||||||
'x-timestamp', 'x-trans-id', 'x-openstack-request-id'])
|
'x-timestamp', 'x-trans-id', 'x-openstack-request-id'])
|
||||||
|
expose_headers.update(controller.app.cors_expose_headers)
|
||||||
for header in resp.headers:
|
for header in resp.headers:
|
||||||
if header.startswith('X-Container-Meta') or \
|
if header.startswith('X-Container-Meta') or \
|
||||||
header.startswith('X-Object-Meta'):
|
header.startswith('X-Object-Meta'):
|
||||||
|
@ -147,6 +147,10 @@ class Application(object):
|
|||||||
a.strip()
|
a.strip()
|
||||||
for a in conf.get('cors_allow_origin', '').split(',')
|
for a in conf.get('cors_allow_origin', '').split(',')
|
||||||
if a.strip()]
|
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(
|
self.strict_cors_mode = config_true_value(
|
||||||
conf.get('strict_cors_mode', 't'))
|
conf.get('strict_cors_mode', 't'))
|
||||||
self.node_timings = {}
|
self.node_timings = {}
|
||||||
|
@ -5348,6 +5348,76 @@ class TestObjectController(ECTestMixin, unittest.TestCase):
|
|||||||
self.assertEqual('x-trans-id',
|
self.assertEqual('x-trans-id',
|
||||||
resp.headers['access-control-expose-headers'])
|
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,
|
def _gather_x_container_headers(self, controller_call, req, *connect_args,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
header_list = kwargs.pop('header_list', ['X-Container-Device',
|
header_list = kwargs.pop('header_list', ['X-Container-Device',
|
||||||
|
Loading…
Reference in New Issue
Block a user