-
-
Notifications
You must be signed in to change notification settings - Fork 16.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement support for X-HTTP-Method-Override in flask.views.MethodView. #582
Conversation
When an incoming request contains the X-HTTP-Method-Override header, the value of that header is used as the view method to be executed instead of the original incoming HTTP verb.
+100, I'd love to see this enabled in Flask by default. However, I believe there's a built-in way to do this with werkzeug. @mitsuhiko ? |
I'm wary of HTTP headers that start with class HTTPMethodOverrideMiddleware(object):
"""The HTTPMethodOverrideMiddleware middleware implements the hidden HTTP
method technique. Not all web browsers support every HTTP method, such as
DELETE and PUT. Using a querystring parameter is the easiest implementation
given Werkzeug and how middleware is implemented. The following is an
example of how to create a form with a PUT method:
<form action="/stuff/id?__METHOD_OVERRIDE__=PUT" method="POST">
...
</form>
"""
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
if '__METHOD_OVERRIDE__' in environ.get('QUERY_STRING', ''):
args = url_decode(environ['QUERY_STRING'])
method = args.get('__METHOD_OVERRIDE__').upper()
if method in ['GET', 'POST', 'PUT', 'DELETE']:
method = method.encode('ascii', 'replace')
environ['REQUEST_METHOD'] = method
return self.app(environ, start_response) |
@mattupstate Agreed, but there are some situations where I do like your middleware solution idea, but I'd rather not pollute my query strings with metadata that is better represented in a header. |
In some cases it is quite convenient to use a query string, especially in plain old HTML views that POST forms. Headers are nice with clients that are more full featured. I once looked into seeing if a header value could be retrieved in the middleware but I think it would have proved difficult since the environ wasn't "parsed" yet but I'm also not very well versed in WSGI yet. I think it would be ideal if it's possible to check for either a query string or header in the middleware. |
Any thoughts, @mitsuhiko? |
Building on what @mattupstate posted here is an example that looks for an class HTTPMethodOverrideMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
method = environ.get('HTTP_X_HTTP_METHOD_OVERRIDE', '').upper()
if method in ['GET', 'POST', 'PUT', 'DELETE']:
method = method.encode('ascii', 'replace')
environ['REQUEST_METHOD'] = method
return self.app(environ, start_response) |
This should indeed be fixed on the WSGI layer for consistency. It's easy enough to make a middleware, maybe we should put it into the docs. |
The Using For further reference, also see @jacobian's note against this similar pull request: https://github.com/toastdriven/django-tastypie/pull/351 |
When an incoming request contains the X-HTTP-Method-Override header, the
value of that header is used as the view method to be executed instead
of the original incoming HTTP verb.
This helps support dumb(er) webservers and proxies that don't understand newer HTTP verbs (e.g. PATCH), of which Amazon's Elastic Load Balancer service is a member.
I only added the functionality to
flask.views.MethodView
, because I was unsure about what would be a good way to do it with the standarddispatch_request
; developers often introspect the HTTP method inside of decorator-based routes when supporting more than one verb in a route, so should therequest.method
value be overridden completely, or should devs be required to check for the X-HTTP-Method-Override header themselves? Neither option seems very appealing to me.