aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r--actionpack/lib/action_dispatch/journey/nodes/node.rb4
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb65
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb35
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb1
4 files changed, 79 insertions, 26 deletions
diff --git a/actionpack/lib/action_dispatch/journey/nodes/node.rb b/actionpack/lib/action_dispatch/journey/nodes/node.rb
index 542e8c6577..d069bf0205 100644
--- a/actionpack/lib/action_dispatch/journey/nodes/node.rb
+++ b/actionpack/lib/action_dispatch/journey/nodes/node.rb
@@ -41,6 +41,7 @@ module ActionDispatch
def literal?; false; end
def terminal?; false; end
def star?; false; end
+ def cat?; false; end
end
class Terminal < Node # :nodoc:
@@ -72,11 +73,13 @@ module ActionDispatch
class Symbol < Terminal # :nodoc:
attr_accessor :regexp
alias :symbol :regexp
+ attr_reader :name
DEFAULT_EXP = /[^\.\/\?]+/
def initialize(left)
super
@regexp = DEFAULT_EXP
+ @name = left.tr '*:'.freeze, ''.freeze
end
def default_regexp?
@@ -115,6 +118,7 @@ module ActionDispatch
end
class Cat < Binary # :nodoc:
+ def cat?; true; end
def type; :CAT; end
end
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index d44c3d31d7..209cd20d80 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -8,18 +8,61 @@ module ActionDispatch
attr_accessor :precedence
+ module VerbMatchers
+ VERBS = %w{ DELETE GET HEAD OPTIONS LINK PATCH POST PUT TRACE UNLINK }
+ VERBS.each do |v|
+ class_eval <<-eoc
+ class #{v}
+ def self.verb; name.split("::").last; end
+ def self.call(req); req.#{v.downcase}?; end
+ end
+ eoc
+ end
+
+ class Unknown
+ attr_reader :verb
+
+ def initialize(verb)
+ @verb = verb
+ end
+
+ def call(request); @verb === request.request_method; end
+ end
+
+ class All
+ def self.call(_); true; end
+ def self.verb; ''; end
+ end
+
+ VERB_TO_CLASS = VERBS.each_with_object({ :all => All }) do |verb, hash|
+ klass = const_get verb
+ hash[verb] = klass
+ hash[verb.downcase] = klass
+ hash[verb.downcase.to_sym] = klass
+ end
+
+ end
+
+ def self.verb_matcher(verb)
+ VerbMatchers::VERB_TO_CLASS.fetch(verb) do
+ VerbMatchers::Unknown.new verb.to_s.dasherize.upcase
+ end
+ end
+
def self.build(name, app, path, constraints, required_defaults, defaults)
- new name, app, path, constraints, required_defaults, defaults
+ request_method_match = verb_matcher(constraints.delete(:request_method))
+ new name, app, path, constraints, required_defaults, defaults, request_method_match
end
##
# +path+ is a path constraint.
# +constraints+ is a hash of constraints to be applied to this route.
- def initialize(name, app, path, constraints, required_defaults, defaults)
+ def initialize(name, app, path, constraints, required_defaults, defaults, request_method_match)
@name = name
@app = app
@path = path
+ @request_method_match = request_method_match
@constraints = constraints
@defaults = defaults
@required_defaults = nil
@@ -96,7 +139,8 @@ module ActionDispatch
end
def matches?(request)
- constraints.all? do |method, value|
+ match_verb(request) &&
+ constraints.all? { |method, value|
case value
when Regexp, String
value === request.send(method).to_s
@@ -109,7 +153,7 @@ module ActionDispatch
else
value === request.send(method)
end
- end
+ }
end
def ip
@@ -117,11 +161,20 @@ module ActionDispatch
end
def requires_matching_verb?
- constraints[:request_method]
+ !@request_method_match.all? { |x| x == VerbMatchers::All }
end
def verb
- constraints[:request_method] || //
+ %r[^#{verbs.join('|')}$]
+ end
+
+ private
+ def verbs
+ @request_method_match.map(&:verb)
+ end
+
+ def match_verb(request)
+ @request_method_match.any? { |m| m.call request }
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index e964bf59e0..c1134d16ad 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -144,12 +144,13 @@ module ActionDispatch
end
def make_route(name, precedence)
- route = Journey::Route.build(name,
+ route = Journey::Route.new(name,
application,
path,
conditions,
required_defaults,
- defaults)
+ defaults,
+ request_method)
route.precedence = precedence
route
@@ -170,38 +171,32 @@ module ActionDispatch
def build_conditions(current_conditions, request_class)
conditions = current_conditions.dup
- # Rack-Mount requires that :request_method be a regular expression.
- # :request_method represents the HTTP verb that matches this route.
- #
- # Here we munge values before they get sent on to rack-mount.
- unless @via == [:all]
- verbs = @via.map { |m| m.to_s.dasherize.upcase }
- conditions[:request_method] = %r[^#{verbs.join('|')}$]
- end
-
conditions.keep_if do |k, _|
request_class.public_method_defined?(k)
end
end
private :build_conditions
+ def request_method
+ @via.map { |x| Journey::Route.verb_matcher(x) }
+ end
+ private :request_method
+
JOINED_SEPARATORS = SEPARATORS.join # :nodoc:
def build_path(ast, requirements, anchor)
pattern = Journey::Path::Pattern.new(ast, requirements, JOINED_SEPARATORS, anchor)
- builder = Journey::GTG::Builder.new ast
-
# Get all the symbol nodes followed by literals that are not the
# dummy node.
- symbols = ast.grep(Journey::Nodes::Symbol).find_all { |n|
- builder.followpos(n).first.literal?
- }
+ symbols = ast.find_all { |n|
+ n.cat? && n.left.symbol? && n.right.cat? && n.right.left.literal?
+ }.map(&:left)
# Get all the symbol nodes preceded by literals.
- symbols.concat ast.find_all(&:literal?).map { |n|
- builder.followpos(n).first
- }.find_all(&:symbol?)
+ symbols.concat ast.find_all { |n|
+ n.cat? && n.left.literal? && n.right.cat? && n.right.left.symbol?
+ }.map { |n| n.right.left }
symbols.each { |x|
x.regexp = /(?:#{Regexp.union(x.regexp, '-')})+/
@@ -640,7 +635,7 @@ module ActionDispatch
# Query if the following named route was already defined.
def has_named_route?(name)
- @set.named_routes.routes[name.to_sym]
+ @set.named_routes.key? name
end
private
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 30e308119d..20926012b4 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -89,6 +89,7 @@ module ActionDispatch
class NamedRouteCollection
include Enumerable
attr_reader :routes, :url_helpers_module, :path_helpers_module
+ private :routes
def initialize
@routes = {}