class Jellyfish::URLMap

Public Class Methods

new(mapped_not_chomped) click to toggle source
# File lib/jellyfish/urlmap.rb, line 7
def initialize mapped_not_chomped
  mapped = transform_keys(mapped_not_chomped){ |k| k.sub(%r{/+\z}, '') }
  keys = mapped.keys
  @no_host = !keys.any?{ |k| match?(k, %r{\Ahttps?://}) }

  string = sort_keys(keys).
    map{ |k| build_regexp(k) }.
    join('|')

  @mapped = mapped
  @routes = %r{\A(?:#{string})(?:/|\z)}
end

Public Instance Methods

call(env) click to toggle source
# File lib/jellyfish/urlmap.rb, line 20
def call env
  path_info = env['PATH_INFO']

  if @no_host
    if matched = @routes.match(path_info)
      cut_path = matched.to_s.chomp('/')
      script_name = key = cut_path.squeeze('/')
    end
  else
    host = (env['HTTP_HOST'] || env['SERVER_NAME']).to_s.downcase
    if matched = @routes.match("#{host}/#{path_info}")
      cut_path = matched.to_s[host.size + 1..-1].chomp('/')
      script_name = cut_path.squeeze('/')

      key =
        if matched[:host]
          host_with_path =
            if script_name.empty?
              host
            else
              File.join(host, script_name)
            end
          "http://#{host_with_path}"
        else
          script_name
        end
    end
  end

  if app = @mapped[key]
    app.call(env.merge(
      'SCRIPT_NAME' => env['SCRIPT_NAME'] + script_name,
      'PATH_INFO' => path_info[cut_path.size..-1]))
  else
    [404, {}, []]
  end
end

Private Instance Methods

build_regexp(path) click to toggle source
# File lib/jellyfish/urlmap.rb, line 60
def build_regexp path
  if @no_host
    regexp_path(path)
  elsif matched = path.match(%r{\Ahttps?://([^/]+)(/?.*)})
    # We only need to know if we're matching against a host,
    # therefore just an empty group is sufficient.
    "(?<host>)#{matched[1]}/#{regexp_path(matched[2])}"
  else
    "[^/]*/#{regexp_path(path)}"
  end
end
match?(string, regexp) click to toggle source
# File lib/jellyfish/urlmap.rb, line 87
def match? string, regexp
  if string.respond_to?(:match?)
    string.match?(regexp)
  else
    string =~ regexp
  end
end
regexp_path(path) click to toggle source
# File lib/jellyfish/urlmap.rb, line 72
def regexp_path path
  Regexp.escape(path).gsub('/', '/+')
end
sort_keys(keys) click to toggle source
# File lib/jellyfish/urlmap.rb, line 95
def sort_keys keys
  keys.sort_by do |k|
    uri = URI.parse(k)

    [-uri.path.to_s.size, -uri.host.to_s.size]
  end
end
transform_keys(hash) { |key| ... } click to toggle source
# File lib/jellyfish/urlmap.rb, line 76
def transform_keys hash, &block
  if hash.respond_to?(:transform_keys)
    hash.transform_keys(&block)
  else
    hash.inject({}) do |result, (key, value)|
      result[yield(key)] = value
      result
    end
  end
end