This project is archived and is in readonly mode.

#182 ✓resolved
Chris Hapgood

Routes restricted to HEAD fail to be matched

Reported by Chris Hapgood | May 13th, 2008 @ 05:53 PM

Consider a route that is restricted to just HEAD requests. For example:

map.resource :session, :collection => {:status => :head}

This action can never be invoked due to the following:

Prior to the recognize_path phase of route recognition, the extract_request_environment method (in routing.rb) determines the request verb by calling request.method, which in turn... always converts :head to :get (line 35 of request.rb).

Comments and changes to this ticket

  • Chris Hapgood

    Chris Hapgood May 23rd, 2008 @ 01:22 PM

    "It makes no sense to restrict a route to just HEAD requests."

    That's a bit dogmatic (or should I say "opinionated"?). I need a low- cost action/resource that allows a (mobile web service) client to periodically authenticate or confirm authentication via HTTP_AUTH. Sure, I could make the client GET an existing resource (expensive for the server), but why? So we have a simple action (no DB, no calcs, no nothing!) that is only capable of returning header data.

    Once you accept that such a method deserves to live, it's easy to accept that it should be restricted to HEAD -it allows buggy clients to be spotted at the server with an exception being raised.

  • Tom Ward

    Tom Ward May 23rd, 2008 @ 02:33 PM

    It's my understanding that a HEAD request to a URI should always return exactly the same headers as a GET request to the same URI. By restricting methods allowed on the URI to only HEAD you would break this rule. A HEAD request would return either status code 200 or 401, while a GET request would return 405.

    I agree that your cheap authentication action deserves to exist, but it doesn't follow that it should be restricted to only handle HEAD. Instead, you should also handle GET, returning either a very simple body (such as just 'OK') or no body at all if you prefer. This would be just as cheap, without breaking the implicit HTTP contract.

  • Chris Hapgood

    Chris Hapgood May 23rd, 2008 @ 02:51 PM


    Thanks for taking the time to look at this ticket a second time. I accept that this request is not going to be implemented, and I can live with it.

    It might be a good idea to document this restriction because it is accepted when routes are built, but then fails with a contradictory error message at run time.

  • Tom Ward

    Tom Ward May 23rd, 2008 @ 03:05 PM

    Now that sounds like a valid bug which should certainly be fixed.

  • Lawrence Pit

    Lawrence Pit June 27th, 2008 @ 03:43 AM

    • Tag set to actionpack, routing

    fyi: from the CHANGELOG at

    Added GET-masquarading for HEAD, so request.method will return :get even for HEADs. This will help anyone relying on case request.method to automatically work with HEAD and map.resources will also allow HEADs to all GET actions. Rails automatically throws away the response content in a reply to HEAD, so you don't even need to worry about that.

    **If you, for whatever reason, still need to distinguish between GET and HEAD in some edge case, you can use Request#head? and even Request.headers["REQUEST_METHOD"] for get the "real" answer.**

  • Chris Hapgood

    Chris Hapgood June 27th, 2008 @ 04:11 AM

    Lawrence, good find. I guess that really puts a nail in the coffin.

  • Repository

    Repository July 19th, 2008 @ 02:16 AM

    • State changed from “invalid” to “resolved”

    (from [d39485078ec56e25a96e97d44b53498d8a1c7426]) Raise ArgumentError if an invalid method is specified as part of a route's conditions. Also raise an error if HEAD is specified as the method, as rails routes all HEAD requests through the equivalent GET, though doesn't return the response body [#182 state:resolved]

    Signed-off-by: Joshua Peek

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href=""></a>