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