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] = what[:postfix] != false ? /^(?<url>#{url})(?<extension>\.\w+)?\/*$/ : /^(?<url>#{url})\/*$/
  # remove : in :param, and / in /param
  what[:params] = params.map{|e| e[:name] && e[:name][1..-1]}[1..-1] || []
end

.check!(what) ⇒ Object



78
79
80
81
82
# File 'lib/nephos-server/router/load.rb', line 78

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)


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

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
35
36
37
38
39
40
41
42
# File 'lib/nephos-server/router/load.rb', line 30

def self.check_keys! what
  raise InvalidRouteUrl, "Missing URL" unless what.keys.include? :url
  if what.keys.include? :to
    match = what[:to].match(/(?<controller>\w+)\#(?<method>\w+)/)
    raise InvalidRouteTo, "Invalid Controller#Method" unless match
    what[:controller] = match["controller"]
    what[:method] = match["method"]
    what.delete :to
  else
    raise InvalidRouteController, "Missing Controller" unless what.keys.include? :controller
    raise InvalidRouteMethod, "Missing Method" unless what.keys.include? :method
  end
end

.check_method!(what, instance) ⇒ Object

Check if the param instance has a method named what

Parameters:



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

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

#error_404(req) ⇒ Object



55
56
57
58
59
60
# File 'lib/nephos-server/router/main.rb', line 55

def error_404(req)
  STDERR.puts "Error 404" if $verbose == "output"
  out = error_custom(req, 404, "404 not found \"#{req.path}\"")
  out.body[0].gsub!("INJECT_REQ_PATH", req.path)
  return out
end

#error_custom(req, code, default = nil) ⇒ Object



46
47
48
49
50
51
52
53
# File 'lib/nephos-server/router/main.rb', line 46

def error_custom(req, code, default=nil)
  STDERR.puts "Error #{code}" if $verbose == "output"
  if File.exist? "app/#{code}.html"
    @responder.render(status: code, html: File.read("app/#{code}.html"))
  else
    render_error(req, code, default || "Error: #{req.status}")
  end
end

#execute(req) ⇒ Object

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



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/nephos-server/router/main.rb', line 71

def execute(req)
  #env = req.env
  puts "#{req.env["REMOTE_ADDR"]} [#{req.request_method}] \t ---> \t #{req.path}" unless @silent
  call = find_route(req)
  # require 'pry'
  # binding.pry
  return error_404(req) if call.nil?
  begin
    return render_controller(req, call)
  rescue => err
    STDERR.puts "Error: #{err.message}" unless @silent
    STDERR.puts err.backtrace unless @silent
    return error_custom(req, 500, "#{err.message}\n---Backtrace---\n#{err.backtrace.join("\n")}\n")
  end
end

#find_route(req) ⇒ Object

Find the right route to use from the url

Parameters:

  • path (Array)


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

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
27
28
# File 'lib/nephos-server/router/main.rb', line 24

def render_controller req, call
  out = @responder.render_from_controller(req, call)
  STDERR.puts "<--- #{out.body}" if $verbose == "output"
  return out
end

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



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

def render_error(req, code, err=nil)
  STDERR.puts "Error #{code}" if $verbose == "output"
  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