lib/rack/app/router/dynamic.rb in rack-app-3.0.0.alpha vs lib/rack/app/router/dynamic.rb in rack-app-3.0.0.beta
- old
+ new
@@ -1,30 +1,12 @@
class Rack::App::Router::Dynamic < Rack::App::Router::Base
- PATH_PARAM = :"#{self}::PATH_PARAM".freeze
- PARTIAL = :"#{self}::PARTIAL".freeze
+ require 'rack/app/router/dynamic/request_path_part_placeholder'
+ DYNAMIC_REQUEST_PATH_PART = RequestPathPartPlaceholder.new('DYNAMIC_REQUEST_PATH_PART')
+ MOUNTED_DIRECTORY = RequestPathPartPlaceholder.new('MOUNTED_DIRECTORY')
+ MOUNTED_APPLICATION = RequestPathPartPlaceholder.new('MOUNTED_APPLICATION')
- def fetch_endpoint(request_method, request_path)
- normalized_request_path = Rack::App::Utils.normalize_path(request_path)
-
- current_cluster = main_cluster(request_method)
- normalized_request_path.split('/').each do |path_part|
- previous_cluster = current_cluster
- current_cluster = current_cluster[path_part] || current_cluster[PATH_PARAM]
- if current_cluster.nil?
- if previous_cluster[PARTIAL]
- current_cluster = previous_cluster[PARTIAL]
- break
- else
- return nil
- end
- end
- end
-
- current_cluster[:endpoint]
- end
-
protected
def initialize
@http_method_cluster = {}
end
@@ -32,68 +14,138 @@
def path_part_is_dynamic?(path_part_str)
!!(path_part_str.to_s =~ /^:\w+$/i)
end
def deep_merge!(hash, other_hash)
- other_hash.each_pair do |current_key, other_value|
-
- this_value = hash[current_key]
-
- hash[current_key] = if this_value.is_a?(Hash) && other_value.is_a?(Hash)
- deep_merge!(this_value, other_value)
- else
- other_value
- end
- end
-
- hash
+ Rack::App::Utils.deep_merge(hash, other_hash)
end
def main_cluster(request_method)
(@http_method_cluster[request_method.to_s.upcase] ||= {})
end
- def path_part_is_a_partial?(path_part)
+ def path_part_is_a_mounted_directory?(path_part)
+ path_part == Rack::App::Constants::MOUNTED_DIRECTORY
+
(path_part == '**' or path_part == '*')
end
+ def path_part_is_a_mounted_rack_based_application?(path_part)
+ path_part == Rack::App::Constants::RACK_BASED_APPLICATION
+ end
+
def compile_registered_endpoints!
@http_method_cluster.clear
endpoints.each do |endpoint_prop|
- compile_endpoint(endpoint_prop[:request_method],endpoint_prop[:request_path],endpoint_prop[:endpoint])
+ compile_endpoint(endpoint_prop[:request_method], endpoint_prop[:request_path], endpoint_prop[:endpoint])
end
end
def compile_endpoint(request_method, request_path, endpoint)
+ clusters_for(request_method) do |current_cluster|
- current_cluster = main_cluster(request_method)
- path_params = {}
- break_build = false
+ break_build = false
+ path_params = {}
+ mount_path = ''
+ options = {}
- request_path.split('/').each.with_index do |path_part, index|
+ request_path_parts = request_path.split('/')
+ request_path_parts.each.with_index do |path_part, index|
- new_cluster_name = if path_part_is_dynamic?(path_part)
- path_params[index]= path_part.sub(/^:/, '')
- PATH_PARAM
+ new_cluster_name = if path_part_is_dynamic?(path_part)
+ path_params[index]= path_part.sub(/^:/, '')
+ DYNAMIC_REQUEST_PATH_PART
- elsif path_part_is_a_partial?(path_part)
- break_build = true
- PARTIAL
+ elsif path_part_is_a_mounted_directory?(path_part)
+ break_build = true
+ MOUNTED_DIRECTORY
- else
- path_part
- end
+ elsif path_part_is_a_mounted_rack_based_application?(path_part)
+ break_build = true
+ mount_path = calculate_mount_path(request_path_parts)
+ MOUNTED_APPLICATION
- current_cluster = (current_cluster[new_cluster_name] ||= {})
- break if break_build
+ else
+ path_part
+ end
+ current_cluster = (current_cluster[new_cluster_name] ||= {})
+ break if break_build
+
+ end
+
+ current_cluster[:endpoint]= endpoint
+ if current_cluster[:endpoint].respond_to?(:register_path_params_matcher)
+ current_cluster[:endpoint].register_path_params_matcher(path_params)
+ end
+
+ options[:mount_path]= mount_path
+ options[:path_params]= path_params
+ current_cluster[:options]= options
+
end
+ end
- current_cluster[:endpoint]= endpoint
- if current_cluster[:endpoint].respond_to?(:register_path_params_matcher)
- current_cluster[:endpoint].register_path_params_matcher(path_params)
+ def calculate_mount_path(request_path_parts)
+ mount_path_parts = (request_path_parts - [Rack::App::Constants::RACK_BASED_APPLICATION, ''])
+ mount_path_parts.empty? ? '' : Rack::App::Utils.join(mount_path_parts)
+ end
+
+ def clusters_for(request_method)
+ if ::Rack::App::Constants::HTTP::ANY == request_method
+ supported_http_protocols.each do |cluster_type|
+ yield(main_cluster(cluster_type))
+ end
+ else
+ yield(main_cluster(request_method))
end
+ end
- endpoint
+ def supported_http_protocols
+ (::Rack::App::Constants::HTTP.constants - [:ANY]).map(&:to_s)
+ end
+
+
+ def fetch_context(request_method, path_info)
+ normalized_request_path = Rack::App::Utils.normalize_path(path_info)
+
+ last_mounted_directory = nil
+ last_mounted_app = nil
+ current_cluster = main_cluster(request_method)
+
+ normalized_request_path.split('/').each do |path_part|
+
+ last_mounted_directory = current_cluster[MOUNTED_DIRECTORY] || last_mounted_directory
+ last_mounted_app = current_cluster[MOUNTED_APPLICATION] || last_mounted_app
+
+ current_cluster = current_cluster[path_part] || current_cluster[DYNAMIC_REQUEST_PATH_PART]
+
+ last_mounted_directory = (current_cluster || {})[MOUNTED_DIRECTORY] || last_mounted_directory
+ last_mounted_app = (current_cluster || {})[MOUNTED_APPLICATION] || last_mounted_app
+
+ if current_cluster.nil?
+ if last_mounted_directory
+ current_cluster = last_mounted_directory
+ break
+
+ elsif last_mounted_app
+ current_cluster = last_mounted_app
+ break
+
+ else
+ return nil
+
+ end
+ end
+
+ end
+
+ return current_cluster
+
+ end
+
+ def format_env(context, env)
+ mount_path = context[:options][:mount_path] rescue ''
+ env[::Rack::PATH_INFO].sub!(mount_path, '')
end
end
\ No newline at end of file