Commits

Anonymous committed c3ffd26

`HEAD` is now implicitly added as method in the routing system if
`GET` is present. Not doing that was considered a bug because often
code assumed that this is the case and in web servers that do not
normalize `HEAD` to `GET` this could break `HEAD` requests.

  • Participants
  • Parent commits e6ad55f

Comments (0)

Files changed (3)

 - fixed a bug where log lines will be duplicated if an application uses
   :meth:`logging.basicConfig` (#499)
 - added secure password hashing and checking functions.
+- `HEAD` is now implicitly added as method in the routing system if
+  `GET` is present.  Not doing that was considered a bug because often
+  code assumed that this is the case and in web servers that do not
+  normalize `HEAD` to `GET` this could break `HEAD` requests.
 
 Version 0.6
 -----------

File tests/test_routing.py

 from werkzeug.wrappers import Response
 from werkzeug.datastructures import ImmutableDict
 from werkzeug.routing import Map, Rule, NotFound, BuildError, RequestRedirect, \
-     RuleTemplate, Submount, EndpointPrefix, Subdomain, UnicodeConverter
+     RuleTemplate, Submount, EndpointPrefix, Subdomain, UnicodeConverter, \
+     MethodNotAllowed
 from werkzeug.test import create_environ
 
 
     assert adapter.build('search') == '/search_get'
     assert adapter.build('search', method='GET') == '/search_get'
     assert adapter.build('search', method='POST') == '/search_post'
+
+
+def test_implicit_head():
+    """Test implicit HEAD in URL rules where GET is present"""
+    url_map = Map([
+        Rule('/get', methods=['GET'], endpoint='a'),
+        Rule('/post', methods=['POST'], endpoint='b')
+    ])
+    adapter = url_map.bind('example.org')
+    assert adapter.match('/get', method='HEAD') == ('a', {})
+    assert_raises(MethodNotAllowed, adapter.match, '/post', method='HEAD')

File werkzeug/routing.py

         endpoints for `POST` and `GET`.  If methods are defined and the path
         matches but the method matched against is not in this list or in the
         list of another rule for that path the error raised is of the type
-        `MethodNotAllowed` rather than `NotFound`.
+        `MethodNotAllowed` rather than `NotFound`.  If `GET` is present in the
+        list of methods and `HEAD` is not, `HEAD` is added automatically.
+
+        .. versionchanged:: 0.6.1
+           `HEAD` is now automatically added to the methods if `GET` is
+           present.  The reason for this is that existing code often did not
+           work properly in servers not rewriting `HEAD` to `GET`
+           automatically and it was not documented how `HEAD` should be
+           treated.  This was considered a bug in Werkzeug because of that.
 
     `strict_slashes`
         Override the `Map` setting for `strict_slashes` only for this rule. If
             self.methods = None
         else:
             self.methods = set([x.upper() for x in methods])
+            if 'HEAD' not in self.methods and 'GET' in self.methods:
+                self.methods.add('HEAD')
         self.endpoint = endpoint
         self.greediness = 0
         self.redirect_to = redirect_to