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.htmlmaster
parent
ff27f3a917
commit
807a487639
|
@ -75,6 +75,11 @@ class BaseApplication(object):
|
||||||
allowed_methods = self._find_attr(func, 'allowed_methods')
|
allowed_methods = self._find_attr(func, 'allowed_methods')
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
allowed_methods = milla.DEFAULT_METHODS
|
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:
|
if request.method not in allowed_methods:
|
||||||
allow_header = {'Allow': ', '.join(allowed_methods)}
|
allow_header = {'Allow': ', '.join(allowed_methods)}
|
||||||
if request.method == 'OPTIONS':
|
if request.method == 'OPTIONS':
|
||||||
|
@ -99,11 +104,7 @@ class BaseApplication(object):
|
||||||
if isinstance(response, _string) or not response:
|
if isinstance(response, _string) or not response:
|
||||||
response = request.ResponseClass(response)
|
response = request.ResponseClass(response)
|
||||||
|
|
||||||
if environ['REQUEST_METHOD'] == 'HEAD':
|
return response(environ, start_response)
|
||||||
start_response(response.status, response.headerlist)
|
|
||||||
return ''
|
|
||||||
else:
|
|
||||||
return response(environ, start_response)
|
|
||||||
|
|
||||||
def _call_after(self, func):
|
def _call_after(self, func):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue