Skip to content

Commit

Permalink
Service.cors_supported_headers are now filtered by method
Browse files Browse the repository at this point in the history
  • Loading branch information
leplatrem committed Mar 13, 2015
1 parent 47c78c9 commit c6fd2ae
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 15 deletions.
4 changes: 2 additions & 2 deletions cornice/cors.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def get_cors_preflight_view(service):
def _preflight_view(request):
response = request.response
origin = request.headers.get('Origin')
supported_headers = service.cors_supported_headers
supported_headers = service.cors_supported_headers()

if not origin:
request.errors.add('header', 'Origin',
Expand Down Expand Up @@ -127,7 +127,7 @@ def apply_cors_post_request(service, request, response):

if request.method != 'OPTIONS':
# Which headers are exposed?
supported_headers = service.cors_supported_headers
supported_headers = service.cors_supported_headers(request.method)
if supported_headers:
response.headers['Access-Control-Expose-Headers'] = (
', '.join(supported_headers))
Expand Down
12 changes: 8 additions & 4 deletions cornice/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,17 +413,21 @@ def cors_enabled(self):
def cors_enabled(self, value):
self._cors_enabled = value

@property
def cors_supported_headers(self):
def cors_supported_headers(self, method=None):
"""Return an iterable of supported headers for this service.
The supported headers are defined by the :param headers: argument
that is passed to services or methods, at definition time.
"""
headers = set()
for _, _, args in self.definitions:
for meth, _, args in self.definitions:
if args.get('cors_enabled', True):
headers |= set(args.get('cors_headers', ()))
exposed_headers = args.get('cors_headers', ())
if method is not None:
if meth.upper() == method.upper():
return exposed_headers
else:
headers |= set(exposed_headers)
return headers

@property
Expand Down
4 changes: 2 additions & 2 deletions cornice/tests/test_cors.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def post(self):
cors_klass.add_view('post', 'post')


@squirel.get(cors_origins=('notmyidea.org',))
@squirel.get(cors_origins=('notmyidea.org',), cors_headers=('X-My-Header',))
def get_squirel(request):
return "squirels"

Expand All @@ -51,7 +51,7 @@ def post_squirel(request):
return "moar squirels (take care)"


@squirel.put(cors_headers=('X-My-Header',))
@squirel.put()
def put_squirel(request):
return "squirels!"

Expand Down
22 changes: 15 additions & 7 deletions cornice/tests/test_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,37 +347,45 @@ def test_cors_headers_for_service_instanciation(self):
# it is possible to list all the headers supported by a service.
service = Service('coconuts', '/migrate',
cors_headers=('X-Header-Coconut'))
self.assertNotIn('X-Header-Coconut', service.cors_supported_headers)
self.assertNotIn('X-Header-Coconut', service.cors_supported_headers())

service.add_view('POST', _stub)
self.assertIn('X-Header-Coconut', service.cors_supported_headers)
self.assertIn('X-Header-Coconut', service.cors_supported_headers())

def test_cors_headers_for_view_definition(self):
# defining headers in the view should work.
service = Service('coconuts', '/migrate')
service.add_view('POST', _stub, cors_headers=('X-Header-Foobar'))
self.assertIn('X-Header-Foobar', service.cors_supported_headers)
self.assertIn('X-Header-Foobar', service.cors_supported_headers())

def test_cors_headers_extension(self):
# definining headers in the service and in the view
service = Service('coconuts', '/migrate',
cors_headers=('X-Header-Foobar'))
service.add_view('POST', _stub, cors_headers=('X-Header-Barbaz'))
self.assertIn('X-Header-Foobar', service.cors_supported_headers)
self.assertIn('X-Header-Barbaz', service.cors_supported_headers)
self.assertIn('X-Header-Foobar', service.cors_supported_headers())
self.assertIn('X-Header-Barbaz', service.cors_supported_headers())

# check that adding the same header twice doesn't make bad things
# happen
service.add_view('POST', _stub, cors_headers=('X-Header-Foobar'),)
self.assertEqual(len(service.cors_supported_headers), 2)
self.assertEqual(len(service.cors_supported_headers()), 2)

# check that adding a header on a cors disabled method doesn't
# change anything
service.add_view('put', _stub,
cors_headers=('X-Another-Header',),
cors_enabled=False)

self.assertFalse('X-Another-Header' in service.cors_supported_headers)
self.assertNotIn('X-Another-Header', service.cors_supported_headers())

def test_cors_headers_for_method(self):
# defining headers in the view should work.
service = Service('coconuts', '/migrate')
service.add_view('GET', _stub, cors_headers=('X-Header-Foobar'))
service.add_view('POST', _stub, cors_headers=('X-Header-Barbaz'))
get_headers = service.cors_supported_headers(method='GET')
self.assertNotIn('X-Header-Barbaz', get_headers)

def test_cors_supported_methods(self):
foo = Service(name='foo', path='/foo', cors_enabled=True)
Expand Down

0 comments on commit c6fd2ae

Please sign in to comment.