Class: Gopher::Application
- Inherits:
-
Object
- Object
- Gopher::Application
- Defined in:
- lib/gopher2000/base.rb
Overview
main application class for a gopher server. holds all the methods/data required to interact with clients.
Constant Summary collapse
- ACCESS_LOG_PATTERN =
The output pattern we will use to generate access logs
"%d\t%m\n"
- @@access_log =
nil
- @@debug_log =
nil
Instance Attribute Summary collapse
-
#config ⇒ Object
Returns the value of attribute config.
-
#last_reload ⇒ Object
Returns the value of attribute last_reload.
-
#menus ⇒ Object
Returns the value of attribute menus.
-
#params ⇒ Object
Returns the value of attribute params.
-
#request ⇒ Object
Returns the value of attribute request.
-
#routes ⇒ Object
Returns the value of attribute routes.
-
#scripts ⇒ Object
Returns the value of attribute scripts.
-
#text_templates ⇒ Object
Returns the value of attribute text_templates.
Class Method Summary collapse
-
.generate_method(method_name) { ... } ⇒ Object
generate a method which we will use to run routes.
-
.sanitize_selector(raw) ⇒ Object
Sanitizes a gopher selector.
Instance Method Summary collapse
-
#compile(path) ⇒ Object
turn a path string with optional keys (/foo/:bar/:boo) into a regexp which will be used when searching for a route.
-
#compile!(path, &block) ⇒ Object
compile a route.
-
#debug_log(x) ⇒ Object
output a debugging message.
-
#debug_mode? ⇒ Boolean
are we in debugging mode?.
-
#default_route { ... } ⇒ Object
specify a default route to handle requests if no other route exists.
-
#dispatch(req) ⇒ Object
find and run the first route which matches the incoming request.
-
#error_template ⇒ Object
get the id of the template that will be used when rendering an error.
-
#find_template(t) ⇒ Object
find a template.
-
#globify(p) ⇒ Object
add a glob to the end of this string, if there’s not one already.
-
#helpers(target = Gopher::Application, &block) ⇒ Object
Add helpers to the Base renedering class, which allows them to be called when outputting the results of an action.
-
#host ⇒ Object
return the host we will use when outputting gopher menus.
-
#invalid_request_template ⇒ Object
get the id of the template that will be used when rendering an invalid request.
-
#lookup(selector) ⇒ Object
lookup an incoming path.
-
#menu(name) { ... } ⇒ Object
define a template which will be used to render a gopher-style menu.
- #mount(path, opts = {}, klass = Gopher::Handlers::DirectoryHandler) ⇒ Object
-
#non_blocking? ⇒ Boolean
should we use non-blocking operations? for now, defaults to false if in debug mode, true if we’re not in debug mode (presumably, in some sort of production state. HAH! Gopher servers in production).
-
#not_found(&block) ⇒ Object
specify a template to be used for missing requests.
-
#not_found_template ⇒ Object
get the id of the template that will be used when rendering a not found error.
-
#port ⇒ Object
return the port we will use when outputting gopher menus.
-
#reload_stale ⇒ Object
reload scripts if needed.
-
#render(template, *arguments) ⇒ Object
Find the desired template and call it within the proper context.
-
#reset! ⇒ Object
reset the app.
-
#route(path) { ... } ⇒ Object
define a route.
-
#should_reload? ⇒ Boolean
check if our script has been updated since the last reload.
-
#text(name) { ... } ⇒ Object
Define a template which will be used for outputting text.
Instance Attribute Details
#config ⇒ Object
Returns the value of attribute config.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def config @config end |
#last_reload ⇒ Object
Returns the value of attribute last_reload.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def last_reload @last_reload end |
#menus ⇒ Object
Returns the value of attribute menus.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def @menus end |
#params ⇒ Object
Returns the value of attribute params.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def params @params end |
#request ⇒ Object
Returns the value of attribute request.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def request @request end |
#routes ⇒ Object
Returns the value of attribute routes.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def routes @routes end |
#scripts ⇒ Object
Returns the value of attribute scripts.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def scripts @scripts end |
#text_templates ⇒ Object
Returns the value of attribute text_templates.
20 21 22 |
# File 'lib/gopher2000/base.rb', line 20 def text_templates @text_templates end |
Class Method Details
.generate_method(method_name) { ... } ⇒ Object
generate a method which we will use to run routes. this is based on #generate_method as used by sinatra.
453 454 455 456 457 458 |
# File 'lib/gopher2000/base.rb', line 453 def generate_method(method_name, &block) define_method(method_name, &block) method = instance_method method_name remove_method method_name method end |
.sanitize_selector(raw) ⇒ Object
Sanitizes a gopher selector
437 438 439 440 441 442 443 444 445 |
# File 'lib/gopher2000/base.rb', line 437 def sanitize_selector(raw) "/#{raw}".dup. strip. # Strip whitespace sub(/\/$/, ''). # Strip last rslash sub(/^\/*/, '/'). # Strip extra lslashes gsub(/\.+/, '.') # Don't want consecutive dots! #raw = "/#{raw}" if ! raw.match(/^\//) end |
Instance Method Details
#compile(path) ⇒ Object
turn a path string with optional keys (/foo/:bar/:boo) into a regexp which will be used when searching for a route
416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
# File 'lib/gopher2000/base.rb', line 416 def compile(path) keys = [] pattern = path.to_str.gsub(/[^\?\%\\\/\:\*\w]/) { |c| encoded(c) } pattern.gsub!(/((:\w+)|\*)/) do |match| if match == "*" keys << 'splat' "(.*?)" else keys << $2[1..-1] "([^/?#]+)" end end [/^#{pattern}$/, keys] end |
#compile!(path, &block) ⇒ Object
compile a route
402 403 404 405 406 407 408 |
# File 'lib/gopher2000/base.rb', line 402 def compile!(path, &block) method_name = path route_method = Application.generate_method(method_name, &block) pattern, keys = compile path [ pattern, keys, route_method ] end |
#debug_log(x) ⇒ Object
output a debugging message
464 465 466 467 |
# File 'lib/gopher2000/base.rb', line 464 def debug_log(x) @@debug_logger ||= ::Logging.logger(STDERR) @@debug_logger.debug x end |
#debug_mode? ⇒ Boolean
are we in debugging mode?
60 61 62 |
# File 'lib/gopher2000/base.rb', line 60 def debug_mode? config[:debug] == true end |
#default_route { ... } ⇒ Object
specify a default route to handle requests if no other route exists
154 155 156 |
# File 'lib/gopher2000/base.rb', line 154 def default_route(&block) @default_route = Application.generate_method("DEFAULT_ROUTE", &block) end |
#dispatch(req) ⇒ Object
find and run the first route which matches the incoming request
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/gopher2000/base.rb', line 195 def dispatch(req) debug_log(req) response = Response.new @request = req if ! @request.valid? response.body = handle_invalid_request response.code = :error else begin debug_log("do lookup for #{@request.selector}") @params, block = lookup(@request.selector) # # call the block that handles this lookup # response.body = block.bind(self).call response.code = :success rescue Gopher::NotFoundError => e debug_log("#{@request.selector} -- not found") response.body = handle_not_found response.code = :missing rescue Exception => e debug_log("#{@request.selector} -- error") debug_log(e.inspect) debug_log(e.backtrace) response.body = handle_error(e) response.code = :error end end access_log(req, response) response end |
#error_template ⇒ Object
get the id of the template that will be used when rendering an error
346 347 348 |
# File 'lib/gopher2000/base.rb', line 346 def error_template .include?(:error) ? :error : :'internal/error' end |
#find_template(t) ⇒ Object
find a template
301 302 303 304 305 306 307 308 309 310 |
# File 'lib/gopher2000/base.rb', line 301 def find_template(t) x = [t] if x return x, Gopher::Rendering::Menu end x = text_templates[t] if x return x, Gopher::Rendering::Text end end |
#globify(p) ⇒ Object
add a glob to the end of this string, if there’s not one already
395 396 397 |
# File 'lib/gopher2000/base.rb', line 395 def globify(p) p =~ /\*/ ? p : "#{p}/?*".gsub("//", "/") end |
#helpers(target = Gopher::Application, &block) ⇒ Object
Add helpers to the Base renedering class, which allows them to be called when outputting the results of an action. Here’s the code in Sinatra for reference:
Makes the methods defined in the block and in the Modules given in ‘extensions` available to the handlers and templates
def helpers(*extensions, &block)
class_eval(&block) if block_given?
include(*extensions) if extensions.any?
end
target - What class should receive the helpers – defaults to Gopher::Rendering::Base, which will make it available when rendering block – a block which declares the helpers you want. for example:
helpers do
def foo; "FOO"; end
end
377 378 379 |
# File 'lib/gopher2000/base.rb', line 377 def helpers(target = Gopher::Application, &block) target.class_eval(&block) end |
#host ⇒ Object
return the host we will use when outputting gopher menus
46 47 48 |
# File 'lib/gopher2000/base.rb', line 46 def host config[:host] ||= '0.0.0.0' end |
#invalid_request_template ⇒ Object
get the id of the template that will be used when rendering an invalid request
355 356 357 |
# File 'lib/gopher2000/base.rb', line 355 def invalid_request_template .include?(:invalid_request) ? :invalid_request : :'internal/invalid_request' end |
#lookup(selector) ⇒ Object
lookup an incoming path
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/gopher2000/base.rb', line 163 def lookup(selector) unless routes.nil? routes.each do |pattern, keys, block| if match = pattern.match(selector) match = match.to_a url = match.shift params = to_params_hash(keys, match) # # @todo think about this # @params = params return params, block end end end unless @default_route.nil? return {}, @default_route end raise Gopher::NotFoundError end |
#menu(name) { ... } ⇒ Object
define a template which will be used to render a gopher-style menu.
266 267 268 |
# File 'lib/gopher2000/base.rb', line 266 def (name, &block) [name.to_sym] = block end |
#mount(path, opts = {}, klass = Gopher::Handlers::DirectoryHandler) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/gopher2000/base.rb', line 101 def mount(path, opts = {}, klass = Gopher::Handlers::DirectoryHandler) debug_log "MOUNT #{path} #{opts.inspect}" opts[:mount_point] = path handler = klass.new(opts) handler.application = self # # add a route for the mounted class # route(globify(path)) do # when we call, pass the params and request object for this # particular request handler.call(params, request) end end |
#non_blocking? ⇒ Boolean
should we use non-blocking operations? for now, defaults to false if in debug mode, true if we’re not in debug mode (presumably, in some sort of production state. HAH! Gopher servers in production)
387 388 389 |
# File 'lib/gopher2000/base.rb', line 387 def non_blocking? config[:non_blocking] ||= ! debug_mode? end |
#not_found(&block) ⇒ Object
specify a template to be used for missing requests
292 293 294 |
# File 'lib/gopher2000/base.rb', line 292 def not_found(&block) :not_found, &block end |
#not_found_template ⇒ Object
get the id of the template that will be used when rendering a not found error
338 339 340 |
# File 'lib/gopher2000/base.rb', line 338 def not_found_template .include?(:not_found) ? :not_found : :'internal/not_found' end |
#port ⇒ Object
return the port we will use when outputting gopher menus
53 54 55 |
# File 'lib/gopher2000/base.rb', line 53 def port config[:port] ||= 70 end |
#reload_stale ⇒ Object
reload scripts if needed
77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/gopher2000/base.rb', line 77 def reload_stale reload_check = should_reload? self.last_reload = Time.now return if ! reload_check reset! self.scripts.each do |f| debug_log "reload #{f}" load f end end |
#render(template, *arguments) ⇒ Object
Find the desired template and call it within the proper context
318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/gopher2000/base.rb', line 318 def render(template, *arguments) # # find the right renderer we need # block, handler = find_template(template) raise TemplateNotFound if block.nil? ctx = handler.new(self) ctx.params = @params ctx.request = @request ctx.instance_exec(*arguments, &block) end |
#reset! ⇒ Object
reset the app. clear out any routes, templates, config values, etc. this is used during the load process
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/gopher2000/base.rb', line 27 def reset! self.routes = [] self. = {} self.text_templates = {} self.scripts ||= [] self.config ||= { :debug => false, :host => "0.0.0.0", :port => 70 } register_defaults self end |
#route(path) { ... } ⇒ Object
define a route.
134 135 136 137 138 139 140 141 142 |
# File 'lib/gopher2000/base.rb', line 134 def route(path, &block) selector = Gopher::Application.sanitize_selector(path) sig = compile!(selector, &block) debug_log("Add route for #{selector}") self.routes ||= [] self.routes << sig end |
#should_reload? ⇒ Boolean
check if our script has been updated since the last reload
68 69 70 71 72 |
# File 'lib/gopher2000/base.rb', line 68 def should_reload? ! last_reload.nil? && self.scripts.any? do |f| File.mtime(f) > last_reload end end |
#text(name) { ... } ⇒ Object
Define a template which will be used for outputting text. This is not strictly required for outputting text, but it gives you access to the methods defined in Gopher::Rendering::Text for wrapping strings, adding simple headers, etc.
285 286 287 |
# File 'lib/gopher2000/base.rb', line 285 def text(name, &block) text_templates[name.to_sym] = block end |