Class: Nephos::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/nephos-server/router/main.rb,
lib/nephos-server/router/load.rb

Overview

The Router provides an interface between the Controller and the client queries.

Constant Summary collapse

ROUTES =
[]

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opt = {}) ⇒ Router

Returns a new instance of Router.

Parameters:

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

    it contains optional parameters, via the keys (Symbol only)

    • :silent : if true, then there will be no puts on the stdin when a request is routed. Else, or by default, there will be information printed on stdin



17
18
19
20
# File 'lib/nephos-server/router/main.rb', line 17

def initialize(opt={})
  @responder = Responder.new
  @silent = !!opt[:silent]
end

Class Method Details

.add(what, verb) ⇒ Object



5
6
7
8
9
10
# File 'lib/nephos-server/router/load.rb', line 5

def self.add(what, verb)
  Nephos::Router::ROUTES << what.merge(verb: verb)
  display = "[#{verb}] #{what[:url]} \t ---> \t #{what[:controller]}##{what[:method]}"
  puts display unless what[:silent]
  return display
end

.add_params!(what) ⇒ Object

Parameters:

  • what (Hash)


13
14
15
16
17
18
19
20
21
22
# File 'lib/nephos-server/router/load.rb', line 13

def self.add_params!(what)
  params = what[:url].split('/').map do |p|
    p.match(/:\w+/) ? {p: "[^\/]+", name: p} : {p: p, name: nil}
  end
  url = params.map{|e| e[:p]}.join("/+")
  url = "/" if url.empty?
  what[:match] = /^#{url}\/*$/
  # remove : in :param, and / in /param
  what[:params] = params.map{|e| e[:name] && e[:name][1..-1]}[1..-1] || []
end

.check!(what) ⇒ Object



70
71
72
73
74
# File 'lib/nephos-server/router/load.rb', line 70

def self.check!(what)
  check_keys! what
  instance = check_controller! what
  check_method! what, instance
end

.check_controller!(what) ⇒ Object

Check if:

  • the what parameter contains a :controller

  • this controller exists

  • if the controller is a child of the Controller class

  • if the controller is instanciable

Parameters:

  • what (Hash)


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/nephos-server/router/load.rb', line 43

def self.check_controller! what
  begin
    controller = Module.const_get(what[:controller])
  rescue => err
    raise InvalidRouteController, "Controller \"#{what[:controller]}\" doesn't exists"
  end
  if not controller.ancestors.include? Nephos::Controller
    raise InvalidRouteController, "Class \"#{what[:controller]}\" is not a Nephos::Controller"
  end
  begin
    instance = controller.new(Rack::Request.new({}), {params: []})
  rescue => err
    raise InvalidRouteController, "Cannot initialize controller"
  end
  return instance
end

.check_keys!(what) ⇒ Object

Check if the what parameter contains the needed keys

  • :url

  • :controller

  • :method

Parameters:

  • what (Hash)

Raises:



30
31
32
33
34
# File 'lib/nephos-server/router/load.rb', line 30

def self.check_keys! what
  raise InvalidRouteUrl, "Missing URL" unless what.keys.include? :url
  raise InvalidRouteController, "Missing Controller" unless what.keys.include? :controller
  raise InvalidRouteMethod, "Missing Method" unless what.keys.include? :method
end

.check_method!(what, instance) ⇒ Object

Check if the param instance has a method named what

Parameters:



64
65
66
67
68
# File 'lib/nephos-server/router/load.rb', line 64

def self.check_method! what, instance
  if not instance.respond_to? what[:method]
    raise InvalidRouteMethod, "No method named \"#{what[:method]}\""
  end
end

Instance Method Details

#execute(req) ⇒ Object

Interface which handle the client query (stored in env), create a new Controller instance, and call the render on it



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

def execute(req)
  env = req.env
  puts "#{req.env["REMOTE_ADDR"]} [#{req.request_method}] \t ---> \t #{req.path}" unless @silent
  call = find_route(req)
  return render_error(req, 404, "404 not found \"#{req.path}\"") if call.nil?
  begin
    return render_controller(req, call)
  rescue => err
    STDERR.puts "Error: #{err.message}"
    STDERR.puts err.backtrace
    return render_error(req, 500, err)
  end
end

#find_route(req) ⇒ Object

Find the right route to use from the url

Parameters:

  • path (Array)


46
47
48
# File 'lib/nephos-server/router/main.rb', line 46

def find_route req
  return ROUTES.find{|e| e[:match] =~ req.path and e[:verb] == req.request_method}
end

#render_controller(req, call) ⇒ Object

render the return of a call to Controller.new.method. Controller and method are stored on call via the keys :controller and :method



24
25
26
# File 'lib/nephos-server/router/main.rb', line 24

def render_controller req, call
  return @responder.render_from_controller(req, call)
end

#render_error(req, code, err = nil) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/nephos-server/router/main.rb', line 28

def render_error(req, code, err=nil)
  if Nephos.env == "production"
    return @responder.render(status: code)
  elsif err
    msg = err
    if msg.is_a? Exception
      msg = err.message + "\n"
      msg += "--- Backtrace ---\n" + err.backtrace.join("\n") + "\n"
    end
    return @responder.render(status: code, content: "Error: #{code}\n#{msg}")
  else
    return @responder.render(status: code)
  end
end