Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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>
  • Loading branch information...
commit dbf55de7e8bfcf7cde967aa72ea006b764d484ac 1 parent 8a14a87
Armin Ronacher authored
Showing with 33 additions and 4 deletions.
  1. +3 −0  CHANGES
  2. +19 −4 flask/app.py
  3. +11 −0 tests/flask_tests.py
3  CHANGES
View
@@ -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
View
@@ -19,7 +19,8 @@
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 @@ def dispatch_request(self):
# 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`.
11 tests/flask_tests.py
View
@@ -120,6 +120,17 @@ def index():
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('/')
Please sign in to comment.
Something went wrong with that request. Please try again.