Class: Rack::URLMap

Inherits:
Object
  • Object
show all
Defined in:
lib/rack/urlmap.rb

Overview

Rack::URLMap takes a hash mapping urls or paths to apps, and dispatches accordingly. Support for HTTP/1.1 host names exists if the URLs start with http:// or https://.

URLMap modifies the SCRIPT_NAME and PATH_INFO such that the part relevant for dispatch is in the SCRIPT_NAME, and the rest in the PATH_INFO. This should be taken care of when you need to reconstruct the URL in order to create links.

URLMap dispatches in such a way that the longest paths are tried first, since they are most specific.

Instance Method Summary collapse

Constructor Details

#initialize(map) ⇒ URLMap

Returns a new instance of URLMap.



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/rack/urlmap.rb', line 15

def initialize(map)
  @mapping = map.map { |location, app|
    if location =~ %r{\Ahttps?://(.*?)(/.*)}
      host, location = $1, $2
    else
      host = nil
    end

    unless location[0] == ?/
      raise ArgumentError, "paths need to start with /"
    end
    location = location.chomp('/')

    [host, location, app]
  }.sort_by { |(h, l, a)| -l.size }  # Longest path first
end

Instance Method Details

#call(env) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rack/urlmap.rb', line 32

def call(env)
  path = env["PATH_INFO"].to_s.squeeze("/")
  hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT')
  @mapping.each { |host, location, app|
    next unless (hHost == host || sName == host \
      || (host.nil? && (hHost == sName || hHost == sName+':'+sPort)))
    next unless location == path[0, location.size]
    next unless path[location.size] == nil || path[location.size] == ?/
    env["SCRIPT_NAME"] += location
    env["PATH_INFO"]    = path[location.size..-1]
    return app.call(env)
  }
  [404, {"Content-Type" => "text/plain"}, ["Not Found: #{path}"]]
end