mirror of https://github.com/pallets/flask.git
Fixed an issue where the default `OPTIONS` response was
not exposing all valid methods in the `Allow` header. This fixes #97 Signed-off-by: Armin Ronacher <armin.ronacher@active-4.com>
This commit is contained in:
parent
8a14a875d2
commit
dbf55de7e8
3
CHANGES
3
CHANGES
|
@ -13,6 +13,9 @@ Version 0.6.1
|
||||||
|
|
||||||
Bugfix release, release date to be announced.
|
Bugfix release, release date to be announced.
|
||||||
|
|
||||||
|
- Fixed an issue where the default `OPTIONS` response was
|
||||||
|
not exposing all valid methods in the `Allow` header.
|
||||||
|
|
||||||
Version 0.6
|
Version 0.6
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
23
flask/app.py
23
flask/app.py
|
@ -19,7 +19,8 @@ from jinja2 import Environment
|
||||||
|
|
||||||
from werkzeug import ImmutableDict
|
from werkzeug import ImmutableDict
|
||||||
from werkzeug.routing import Map, Rule
|
from werkzeug.routing import Map, Rule
|
||||||
from werkzeug.exceptions import HTTPException, InternalServerError
|
from werkzeug.exceptions import HTTPException, InternalServerError, \
|
||||||
|
MethodNotAllowed
|
||||||
|
|
||||||
from .helpers import _PackageBoundObject, url_for, get_flashed_messages, \
|
from .helpers import _PackageBoundObject, url_for, get_flashed_messages, \
|
||||||
_tojson_filter, _endpoint_from_view_func
|
_tojson_filter, _endpoint_from_view_func
|
||||||
|
@ -689,14 +690,28 @@ class Flask(_PackageBoundObject):
|
||||||
# if we provide automatic options for this URL and the
|
# if we provide automatic options for this URL and the
|
||||||
# request came with the OPTIONS method, reply automatically
|
# request came with the OPTIONS method, reply automatically
|
||||||
if rule.provide_automatic_options and req.method == 'OPTIONS':
|
if rule.provide_automatic_options and req.method == 'OPTIONS':
|
||||||
rv = self.response_class()
|
return self._make_default_options_response()
|
||||||
rv.allow.update(rule.methods)
|
|
||||||
return rv
|
|
||||||
# otherwise dispatch to the handler for that endpoint
|
# otherwise dispatch to the handler for that endpoint
|
||||||
return self.view_functions[rule.endpoint](**req.view_args)
|
return self.view_functions[rule.endpoint](**req.view_args)
|
||||||
except HTTPException, e:
|
except HTTPException, e:
|
||||||
return self.handle_http_exception(e)
|
return self.handle_http_exception(e)
|
||||||
|
|
||||||
|
def _make_default_options_response(self):
|
||||||
|
# This would be nicer in Werkzeug 0.7, which however currently
|
||||||
|
# is not released. Werkzeug 0.7 provides a method called
|
||||||
|
# allowed_methods() that returns all methods that are valid for
|
||||||
|
# a given path.
|
||||||
|
methods = []
|
||||||
|
try:
|
||||||
|
_request_ctx_stack.top.url_adapter.match(method='--')
|
||||||
|
except MethodNotAllowed, e:
|
||||||
|
methods = e.valid_methods
|
||||||
|
except HTTPException, e:
|
||||||
|
pass
|
||||||
|
rv = self.response_class()
|
||||||
|
rv.allow.update(methods)
|
||||||
|
return rv
|
||||||
|
|
||||||
def make_response(self, rv):
|
def make_response(self, rv):
|
||||||
"""Converts the return value from a view function to a real
|
"""Converts the return value from a view function to a real
|
||||||
response object that is an instance of :attr:`response_class`.
|
response object that is an instance of :attr:`response_class`.
|
||||||
|
|
|
@ -120,6 +120,17 @@ class BasicFunctionalityTestCase(unittest.TestCase):
|
||||||
assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST']
|
assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST']
|
||||||
assert rv.data == ''
|
assert rv.data == ''
|
||||||
|
|
||||||
|
def test_options_on_multiple_rules(self):
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
@app.route('/', methods=['GET', 'POST'])
|
||||||
|
def index():
|
||||||
|
return 'Hello World'
|
||||||
|
@app.route('/', methods=['PUT'])
|
||||||
|
def index_put():
|
||||||
|
return 'Aha!'
|
||||||
|
rv = app.test_client().open('/', method='OPTIONS')
|
||||||
|
assert sorted(rv.allow) == ['GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
|
||||||
|
|
||||||
def test_request_dispatching(self):
|
def test_request_dispatching(self):
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
|
|
Loading…
Reference in New Issue