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
|
# frozen_string_literal: true
require 'forwardable'
require 'mustermann/grape'
require 'grape/util/cache'
module Grape
class Router
class Pattern
DEFAULT_PATTERN_OPTIONS = { uri_decode: true }.freeze
DEFAULT_SUPPORTED_CAPTURE = %i[format version].freeze
attr_reader :origin, :path, :pattern, :to_regexp
extend Forwardable
def_delegators :pattern, :named_captures, :params
def_delegators :to_regexp, :===
alias match? ===
def initialize(pattern, **options)
@origin = pattern
@path = build_path(pattern, **options)
@pattern = Mustermann::Grape.new(@path, **pattern_options(options))
@to_regexp = @pattern.to_regexp
end
private
def pattern_options(options)
capture = extract_capture(**options)
options = DEFAULT_PATTERN_OPTIONS.dup
options[:capture] = capture if capture.present?
options
end
def build_path(pattern, anchor: false, suffix: nil, **_options)
unless anchor || pattern.end_with?('*path')
pattern = +pattern
pattern << '/' unless pattern.end_with?('/')
pattern << '*path'
end
pattern = -pattern.split('/').tap do |parts|
parts[parts.length - 1] = "?#{parts.last}"
end.join('/') if pattern.end_with?('*path')
PatternCache[[pattern, suffix]]
end
def extract_capture(requirements: {}, **options)
requirements = {}.merge(requirements)
DEFAULT_SUPPORTED_CAPTURE.each_with_object(requirements) do |field, capture|
option = Array(options[field])
capture[field] = option.map(&:to_s) if option.present?
end
end
class PatternCache < Grape::Util::Cache
def initialize
@cache = Hash.new do |h, (pattern, suffix)|
h[[pattern, suffix]] = -"#{pattern}#{suffix}"
end
end
end
end
end
end
|