Class: Padrino::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/padrino-core/router.rb

Overview

This class is an extended version of Rack::URLMap.

Padrino::Router like Rack::URLMap dispatches in such a way that the longest paths are tried first, since they are most specific.

Features:

  • Map a path to the specified App

  • Ignore server names (this solve issues with vhost and domain aliases)

  • Use hosts instead of server name for mappings (this help us with our vhost and domain aliases)

Examples:


routes = Padrino::Router.new do
  map(:path => "/", :to => PadrinoWeb, :host => "padrino.local")
  map(:path => "/", :to => Admin, :host => "admin.padrino.local")
end
run routes

routes = Padrino::Router.new do
  map(:path => "/", :to => PadrinoWeb, :host => /*.padrino.local/)
end
run routes

Instance Method Summary collapse

Constructor Details

#initialize(*mapping, &block) ⇒ Router

Returns a new instance of Router.



29
30
31
32
33
# File 'lib/padrino-core/router.rb', line 29

def initialize(*mapping, &block)
  @mapping = []
  mapping.each { |m| map(m) }
  instance_eval(&block) if block
end

Instance Method Details

#call(env) ⇒ Object

The call handler setup to route a request given the mappings specified.



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/padrino-core/router.rb', line 68

def call(env)
  began_at = Time.now
  path_info = env["PATH_INFO"].to_s
  script_name = env['SCRIPT_NAME']
  http_host = env['HTTP_HOST']
  last_result = nil

  @mapping.each do |host, path, match, app|
    next unless host.nil? || http_host =~ host
    next unless path_info =~ match && rest = $1
    next unless rest.empty? || rest[0] == ?/

    rest = "/" if rest.empty?

    env['SCRIPT_NAME'] = script_name + path
    env['PATH_INFO'] = rest
    last_result = app.call(env)

    cascade_setting = app.respond_to?(:cascade) ? app.cascade : true
    cascade_statuses = cascade_setting.respond_to?(:include?) ? cascade_setting : Mounter::DEFAULT_CASCADE
    break unless cascade_setting && cascade_statuses.include?(last_result[0])
  end
  last_result || begin
    env['SCRIPT_NAME'] = script_name
    env['PATH_INFO'] = path_info
    Padrino::Logger::Rack.new(nil,'/').send(:log, env, 404, {}, began_at) if logger.debug?
    [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path_info}"]]
  end
end

#map(options = {}) ⇒ Array

Map a route path and host to a specified application.

Examples:

map(:path => "/", :to => PadrinoWeb, :host => "padrino.local")

Parameters:

  • options (Hash) (defaults to: {})

    The options to map.

Options Hash (options):

  • :to (Sinatra::Application)

    The class of the application to mount.

  • :path (String) — default: "/"

    The path to map the specified application.

  • :host (String)

    The host to map the specified application.

Returns:

  • (Array)

    The sorted route mappings.

Raises:

  • (ArgumentError)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/padrino-core/router.rb', line 52

def map(options={})
  path = options[:path] || "/"
  host = options[:host]
  app  = options[:to]

  raise ArgumentError, "paths need to start with /" if path[0] != ?/
  raise ArgumentError, "app is required" if app.nil?

  path  = path.chomp('/')
  match = Regexp.new("^#{Regexp.quote(path).gsub('/', '/+')}(.*)", nil, 'n')
  host  = Regexp.new("^#{Regexp.quote(host)}$", true, 'n') unless host.nil? || host.is_a?(Regexp)

  @mapping << [host, path, match, app]
end