Add more doc and test for cors_expose_headers option

In follow-up to the related change, mention the new
cors_expose_headers option (and other proxy-server.conf
options) in the CORS doc.

Add a test for the cors options being loaded into the
proxy server.

Improve CORS comments in docs.

Change-Id: I647d8f9e9cbd98de05443638628414b1e87d1a76
Related-Change: I5ca90a052f27c98a514a96ee2299bfa1b6d46334
This commit is contained in:
Alistair Coles 2017-03-13 17:12:13 +00:00 committed by Tim Burke
parent 956172623c
commit 904e7c97f1
5 changed files with 73 additions and 18 deletions

View File

@ -142,11 +142,14 @@ This optional suffix (default is empty) that would be appended to the swift tran
id allows one to easily figure out from which cluster that X-Trans-Id belongs to. id allows one to easily figure out from which cluster that X-Trans-Id belongs to.
This is very useful when one is managing more than one swift cluster. This is very useful when one is managing more than one swift cluster.
.IP \fBcors_allow_origin\fR .IP \fBcors_allow_origin\fR
Use a comma separated list of full URL (http://foo.bar:1234,https://foo.bar) List of origin hosts that are allowed for CORS requests in addition to what
the container has set. 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. If True (default) then CORS requests are only allowed if their Origin header
matches an allowed origin. Otherwise, any Origin is allowed.
.IP \fBcors_expose_headers\fR .IP \fBcors_expose_headers\fR
Comma separated list of headers to expose through Access-Control-Expose-Headers Comma separated list of headers to expose through Access-Control-Expose-Headers,
in addition to the defaults and any headers set in container metadata.
.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).

View File

@ -28,6 +28,11 @@ The supported headers are,
| | Space separated. | | | Space separated. |
+------------------------------------------------+------------------------------+ +------------------------------------------------+------------------------------+
In addition the the values set in container metadata, some cluster-wide values
may also be configured using the ``strict_cors_mode``, ``cors_allow_origin``
and ``cors_expose_headers`` in ``proxy-server.conf``. See
``proxy-server.conf-sample`` for more information.
Before a browser issues an actual request it may issue a `preflight request`_. Before a browser issues an actual request it may issue a `preflight request`_.
The preflight request is an OPTIONS call to verify the Origin is allowed to The preflight request is an OPTIONS call to verify the Origin is allowed to
make the request. The sequence of events are, make the request. The sequence of events are,
@ -48,6 +53,8 @@ returns the following values for this header,
* all metadata headers (``X-Container-Meta-*`` for containers and * all metadata headers (``X-Container-Meta-*`` for containers and
``X-Object-Meta-*`` for objects) ``X-Object-Meta-*`` for objects)
* headers listed in ``X-Container-Meta-Access-Control-Expose-Headers`` * headers listed in ``X-Container-Meta-Access-Control-Expose-Headers``
* headers configured using the ``cors_expose_headers`` option in
``proxy-server.conf``
.. note:: .. note::
An OPTIONS request to a symlink object will respond with the options for An OPTIONS request to a symlink object will respond with the options for

View File

@ -1765,14 +1765,14 @@ cert_file Path to the ssl
key_file Path to the ssl .key. This key_file Path to the ssl .key. This
should be enabled for testing should be enabled for testing
purposes only. purposes only.
cors_allow_origin This is a list of hosts that cors_allow_origin List of origin hosts that are allowed
are included with any CORS for CORS requests in addition to what
request by default and
returned with the
Access-Control-Allow-Origin
header in addition to what
the container has set. the container has set.
strict_cors_mode True strict_cors_mode True If True (default) then CORS
requests are only allowed if their
Origin header matches an allowed
origin. Otherwise, any Origin is
allowed.
cors_expose_headers This is a list of headers that cors_expose_headers This is a list of headers that
are included in the header are included in the header
Access-Control-Expose-Headers Access-Control-Expose-Headers

View File

