Browse Source

Merge pull request #2249 from davidism/provide-automatic-options

Continue #1489: Add kwarg to disable auto OPTIONS on add_url_rule
pull/1936/merge
David Lord 8 years ago committed by GitHub
parent
commit
9569e8c956
  1. 4
      CHANGES
  2. 7
      flask/app.py
  3. 50
      tests/test_basic.py

4
CHANGES

@ -21,7 +21,11 @@ Major release, unreleased
- ``send_file`` supports Unicode in ``attachment_filename``. (`#2223`_) - ``send_file`` supports Unicode in ``attachment_filename``. (`#2223`_)
- Pass ``_scheme`` argument from ``url_for`` to ``handle_build_error``. - Pass ``_scheme`` argument from ``url_for`` to ``handle_build_error``.
(`#2017`_) (`#2017`_)
- Add support for ``provide_automatic_options`` in ``add_url_rule`` to disable
adding OPTIONS method when the ``view_func`` argument is not a class.
(`#1489`_).
.. _#1489: https://github.com/pallets/flask/pull/1489
.. _#2017: https://github.com/pallets/flask/pull/2017 .. _#2017: https://github.com/pallets/flask/pull/2017
.. _#2223: https://github.com/pallets/flask/pull/2223 .. _#2223: https://github.com/pallets/flask/pull/2223

7
flask/app.py

@ -980,7 +980,7 @@ class Flask(_PackageBoundObject):
return iter(self._blueprint_order) return iter(self._blueprint_order)
@setupmethod @setupmethod
def add_url_rule(self, rule, endpoint=None, view_func=None, **options): def add_url_rule(self, rule, endpoint=None, view_func=None, provide_automatic_options=None, **options):
"""Connects a URL rule. Works exactly like the :meth:`route` """Connects a URL rule. Works exactly like the :meth:`route`
decorator. If a view_func is provided it will be registered with the decorator. If a view_func is provided it will be registered with the
endpoint. endpoint.
@ -1020,6 +1020,10 @@ class Flask(_PackageBoundObject):
endpoint endpoint
:param view_func: the function to call when serving a request to the :param view_func: the function to call when serving a request to the
provided endpoint provided endpoint
:param provide_automatic_options: controls whether the ``OPTIONS``
method should be added automatically. This can also be controlled
by setting the ``view_func.provide_automatic_options = False``
before adding the rule.
:param options: the options to be forwarded to the underlying :param options: the options to be forwarded to the underlying
:class:`~werkzeug.routing.Rule` object. A change :class:`~werkzeug.routing.Rule` object. A change
to Werkzeug is handling of method options. methods to Werkzeug is handling of method options. methods
@ -1049,6 +1053,7 @@ class Flask(_PackageBoundObject):
# starting with Flask 0.8 the view_func object can disable and # starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling. # force-enable the automatic options handling.
if provide_automatic_options is None:
provide_automatic_options = getattr(view_func, provide_automatic_options = getattr(view_func,
'provide_automatic_options', None) 'provide_automatic_options', None)

50
tests/test_basic.py

@ -50,7 +50,7 @@ def test_options_on_multiple_rules():
assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'] assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
def test_options_handling_disabled(): def test_provide_automatic_options_attr():
app = flask.Flask(__name__) app = flask.Flask(__name__)
def index(): def index():
@ -70,6 +70,54 @@ def test_options_handling_disabled():
assert sorted(rv.allow) == ['OPTIONS'] assert sorted(rv.allow) == ['OPTIONS']
def test_provide_automatic_options_kwarg():
app = flask.Flask(__name__)
def index():
return flask.request.method
def more():
return flask.request.method
app.add_url_rule('/', view_func=index, provide_automatic_options=False)
app.add_url_rule(
'/more', view_func=more, methods=['GET', 'POST'],
provide_automatic_options=False
)
c = app.test_client()
assert c.get('/').data == b'GET'
rv = c.post('/')
assert rv.status_code == 405
assert sorted(rv.allow) == ['GET', 'HEAD']
# Older versions of Werkzeug.test.Client don't have an options method
if hasattr(c, 'options'):
rv = c.options('/')
else:
rv = c.open('/', method='OPTIONS')
assert rv.status_code == 405
rv = c.head('/')
assert rv.status_code == 200
assert not rv.data # head truncates
assert c.post('/more').data == b'POST'
assert c.get('/more').data == b'GET'
rv = c.delete('/more')
assert rv.status_code == 405
assert sorted(rv.allow) == ['GET', 'HEAD', 'POST']
if hasattr(c, 'options'):
rv = c.options('/more')
else:
rv = c.open('/more', method='OPTIONS')
assert rv.status_code == 405
def test_request_dispatching(): def test_request_dispatching():
app = flask.Flask(__name__) app = flask.Flask(__name__)

Loading…
Cancel
Save