Skip to content

Commit 67c4b2c

Browse files
authored
Fix request path normalization (#272)
* Normalize path before evaluating resource rules
1 parent 5c6e05e commit 67c4b2c

File tree

6 files changed

+33
-16
lines changed

6 files changed

+33
-16
lines changed

.travis.yml

+12-11
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@ python:
77
- '3.4'
88
- '3.5'
99
- '3.6'
10+
- '3.7'
11+
- '3.8'
1012
- pypy
1113

12-
# from https://github.com/travis-ci/travis-ci/issues/9815
13-
# https://github.com/travis-ci/travis-ci/issues/9069#issuecomment-425720905
14-
# Enable 3.7 without globally enabling sudo and dist: xenial for other build jobs
1514
matrix:
16-
include:
17-
- python: 3.7
18-
dist: xenial
19-
sudo: true
20-
15+
exclude:
16+
- python: 3.4
17+
- env:
18+
- DEPEENDENCIES="flask==1.1"
19+
2120
env:
22-
- FLASK=0.10.1
23-
- FLASK=0.10
21+
- DEPEENDENCIES="flask==0.10.1 werkzeug==0.16.1" # pin werkzeug for Flask 10, 10.1 since Flask does not pin it itself.
22+
- DEPEENDENCIES="flask==0.10 werkzeug==0.16.1"
23+
- DEPEENDENCIES="flask==1.0"
24+
- DEPEENDENCIES="flask==1.1"
2425

2526
install:
26-
- pip install -U setuptools pep8 six coverage docutils pygments flask==$FLASK
27+
- pip install -U setuptools pep8 six coverage docutils pygments packaging $DEPEENDENCIES
2728

2829
script:
2930
- coverage erase

examples/app_based_example.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def get_exception():
124124
Browsers will first make a preflight request to verify that the resource
125125
allows cross-origin POSTs with a JSON Content-Type, which can be simulated
126126
as:
127-
$ curl --include -X OPTIONS http://127.0.0.1:5000/exception \
127+
$ curl --include -X OPTIONS http://127.0.0.1:5000/api/exception \
128128
--header Access-Control-Request-Method:POST \
129129
--header Access-Control-Request-Headers:Content-Type \
130130
--header Origin:www.examplesite.com

flask_cors/extension.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
"""
1111
from flask import request
1212
from .core import *
13+
try:
14+
from urllib.parse import unquote_plus
15+
except ImportError:
16+
from urllib import unquote_plus
1317

1418
LOG = logging.getLogger(__name__)
1519

@@ -173,9 +177,9 @@ def cors_after_request(resp):
173177
if resp.headers is not None and resp.headers.get(ACL_ORIGIN):
174178
LOG.debug('CORS have been already evaluated, skipping')
175179
return resp
176-
180+
normalized_path = unquote_plus(request.path)
177181
for res_regex, res_options in resources:
178-
if try_match(request.path, res_regex):
182+
if try_match(normalized_path, res_regex):
179183
LOG.debug("Request to '%s' matches CORS resource '%s'. Using options: %s",
180184
request.path, get_regexp_pattern(res_regex), res_options)
181185
set_cors_headers(resp, res_options)

setup.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
platforms='any',
3434
install_requires=install_requires,
3535
tests_require=[
36-
'nose'
36+
'nose',
37+
'packaging'
3738
],
3839
test_suite='nose.collector',
3940
classifiers=[

tests/decorator/test_exception_interception.py

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
:copyright: (c) 2016 by Cory Dolphin.
99
:license: MIT, see LICENSE for more details.
1010
"""
11+
import unittest
12+
13+
import flask
14+
from packaging import version
1115
from ..base_test import FlaskCorsTestCase
1216
from flask import Flask, abort
1317
from flask_cors import *
@@ -198,6 +202,9 @@ def get_with_origins(path):
198202
self.assertEqual(resp.status_code, 200)
199203
self.assertFalse(ACL_ORIGIN in resp.headers)
200204

205+
@unittest.skipIf(version.parse(flask.__version__) >= version.parse("1.1"),
206+
"Flask 1.1 changed interception behavior, so after request handlers are always run. "
207+
"This obviates the need for our hacky interception")
201208
def test_acl_uncaught_exception_500(self):
202209
'''
203210
Uncaught exceptions will trigger Flask's internal exception

tests/extension/test_app_extension.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ class AppExtensionString(FlaskCorsTestCase):
204204
def setUp(self):
205205
self.app = Flask(__name__)
206206
CORS(self.app, resources=r'/api/*',
207-
headers='Content-Type',
207+
allow_headers='Content-Type',
208208
expose_headers='X-Total-Count',
209209
origins='http://bar.com')
210210

@@ -225,6 +225,10 @@ def overridden():
225225
def index():
226226
return 'Welcome'
227227

228+
@self.app.route('/foo.txt')
229+
def foo_txt():
230+
return 'Welcome'
231+
228232
def test_exposed(self):
229233
for path in '/api/v1/foo', '/api/v1/bar':
230234
for resp in self.iter_responses(path, origin='http://bar.com'):

0 commit comments

Comments
 (0)