lib/grape/router.rb in grape-0.18.0 vs lib/grape/router.rb in grape-0.19.0
- old
+ new
@@ -17,20 +17,25 @@
path.sub!(%r{/+\Z}, '')
path = '/' if path == ''
path
end
+ def self.supported_methods
+ @supported_methods ||= Grape::Http::Headers::SUPPORTED_METHODS + ['*']
+ end
+
def initialize
@neutral_map = []
@map = Hash.new { |hash, key| hash[key] = [] }
@optimized_map = Hash.new { |hash, key| hash[key] = // }
end
def compile!
return if compiled
@union = Regexp.union(@neutral_map.map(&:regexp))
- map.each do |method, routes|
+ self.class.supported_methods.each do |method|
+ routes = map[method]
@optimized_map[method] = routes.map.with_index do |route, index|
route.index = index
route.regexp = /(?<_#{index}>#{route.pattern.to_regexp})/
end
@optimized_map[method] = Regexp.union(@optimized_map[method])
@@ -62,54 +67,69 @@
private
def identity(env)
route = nil
- response = transaction(env) do |input, method, routing_args|
+ response = transaction(env) do |input, method|
route = match?(input, method)
- if route
- env[Grape::Env::GRAPE_ROUTING_ARGS] = make_routing_args(routing_args, route, input)
- route.exec(env)
- end
+ process_route(route, env) if route
end
[response, route]
end
def rotation(env, exact_route = nil)
response = nil
- input, method, routing_args = *extract_required_args(env)
- routes_for(method).each do |route|
+ input, method = *extract_input_and_method(env)
+ map[method].each do |route|
next if exact_route == route
next unless route.match?(input)
- env[Grape::Env::GRAPE_ROUTING_ARGS] = make_routing_args(routing_args, route, input)
- response = route.exec(env)
+ response = process_route(route, env)
break unless cascade?(response)
end
response
end
def transaction(env)
- input, method, routing_args = *extract_required_args(env)
- response = yield(input, method, routing_args)
+ input, method = *extract_input_and_method(env)
+ response = yield(input, method)
return response if response && !(cascade = cascade?(response))
neighbor = greedy_match?(input)
- return unless neighbor
- (!cascade && neighbor) ? call_with_allow_headers(env, neighbor.allow_header, neighbor.endpoint) : nil
+ # If neighbor exists and request method is OPTIONS,
+ # return response by using #call_with_allow_headers.
+ return call_with_allow_headers(
+ env,
+ neighbor.allow_header,
+ neighbor.endpoint
+ ) if neighbor && method == 'OPTIONS' && !cascade
+
+ route = match?(input, '*')
+ if route
+ response = process_route(route, env)
+ return response if response && !(cascade = cascade?(response))
+ end
+
+ !cascade && neighbor ? call_with_allow_headers(env, neighbor.allow_header, neighbor.endpoint) : nil
end
+ def process_route(route, env)
+ input, = *extract_input_and_method(env)
+ routing_args = env[Grape::Env::GRAPE_ROUTING_ARGS]
+ env[Grape::Env::GRAPE_ROUTING_ARGS] = make_routing_args(routing_args, route, input)
+ route.exec(env)
+ end
+
def make_routing_args(default_args, route, input)
args = default_args || { route_info: route }
args.merge(route.params(input))
end
- def extract_required_args(env)
+ def extract_input_and_method(env)
input = string_for(env[Grape::Http::Headers::PATH_INFO])
method = env[Grape::Http::Headers::REQUEST_METHOD]
- routing_args = env[Grape::Env::GRAPE_ROUTING_ARGS]
- [input, method, routing_args]
+ [input, method]
end
def with_optimization
compile! unless compiled
yield || default_response
@@ -137,13 +157,9 @@
endpoint.call(env)
end
def cascade?(response)
response && response[1][Grape::Http::Headers::X_CASCADE] == 'pass'
- end
-
- def routes_for(method)
- map[method] + map['ANY']
end
def string_for(input)
self.class.normalize_path(input)
end