2016-07-26 10:03:17 -04:00
|
|
|
# frozen_string_literal: true
|
2016-08-02 13:47:59 -04:00
|
|
|
require 'rack'
|
2016-07-26 10:03:17 -04:00
|
|
|
|
|
|
|
module Sidekiq
|
|
|
|
module WebRouter
|
2018-02-16 16:11:54 -05:00
|
|
|
GET = 'GET'
|
|
|
|
DELETE = 'DELETE'
|
|
|
|
POST = 'POST'
|
|
|
|
PUT = 'PUT'
|
|
|
|
PATCH = 'PATCH'
|
|
|
|
HEAD = 'HEAD'
|
2016-07-26 10:03:17 -04:00
|
|
|
|
2018-02-16 16:11:54 -05:00
|
|
|
ROUTE_PARAMS = 'rack.route_params'
|
|
|
|
REQUEST_METHOD = 'REQUEST_METHOD'
|
|
|
|
PATH_INFO = 'PATH_INFO'
|
2016-07-26 10:03:17 -04:00
|
|
|
|
|
|
|
def get(path, &block)
|
|
|
|
route(GET, path, &block)
|
|
|
|
end
|
|
|
|
|
|
|
|
def post(path, &block)
|
|
|
|
route(POST, path, &block)
|
|
|
|
end
|
|
|
|
|
2016-07-29 16:56:52 -04:00
|
|
|
def put(path, &block)
|
|
|
|
route(PUT, path, &block)
|
|
|
|
end
|
|
|
|
|
|
|
|
def patch(path, &block)
|
|
|
|
route(PATCH, path, &block)
|
|
|
|
end
|
|
|
|
|
2016-07-28 22:36:21 -04:00
|
|
|
def delete(path, &block)
|
|
|
|
route(DELETE, path, &block)
|
|
|
|
end
|
|
|
|
|
2016-07-26 10:03:17 -04:00
|
|
|
def route(method, path, &block)
|
2016-07-29 16:56:52 -04:00
|
|
|
@routes ||= { GET => [], POST => [], PUT => [], PATCH => [], DELETE => [], HEAD => [] }
|
|
|
|
|
|
|
|
@routes[method] << WebRoute.new(method, path, block)
|
|
|
|
@routes[HEAD] << WebRoute.new(method, path, block) if method == GET
|
2016-07-26 10:03:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def match(env)
|
|
|
|
request_method = env[REQUEST_METHOD]
|
2016-08-02 13:47:59 -04:00
|
|
|
path_info = ::Rack::Utils.unescape env[PATH_INFO]
|
2016-07-29 16:56:52 -04:00
|
|
|
|
2016-11-03 14:10:53 -04:00
|
|
|
# There are servers which send an empty string when requesting the root.
|
|
|
|
# These servers should be ashamed of themselves.
|
|
|
|
path_info = "/" if path_info == ""
|
|
|
|
|
2016-07-29 16:56:52 -04:00
|
|
|
@routes[request_method].each do |route|
|
|
|
|
if params = route.match(request_method, path_info)
|
2016-07-26 10:03:17 -04:00
|
|
|
env[ROUTE_PARAMS] = params
|
2016-07-29 16:56:52 -04:00
|
|
|
|
2016-07-29 15:09:00 -04:00
|
|
|
return WebAction.new(env, route.block)
|
2016-07-26 10:03:17 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class WebRoute
|
2016-07-29 15:28:27 -04:00
|
|
|
attr_accessor :request_method, :pattern, :block, :name
|
2016-07-26 10:03:17 -04:00
|
|
|
|
2018-02-16 16:11:54 -05:00
|
|
|
NAMED_SEGMENTS_PATTERN = /\/([^\/]*):([^\.:$\/]+)/
|
2016-07-26 10:03:17 -04:00
|
|
|
|
2016-07-29 15:09:00 -04:00
|
|
|
def initialize(request_method, pattern, block)
|
2016-07-26 10:03:17 -04:00
|
|
|
@request_method = request_method
|
|
|
|
@pattern = pattern
|
2016-07-29 15:09:00 -04:00
|
|
|
@block = block
|
2016-07-26 10:03:17 -04:00
|
|
|
end
|
|
|
|
|
2016-07-29 16:56:52 -04:00
|
|
|
def matcher
|
|
|
|
@matcher ||= compile
|
2016-07-26 10:03:17 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
def compile
|
2016-07-29 16:56:52 -04:00
|
|
|
if pattern.match(NAMED_SEGMENTS_PATTERN)
|
|
|
|
p = pattern.gsub(NAMED_SEGMENTS_PATTERN, '/\1(?<\2>[^$/]+)')
|
|
|
|
|
|
|
|
Regexp.new("\\A#{p}\\Z")
|
2016-07-26 10:03:17 -04:00
|
|
|
else
|
|
|
|
pattern
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def match(request_method, path)
|
2016-07-29 16:56:52 -04:00
|
|
|
case matcher
|
|
|
|
when String
|
|
|
|
{} if path == matcher
|
|
|
|
else
|
|
|
|
if path_match = path.match(matcher)
|
2016-08-30 16:29:03 -04:00
|
|
|
Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
|
2016-07-29 16:56:52 -04:00
|
|
|
end
|
2016-07-26 10:03:17 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|