Class: Tap::Controllers::Server

Inherits:
Tap::Controller show all
Includes:
Utils
Defined in:
lib/tap/controllers/server.rb

Overview

:startdoc::controller remotely controls and monitor a server

Server provides several uris to control and monitor the server behavior. Importantly, server allows the remote shutdown of a Tap::Server if a shutdown_key is set. This makes it possible to run servers in the background and still have a shutdown handle on them.

Constant Summary

Constants inherited from Tap::Controller

Tap::Controller::ServerError

Instance Attribute Summary

Attributes inherited from Tap::Controller

#request, #response, #server

Instance Method Summary collapse

Methods inherited from Tap::Controller

#action?, call, #dispatch, #error, get, inherited, #initialize, #module_render, nest, #not_found, #redirect, #render, #render_erb, #render_layout, #route, set, set_variables

Constructor Details

This class inherits a constructor from Tap::Controller

Instance Method Details

#accessObject

Essentially a login for server administration



46
47
48
49
50
51
52
53
54
# File 'lib/tap/controllers/server.rb', line 46

def access
  if request.get?
    render 'access.erb', :locals => {
      :secret => request['secret']
    }, :layout => true
  else
    redirect uri("admin", :secret => request['secret'])
  end
end

#admin(secret = nil) ⇒ Object

Administrate this server



57
58
59
60
# File 'lib/tap/controllers/server.rb', line 57

def admin(secret=nil)
  template = server.admin?(secret) ? 'admin.erb' : 'access.erb'
  render template, :locals => {:secret => secret}, :layout => true
end

#call(rack_env) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/tap/controllers/server.rb', line 87

def call(rack_env)
  server = rack_env['tap.server']
  env = server ? server.env : nil
  path_info = rack_env['PATH_INFO']
  
  # serve static files
  path = env.path(:public, path_info) {|file| File.file?(file) }
  return static_file(path) if path
  
  # route to a controller
  blank, path, path_info = path_info.split("/", 3)
  constant = env ? env.constants.seek(unescape(path)) : nil

  if constant
    # adjust rack_env if route routes to a controller
    rack_env['SCRIPT_NAME'] = "#{rack_env['SCRIPT_NAME'].chomp('/')}/#{path}"
    rack_env['PATH_INFO'] = "/#{path_info}"

    constant.unload if server.development
    controller = constant.constantize
    controller == Server ? super : controller.call(rack_env)
  else
    response = Rack::Response.new
    response.status = 302
    response['Location'] = ["/server#{rack_env['PATH_INFO']}".chomp("/")]
    response.finish
  end
end

#help(*key) ⇒ Object



75
76
77
78
79
80
81
82
# File 'lib/tap/controllers/server.rb', line 75

def help(*key)
  if constant = server.env[key.join('/')]
    path = server.module_path('help.erb', constant)
    render :file => path, :locals => {:obj => constant}
  else
    "unknown constant: #{key.join('/')}"
  end
end

#help_uri(key) ⇒ Object

Returns a help uri for the specified resource, currently only sketched out.



128
129
130
# File 'lib/tap/controllers/server.rb', line 128

def help_uri(key)
  uri("help/#{key}")
end

#indexObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/tap/controllers/server.rb', line 18

def index
  env = server.env
  env_keys = env.minihash(true) 
  constants = env.constants
  manifests = env.collect do |current|
    types = {}
    constants.entries(current).minimap.each do |key, const|
      const.types.keys.each do |type|
        (types[type] ||= []) << [key, const]
      end
    end
    
    types = types.to_a.sort_by {|type, minimap| type }
    types.empty? ? nil : [env_keys[current], types]
  end 
  
  render 'index.erb', :locals => {
    :manifests => manifests.compact
  }, :layout => true
end

#pingObject

Returns pong



40
41
42
43
# File 'lib/tap/controllers/server.rb', line 40

def ping
  response['Content-Type'] = "text/plain"
  "pong"
end

#shutdown(secret = nil) ⇒ Object

Terminates app and stops self (on post).



63
64
65
66
67
68
69
70
71
72
73
# File 'lib/tap/controllers/server.rb', line 63

def shutdown(secret=nil)
  response['Content-Type'] = "text/plain"
  
  if server.admin?(secret) && request.post?
    # wait a bit to shutdown, so the response is sent out.
    Thread.new { sleep(0.1); server.stop! }
    "shutdown"
  else
    ""
  end
end

#templateObject



132
133
134
135
136
137
138
139
140
141
# File 'lib/tap/controllers/server.rb', line 132

def template
  %Q{<% if !minimap.empty? && count > 1 %>
  <h2><%= env_key %></h2>
  <li>
    <ul><% minimap.each do |key, entry| %>
    <li><%= key %> (<a href="help/<%= key %>">?</a>)</li><% end %>
    </ul>
  </li>
<% end %>}
end

#uri(action = nil, params = {}) ⇒ Object

Returns a controller uri, attaching the secret to the action, if specified.



117
118
119
120
121
122
123
124
125
# File 'lib/tap/controllers/server.rb', line 117

def uri(action=nil, params={})
  secret = params.delete(:secret)
  
  if secret
    action = action ? "#{action}/#{secret}" : secret
  end
  
  super(action, params)
end