From d3eb92d95a694905a80668dcde1fb49e2d08f388 Mon Sep 17 00:00:00 2001 From: Guo Xiang Tan Date: Thu, 3 Jul 2014 21:32:14 -0700 Subject: Avoid duplicating routes for HEAD requests. Follow up to rails#15321 Instead of duplicating the routes, we will first match the HEAD request to HEAD routes. If no match is found, we will then map the HEAD request to GET routes. --- actionpack/lib/action_dispatch/http/request.rb | 6 ++++ actionpack/lib/action_dispatch/journey/router.rb | 40 ++++++++++++++---------- 2 files changed, 29 insertions(+), 17 deletions(-) (limited to 'actionpack/lib') diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index f35289253b..c441f7f95b 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -105,6 +105,12 @@ module ActionDispatch @request_method ||= check_method(env["REQUEST_METHOD"]) end + def request_method=(request_method) #:nodoc: + if check_method(request_method) + @request_method = env["REQUEST_METHOD"] = request_method + end + end + # Returns a symbol form of the #request_method def request_method_symbol HTTP_METHOD_LOOKUP[request_method] diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb index 21817b374c..9131b65380 100644 --- a/actionpack/lib/action_dispatch/journey/router.rb +++ b/actionpack/lib/action_dispatch/journey/router.rb @@ -101,11 +101,13 @@ module ActionDispatch r.path.match(req.path_info) } - if req.env["REQUEST_METHOD"] === "HEAD" - routes.concat get_routes_as_head(routes) - end + routes = + if req.request_method == "HEAD" + match_head_routes(routes, req) + else + match_routes(routes, req) + end - routes.select! { |r| r.matches?(req) } routes.sort_by!(&:precedence) routes.map! { |r| @@ -118,19 +120,23 @@ module ActionDispatch } end - def get_routes_as_head(routes) - precedence = (routes.map(&:precedence).max || 0) + 1 - routes.select { |r| - r.verb === "GET" && !(r.verb === "HEAD") - }.map! { |r| - Route.new(r.name, - r.app, - r.path, - r.conditions.merge(request_method: "HEAD"), - r.defaults).tap do |route| - route.precedence = r.precedence + precedence - end - } + def match_head_routes(routes, req) + head_routes = match_routes(routes, req) + + if head_routes.empty? + begin + req.request_method = "GET" + match_routes(routes, req) + ensure + req.request_method = "HEAD" + end + else + head_routes + end + end + + def match_routes(routes, req) + routes.select { |r| r.matches?(req) } end end end -- cgit v1.2.3