1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
# frozen_string_literal: true
require 'grape/router/pattern'
require 'grape/router/attribute_translator'
require 'forwardable'
require 'pathname'
module Grape
class Router
class Route
ROUTE_ATTRIBUTE_REGEXP = /route_([_a-zA-Z]\w*)/.freeze
SOURCE_LOCATION_REGEXP = /^(.*?):(\d+?)(?::in `.+?')?$/.freeze
FIXED_NAMED_CAPTURES = %w[format version].freeze
attr_accessor :pattern, :translator, :app, :index, :options
alias attributes translator
extend Forwardable
def_delegators :pattern, :path, :origin
delegate Grape::Router::AttributeTranslator::ROUTE_ATTRIBUTES => :attributes
def method_missing(method_id, *arguments)
match = ROUTE_ATTRIBUTE_REGEXP.match(method_id.to_s)
if match
method_name = match.captures.last.to_sym
warn_route_methods(method_name, caller(1).shift)
@options[method_name]
else
super
end
end
def respond_to_missing?(method_id, _)
ROUTE_ATTRIBUTE_REGEXP.match?(method_id.to_s)
end
def route_method
warn_route_methods(:method, caller(1).shift, :request_method)
request_method
end
def route_path
warn_route_methods(:path, caller(1).shift)
pattern.path
end
def initialize(method, pattern, **options)
method_s = method.to_s
method_upcase = Grape::Http::Headers.find_supported_method(method_s) || method_s.upcase
@options = options.merge(method: method_upcase)
@pattern = Pattern.new(pattern, **options)
@translator = AttributeTranslator.new(**options, request_method: method_upcase)
end
def exec(env)
@app.call(env)
end
def apply(app)
@app = app
self
end
def match?(input)
translator.respond_to?(:forward_match) && translator.forward_match ? input.start_with?(pattern.origin) : pattern.match?(input)
end
def params(input = nil)
if input.nil?
pattern.named_captures.keys.each_with_object(translator.params) do |(key), defaults|
defaults[key] ||= '' unless FIXED_NAMED_CAPTURES.include?(key) || defaults.key?(key)
end
else
parsed = pattern.params(input)
parsed ? parsed.delete_if { |_, value| value.nil? }.symbolize_keys : {}
end
end
private
def warn_route_methods(name, location, expected = nil)
path, line = *location.scan(SOURCE_LOCATION_REGEXP).first
path = File.realpath(path) if Pathname.new(path).relative?
expected ||= name
warn <<~WARNING
#{path}:#{line}: The route_xxx methods such as route_#{name} have been deprecated, please use #{expected}.
WARNING
end
end
end
end
|