From 807a4876393961f3eb9c6a873e243ec5b2f87b6c Mon Sep 17 00:00:00 2001 From: "Dustin C. Hatch" Date: Sun, 10 Jul 2016 20:28:26 -0500 Subject: [PATCH] app: Map HEAD requests to GET After much discussion, the WSGI community has mostly agreed that applications should not treat GET and HEAD requests differently. The HTTP specification practically demands that they are handled the same way by applications, with the exception that responses to HEAD requests do not send a body. When they are handled differently, there is an unfortunate tendency to over-optimize the HEAD request, causing discrepancies between the headers it returns and those returned by GET. Further, WSGI middleware may need access to the response body in order to properly manipulate the response (e.g. to rewrite links, etc.), which could effect the response to HEAD requests as well. This commit changes the behavior of `BaseApplication` to change the method of all `HEAD` requests to `GET` prior to dispatching them. `Request` objects now have a `real_method` attribute, which indicates the original method of the request. http://blog.dscpl.com.au/2009/10/wsgi-issues-with-http-head-requests.html --- src/milla/app.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/milla/app.py b/src/milla/app.py index 67e2392..e53f9ce 100644 --- a/src/milla/app.py +++ b/src/milla/app.py @@ -75,6 +75,11 @@ class BaseApplication(object): allowed_methods = self._find_attr(func, 'allowed_methods') except AttributeError: allowed_methods = milla.DEFAULT_METHODS + if request.method == 'HEAD': + request.real_method = 'HEAD' + request.method = 'GET' + else: + request.real_method = request.method if request.method not in allowed_methods: allow_header = {'Allow': ', '.join(allowed_methods)} if request.method == 'OPTIONS': @@ -99,11 +104,7 @@ class BaseApplication(object): if isinstance(response, _string) or not response: response = request.ResponseClass(response) - if environ['REQUEST_METHOD'] == 'HEAD': - start_response(response.status, response.headerlist) - return '' - else: - return response(environ, start_response) + return response(environ, start_response) def _call_after(self, func): try: