Repository URL to install this package:
|
Version:
0.9.2 ▾
|
class EBuilder
# displays URLs the app will respond to,
# with controller and action that serving each URL.
def url_map
mount_controllers!
sort_routes!
URLMapPrinter.new(@routes)
end
alias urlmap url_map
unless defined?(EBuilder::URLMapPrinter)
class URLMapPrinter
def initialize routes
@routes = routes.freeze
end
def to_s
out = ''
@routes.each_pair do |unit,routes|
routes.each_pair do |route,setup|
out << "%s\n" % route.source
setup.each_pair do |rm,rs|
out << " %s%s" % [rm, ' ' * (10 - rm.to_s.size)]
out << "%s\n" % caller(unit, rs)
end
out << "\n"
end
end
out
end
def inspect
@routes
end
private
def caller unit, setup
return setup[:app] if [:rewriter, :application].include?(unit)
[setup[:app], setup[:action]].join('#')
end
end
end
private
# matching regexp is built to match the action boundary
# and whatever that comes after boundary.
# this method will simply concatenate boundary with whatever else.
def matched_path_info matches
matches[1].to_s + matches[2].to_s # 2x faster than matches[1..2].join
end
# routes should be sorted by length in descending order,
# that's it, longer routes goes first as they are more relevant.
def sort_routes!
sorted_routes = {}
@routes.each_pair do |unit,routes|
sorted_routes[unit] = Hash[routes.sort do |a,b|
route_priority(*b) <=> route_priority(*a)
end]
end
@routes = sorted_routes
end
def route_priority route, setup
if priority = setup.values.first[:priority]
return priority
end
route.is_a?(Regexp) ? route.source.length : route.to_s.length
end
# splitting path_info into format and path,
# so "index.html" returns [".html", "index"]
# - "index/something.html" => [".html", "index/something"]
# - "index" => [nil, "index"]
# - "index/something" => [nil, "index/something"]
#
# if ".html" is a unrecognized format
# the path remains the same and a nil format returned
def handle_format formats, path_info
format = nil
if formats.any?
if format = formats[path_info]
path_info = ''
elsif format = formats[File.extname(path_info)]
# File join + dirname + basename
# is faster than building a regexp and sub path info based on it
path_info = File.join File.dirname(path_info), File.basename(path_info, format)
end
end
[format, path_info]
end
def valid_context? unit, setup, env
if unit == :rewriter # rewriter works only on GET and HEAD requests
return valid_rewriter_context?(setup, env[ENV__REQUEST_METHOD])
end
valid_route_context?(setup, env[ENV__REQUEST_METHOD])
end
# check whether action respond to given request method
# or to whatever method.
# RESTless actions like `def index`, `def edit` will respond to whatever method.
# RESTified actions, like `def post_index`, `def put_edit`
# will respond only to specified request method.
def valid_route_context? route_setup, request_method
route_setup[request_method] || route_setup[:*]
end
# check whether it is a GET or HEAD request
# cause rewriters are listening only on these request methods.
# if yes, extract rewriter setup using GET key,
# cause rewriters are added like {'GET' => {app: logic_proc}}
def valid_rewriter_context? overall_setup, request_method
(request_method == HTTP__DEFAULT_REQUEST_METHOD ||
request_method == HTTP__HEAD_REQUEST_METHOD) &&
overall_setup[HTTP__DEFAULT_REQUEST_METHOD]
end
def valid_host? accepted_hosts, env
return true if accepted_hosts.empty?
http_host, server_name, server_port =
env.values_at(ENV__HTTP_HOST, ENV__SERVER_NAME, ENV__SERVER_PORT)
accepted_hosts[http_host] ||
accepted_hosts[server_name] ||
http_host == server_name ||
http_host == server_name+':'+server_port # 3x faster than create and join an array
end
def normalize_path path
(path_ok?(path) ? path : '/' << path).freeze
end
# checking whether path is empty or starts with a slash
def path_ok? path
# comparing fixnums are much faster than comparing strings
path.hash == (@empty_string_hash ||= '' .hash) || # faster than path.empty?
path[0].hash == (@slash_hash ||= '/'.hash) # faster than path =~ /^\//
end
def not_found env
[
STATUS__NOT_FOUND,
{HEADER__CONTENT_TYPE => CONTENT_TYPE__PLAIN},
['Not Found: %s' % env[ENV__PATH_INFO]]
]
end
def not_implemented implemented
[
STATUS__NOT_IMPLEMENTED,
{HEADER__CONTENT_TYPE => CONTENT_TYPE__PLAIN},
['Resource found but it can be accessed only through %s' % implemented]
]
end
end