Skip to content

Commit

Permalink
Fix request path normalization (#272)
Browse files Browse the repository at this point in the history
* Normalize path before evaluating resource rules
  • Loading branch information
corydolphin committed Aug 30, 2020
1 parent 5c6e05e commit 67c4b2c
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 16 deletions.
23 changes: 12 additions & 11 deletions .travis.yml
Expand Up @@ -7,23 +7,24 @@ python:
- '3.4'
- '3.5'
- '3.6'
- '3.7'
- '3.8'
- pypy

# from https://github.com/travis-ci/travis-ci/issues/9815
# https://github.com/travis-ci/travis-ci/issues/9069#issuecomment-425720905
# Enable 3.7 without globally enabling sudo and dist: xenial for other build jobs
matrix:
include:
- python: 3.7
dist: xenial
sudo: true
exclude:
- python: 3.4
- env:
- DEPEENDENCIES="flask==1.1"

env:
- FLASK=0.10.1
- FLASK=0.10
- DEPEENDENCIES="flask==0.10.1 werkzeug==0.16.1" # pin werkzeug for Flask 10, 10.1 since Flask does not pin it itself.
- DEPEENDENCIES="flask==0.10 werkzeug==0.16.1"
- DEPEENDENCIES="flask==1.0"
- DEPEENDENCIES="flask==1.1"

install:
- pip install -U setuptools pep8 six coverage docutils pygments flask==$FLASK
- pip install -U setuptools pep8 six coverage docutils pygments packaging $DEPEENDENCIES

script:
- coverage erase
Expand Down
2 changes: 1 addition & 1 deletion examples/app_based_example.py
Expand Up @@ -124,7 +124,7 @@ def get_exception():
Browsers will first make a preflight request to verify that the resource
allows cross-origin POSTs with a JSON Content-Type, which can be simulated
as:
$ curl --include -X OPTIONS http://127.0.0.1:5000/exception \
$ curl --include -X OPTIONS http://127.0.0.1:5000/api/exception \
--header Access-Control-Request-Method:POST \
--header Access-Control-Request-Headers:Content-Type \
--header Origin:www.examplesite.com
Expand Down
8 changes: 6 additions & 2 deletions flask_cors/extension.py
Expand Up @@ -10,6 +10,10 @@
"""
from flask import request
from .core import *
try:
from urllib.parse import unquote_plus
except ImportError:
from urllib import unquote_plus

LOG = logging.getLogger(__name__)

Expand Down Expand Up @@ -173,9 +177,9 @@ def cors_after_request(resp):
if resp.headers is not None and resp.headers.get(ACL_ORIGIN):
LOG.debug('CORS have been already evaluated, skipping')
return resp

normalized_path = unquote_plus(request.path)
for res_regex, res_options in resources:
if try_match(request.path, res_regex):
if try_match(normalized_path, res_regex):
LOG.debug("Request to '%s' matches CORS resource '%s'. Using options: %s",
request.path, get_regexp_pattern(res_regex), res_options)
set_cors_headers(resp, res_options)
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -33,7 +33,8 @@
platforms='any',
install_requires=install_requires,
tests_require=[
'nose'
'nose',
'packaging'
],
test_suite='nose.collector',
classifiers=[
Expand Down
7 changes: 7 additions & 0 deletions tests/decorator/test_exception_interception.py
Expand Up @@ -8,6 +8,10 @@
:copyright: (c) 2016 by Cory Dolphin.
:license: MIT, see LICENSE for more details.
"""
import unittest

import flask
from packaging import version
from ..base_test import FlaskCorsTestCase
from flask import Flask, abort
from flask_cors import *
Expand Down Expand Up @@ -198,6 +202,9 @@ def get_with_origins(path):
self.assertEqual(resp.status_code, 200)
self.assertFalse(ACL_ORIGIN in resp.headers)

@unittest.skipIf(version.parse(flask.__version__) >= version.parse("1.1"),
"Flask 1.1 changed interception behavior, so after request handlers are always run. "
"This obviates the need for our hacky interception")
def test_acl_uncaught_exception_500(self):
'''
Uncaught exceptions will trigger Flask's internal exception
Expand Down
6 changes: 5 additions & 1 deletion tests/extension/test_app_extension.py
Expand Up @@ -204,7 +204,7 @@ class AppExtensionString(FlaskCorsTestCase):
def setUp(self):
self.app = Flask(__name__)
CORS(self.app, resources=r'/api/*',
headers='Content-Type',
allow_headers='Content-Type',
expose_headers='X-Total-Count',
origins='http://bar.com')

Expand All @@ -225,6 +225,10 @@ def overridden():
def index():
return 'Welcome'

@self.app.route('/foo.txt')
def foo_txt():
return 'Welcome'

def test_exposed(self):
for path in '/api/v1/foo', '/api/v1/bar':
for resp in self.iter_responses(path, origin='http://bar.com'):
Expand Down

0 comments on commit 67c4b2c

Please sign in to comment.