@ -70,11 +70,18 @@ bind_port = 8080
# log_statsd_sample_rate_factor = 1.0 # log_statsd_sample_rate_factor = 1.0
# log_statsd_metric_prefix = # log_statsd_metric_prefix =
# #
# List of origin hosts that are allowed for CORS requests in addition to what
# the container has set.
# 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)
# cors_allow_origin = # cors_allow_origin =
# If True (default) then CORS requests are only allowed if their Origin header
# matches an allowed origin. Otherwise, any Origin is allowed.
# strict_cors_mode = True # strict_cors_mode = True
# #
# Comma separated list of headers to expose through Access-Control-Expose-Headers # Comma separated list of headers to expose through Access-Control-Expose-Headers,
# in addition to the defaults and any headers set in container metadata (see
# CORS documentation).
# cors_expose_headers = # cors_expose_headers =
# #
# client_timeout = 60 # client_timeout = 60

View File

@ -562,18 +562,48 @@ class TestController(unittest.TestCase):
@patch_policies([StoragePolicy(0, 'zero', True, object_ring=FakeRing())]) @patch_policies([StoragePolicy(0, 'zero', True, object_ring=FakeRing())])
class TestProxyServer(unittest.TestCase): class TestProxyServerConfiguration(unittest.TestCase):
def _make_app(self, conf):
def test_creation(self): # helper function to instantiate a proxy server instance
# later config should be extended to assert more config options return proxy_server.Application(conf, FakeMemcache(),
app = proxy_server.Application({'node_timeout': '3.5',
'recoverable_node_timeout': '1.5'},
FakeMemcache(),
container_ring=FakeRing(), container_ring=FakeRing(),
account_ring=FakeRing()) account_ring=FakeRing())
def test_node_timeout(self):
# later config should be extended to assert more config options
app = self._make_app({'node_timeout': '3.5',
'recoverable_node_timeout': '1.5'})
self.assertEqual(app.node_timeout, 3.5) self.assertEqual(app.node_timeout, 3.5)
self.assertEqual(app.recoverable_node_timeout, 1.5) self.assertEqual(app.recoverable_node_timeout, 1.5)
def test_cors_options(self):
# check defaults
app = self._make_app({})
self.assertFalse(app.cors_allow_origin)
self.assertFalse(app.cors_expose_headers)
self.assertTrue(app.strict_cors_mode)
# check custom configs
app = self._make_app({
'cors_allow_origin': '',
'cors_expose_headers': '',
'strict_cors_mode': 'True'})
self.assertTrue(app.strict_cors_mode)
app = self._make_app({
'cors_allow_origin': ' http://X.com,http://Y.com ,, http://Z.com',
'cors_expose_headers': ' custom1,,, custom2,custom3,,',
'strict_cors_mode': 'False'})
self.assertEqual({'http://X.com', 'http://Y.com', 'http://Z.com'},
set(app.cors_allow_origin))
self.assertEqual({'custom1', 'custom2', 'custom3'},
set(app.cors_expose_headers))
self.assertFalse(app.strict_cors_mode)
@patch_policies([StoragePolicy(0, 'zero', True, object_ring=FakeRing())])
class TestProxyServer(unittest.TestCase):
def test_get_object_ring(self): def test_get_object_ring(self):
baseapp = proxy_server.Application({}, baseapp = proxy_server.Application({},
FakeMemcache(), FakeMemcache(),
@ -5280,6 +5310,14 @@ class TestReplicatedObjectController(
self.assertNotIn('access-control-expose-headers', resp.headers) self.assertNotIn('access-control-expose-headers', resp.headers)
self.assertNotIn('access-control-allow-origin', resp.headers) self.assertNotIn('access-control-allow-origin', resp.headers)
# test proxy server cors_allow_origin option
self.app.cors_allow_origin = ['http://foo.bar']
resp = self._get_CORS_response(
container_cors=container_cors, strict_mode=True)
self.assertEqual('http://foo.bar',
resp.headers['access-control-allow-origin'])
self.assertEqual(expected_exposed, exposed)
def test_CORS_valid_with_obj_headers(self): def test_CORS_valid_with_obj_headers(self):
container_cors = {'allow_origin': 'http://foo.bar'} container_cors = {'allow_origin': 'http://foo.bar'}