Class: Jets::Controller::Middleware::Local::RouteMatcher

Inherits:
Object
  • Object
show all
Defined in:
lib/jets/controller/middleware/local/route_matcher.rb

Instance Method Summary collapse

Constructor Details

#initialize(env) ⇒ RouteMatcher

Returns a new instance of RouteMatcher.



3
4
5
# File 'lib/jets/controller/middleware/local/route_matcher.rb', line 3

def initialize(env)
  @env = env
end

Instance Method Details

#capture_detection(route_path, actual_path) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/jets/controller/middleware/local/route_matcher.rb', line 87

def capture_detection(route_path, actual_path)
  # changes path to a string used for a regexp
  # posts/:id/edit => posts\/(.*)\/edit

  regexp_string = route_path.split('/').map do |s|
                    s.include?(':') ? Jets::Route::CAPTURE_REGEX : s
                  end.join('\/')
  # make sure beginning and end of the string matches
  regexp_string = "^#{regexp_string}$"

  regexp = Regexp.new(regexp_string)
  !!regexp.match(actual_path) # could be true or false
end

#find_routeObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/jets/controller/middleware/local/route_matcher.rb', line 7

def find_route
  reset_routes!
  # Precedence:
  # 1. Routes with no captures get highest precedence: posts/new
  # 2. Then we consider the routes with captures: post/:id
  #
  # Within these 2 groups we consider the routes with the longest path first
  # since posts/:id and posts/:id/edit can both match.
  routes = router.ordered_routes
  route = routes.find do |r|
    route_found?(r)
  end
  route
end

#proxy_detection(route_path, actual_path) ⇒ Object

catchall/globbing/wildcard/proxy routes. Examples:

get "files/*path", to: "files#show"
get "others/*rest", to: "others#show"
get "*catchall", to: "public_files#show" # last catchall route for Jets


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/jets/controller/middleware/local/route_matcher.rb', line 63

def proxy_detection(route_path, actual_path)
  # drop the proxy_segment
  leading_path = route_path.split('/')[0..-2].join('/')

  # get "*catchall", to: "public_files#show"
  if leading_path.empty? # This is the last catchall route "*catchall"
    return true # always return true here because the entire path
    # will always match
  end

  # Other types of wildcard route:
  #
  #    get "files/*path", to: "files#show"
  #    get "others/*rest", to: "others#show"
  unless leading_path.ends_with?('/')
    # Ensure trailing slash to make pattern matching stricter
    leading_path = "#{leading_path}/"
  end

  pattern = "^#{leading_path}"
  regexp = Regexp.new(pattern)
  !!regexp.match(actual_path) # could be true or false
end

#reset_routes!Object

“hot reload” for development



23
24
25
26
27
28
# File 'lib/jets/controller/middleware/local/route_matcher.rb', line 23

def reset_routes!
  return unless Jets.env.development?

  Jets::Router.clear!
  Jets.application.load_routes
end

#route_found?(route) ⇒ Boolean

Returns:

  • (Boolean)


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
# File 'lib/jets/controller/middleware/local/route_matcher.rb', line 30

def route_found?(route)
  request_method = @env["REQUEST_METHOD"] || "GET"
  actual_path = @env["PATH_INFO"].sub(/^\//,'') # remove beginning slash

  # Immediately stop checking when the request method: GET, POST, ANY, etc
  # doesnt match.
  return false if request_method != route.method and route.method != "ANY"

  path = route.path

  if actual_path == path
    # regular string match detection
    return true # exact route matches are highest precedence
  end

  # Check path for route capture and wildcard matches:
  # A colon (:) means the variable has a variable
  if path.include?(':') # 2nd highest precedence
    capture_detection(path, actual_path) # early return true or false
  # A star (*) means the variable has a glob
  elsif path.include?('*') # lowest precedence
    proxy_detection(path, actual_path) # early return true or false
  else
    false # reach here, means no route matched
  end
end

#routerObject



101
102
103
104
# File 'lib/jets/controller/middleware/local/route_matcher.rb', line 101

def router
  return @router if @router
  @router = Jets.application.routes
end