require 'sitehub/getter_setter_methods' require 'sitehub/constants' require 'sitehub/nil_route' require 'rack/request' require 'rack/response' require 'rack/utils' require 'em-http' class SiteHub module Middleware class CandidateRouteMappings < Hash INVALID_PATH_MATCHER = 'Matcher for path (%s) was not a valid regexp: %s'.freeze class InvalidPathMatcherError < StandardError end NIL_ROUTE = NilRoute.new include Equality extend GetterSetterMethods getter_setter :sitehub_cookie_name, RECORDED_ROUTES_COOKIE def initialize self.default = NIL_ROUTE end def call(env) source_request = Rack::Request.new(env) route = mapped_route(path: source_request.path, request: source_request) route.call(env) end def init values.each(&:build) self end def add_route(url: nil, mapped_path: nil, route_builder: nil, &block) if route_builder self[route_builder.mapped_path] = route_builder return end mapped_path = string_to_regexp(mapped_path) if string_containing_regexp?(mapped_path) self[mapped_path] = CandidateRoutes.new(sitehub_cookie_name: sitehub_cookie_name, mapped_path: mapped_path, &block).tap do |builder| builder.default(url: url) if url end end def mapped_route(path:, request:) self[mapping(path)].resolve(id: request.cookies[sitehub_cookie_name], env: request.env) end def mapping(path) keys.find do |key| case key when Regexp key.match(path) else path == key end end end def string_containing_regexp?(obj) return false unless obj.is_a?(String) obj.start_with?('%r{') && obj.end_with?('}') end private def string_to_regexp(mapped_path) regexp_string = mapped_path.to_s.sub(/^%r{/, '').sub(/}$/, '') Regexp.compile(regexp_string) rescue RegexpError => e raise InvalidPathMatcherError, format(INVALID_PATH_MATCHER, regexp_string, e.message) end end end end