Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made the set_cors_headers method in core.py compatible with resp.head… #172

Merged
merged 3 commits into from Aug 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 8 additions & 1 deletion flask_cors/core.py
Expand Up @@ -13,7 +13,7 @@
from datetime import timedelta
from six import string_types
from flask import request, current_app
from werkzeug.datastructures import MultiDict
from werkzeug.datastructures import Headers, MultiDict

LOG = logging.getLogger(__name__)

Expand Down Expand Up @@ -226,6 +226,13 @@ def set_cors_headers(resp, options):
LOG.debug('CORS have been already evaluated, skipping')
return resp

# Some libraries, like OAuthlib, set resp.headers to non Multidict
# objects (Werkzeug Headers work as well). This is a problem because
# headers allow repeated values.
if (not isinstance(resp.headers, Headers)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome catch that there are multiple types here. This makes me realize that checking the actual type is not necessarily what we want, rather we can duck-type this and make it a little more flexible for the future.

I'd suggest we change this to be:

if (not hasattr(resp.headers, 'add')):

Feel free to push back if that seems to nit-picky!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@corydolphin No, that sounds fine to me. I didn't realize you could do that!

Edit: Does having an add method necessarily imply that the object can handle repeated values?

and not isinstance(resp.headers, MultiDict)):
resp.headers = MultiDict(resp.headers)

headers_to_set = get_cors_headers(options, request.headers, request.method)

LOG.debug('Settings CORS headers: %s', str(headers_to_set))
Expand Down
33 changes: 33 additions & 0 deletions tests/core/test_override_headers.py
@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
"""
test
~~~~

Flask-Cors tests module
"""

from ..base_test import FlaskCorsTestCase
from flask import Flask, Response

from flask_cors import *
from flask_cors.core import *

class ResponseHeadersOverrideTestCaseIntegration(FlaskCorsTestCase):
def setUp(self):
self.app = Flask(__name__)
CORS(self.app)

@self.app.route('/')
def index():
response = Response(headers={"custom": "dictionary"})
return 'Welcome'

def test_override_headers(self):
'''
Ensure we work even if response.headers is set to something other than a MultiDict.
'''
for resp in self.iter_responses('/'):
self.assertTrue(ACL_ORIGIN in resp.headers)

if __name__ == "__main__":
unittest.main()