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.
|
||||
|
||||
- Fixed an issue where the default `OPTIONS` response was
|
||||
not exposing all valid methods in the `Allow` header.
|
||||
|
||||
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.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, \
|
||||
_tojson_filter, _endpoint_from_view_func
|
||||
|
@ -689,14 +690,28 @@ class Flask(_PackageBoundObject):
|
|||
# if we provide automatic options for this URL and the
|
||||
# request came with the OPTIONS method, reply automatically
|
||||
if rule.provide_automatic_options and req.method == 'OPTIONS':
|
||||
rv = self.response_class()
|
||||
rv.allow.update(rule.methods)
|
||||
return rv
|
||||
return self._make_default_options_response()
|
||||
# otherwise dispatch to the handler for that endpoint
|
||||
return self.view_functions[rule.endpoint](**req.view_args)
|
||||
except HTTPException, 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):
|
||||
"""Converts the return value from a view function to a real
|
||||
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 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):
|
||||
app = flask.Flask(__name__)
|
||||
@app.route('/')
|
||||
|
|
Loading…
Reference in New Issue