Anonymous avatar 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.

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
 -----------

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')

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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.