Added support for automagic OPTIONS

This commit is contained in:
Armin Ronacher 2010-07-12 23:04:24 +02:00
parent a532568680
commit 5e1b1030e8
7 changed files with 74 additions and 18 deletions

View file

@ -464,6 +464,9 @@ class Flask(_PackageBoundObject):
.. versionchanged:: 0.2
`view_func` parameter added.
.. versionchanged:: 0.6
`OPTIONS` is added automatically as method.
:param rule: the URL rule as string
:param endpoint: the endpoint for the registered URL rule. Flask
itself assumes the name of the view function as
@ -471,15 +474,27 @@ class Flask(_PackageBoundObject):
:param view_func: the function to call when serving a request to the
provided endpoint
:param options: the options to be forwarded to the underlying
:class:`~werkzeug.routing.Rule` object
:class:`~werkzeug.routing.Rule` object. A change
to Werkzeug is handling of method options. methods
is a list of methods this rule should be limited
to (`GET`, `POST` etc.). By default a rule
just listens for `GET` (and implicitly `HEAD`).
Starting with Flask 0.6, `OPTIONS` is implicitly
added and handled by the standard request handling.
"""
if endpoint is None:
assert view_func is not None, 'expected view func if endpoint ' \
'is not provided.'
endpoint = view_func.__name__
options['endpoint'] = endpoint
options.setdefault('methods', ('GET',))
self.url_map.add(Rule(rule, **options))
methods = options.pop('methods', ('GET',))
provide_automatic_options = False
if 'OPTIONS' not in methods:
methods = tuple(methods) + ('OPTIONS',)
provide_automatic_options = True
rule = Rule(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
self.url_map.add(rule)
if view_func is not None:
self.view_functions[endpoint] = view_func
@ -539,8 +554,10 @@ class Flask(_PackageBoundObject):
:param rule: the URL rule as string
:param methods: a list of methods this rule should be limited
to (``GET``, ``POST`` etc.). By default a rule
just listens for ``GET`` (and implicitly ``HEAD``).
to (`GET`, `POST` etc.). By default a rule
just listens for `GET` (and implicitly `HEAD`).
Starting with Flask 0.6, `OPTIONS` is implicitly
added and handled by the standard request handling.
:param subdomain: specifies the rule for the subdomain in case
subdomain matching is in use.
:param strict_slashes: can be used to disable the strict slashes
@ -650,7 +667,15 @@ class Flask(_PackageBoundObject):
try:
if req.routing_exception is not None:
raise req.routing_exception
return self.view_functions[req.endpoint](**req.view_args)
rule = req.url_rule
# 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
# 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)

View file

@ -38,8 +38,9 @@ class _RequestContext(object):
self.flashes = None
try:
self.request.endpoint, self.request.view_args = \
self.url_adapter.match()
url_rule, self.request.view_args = \
self.url_adapter.match(return_rule=True)
self.request.url_rule = url_rule
except HTTPException, e:
self.request.routing_exception = e

View file

@ -15,6 +15,7 @@ import posixpath
import mimetypes
from time import time
from zlib import adler32
from functools import wraps
# try to load the best simplejson implementation available. If JSON
# is not installed, we add a failing class.

View file

@ -24,11 +24,12 @@ class Request(RequestBase):
:attr:`~flask.Flask.request_class` to your subclass.
"""
#: the endpoint that matched the request. This in combination with
#: :attr:`view_args` can be used to reconstruct the same or a
#: modified URL. If an exception happened when matching, this will
#: be `None`.
endpoint = None
#: the internal URL rule that matched the request. This can be
#: useful to inspect which methods are allowed for the URL from
#: a before/after handler (``request.url_rule.methods``) etc.
#:
#: .. versionadded:: 0.6
url_rule = None
#: a dict of view arguments that matched the request. If an exception
#: happened when matching, this will be `None`.
@ -40,6 +41,16 @@ class Request(RequestBase):
#: something similar.
routing_exception = None
@property
def endpoint(self):
"""The endpoint that matched the request. This in combination with
:attr:`view_args` can be used to reconstruct the same or a
modified URL. If an exception happened when matching, this will
be `None`.
"""
if self.url_rule is not None:
return self.url_rule.endpoint
@property
def module(self):
"""The name of the current module"""