class Deas::Runner
Constants
- DEFAULT_CHARSET
- DEFAULT_MIME_TYPE
- SplatParseError
Attributes
handler[R]
handler_class[R]
logger[R]
params[R]
request[R]
route_path[R]
router[R]
template_source[R]
Public Class Methods
body_value(value)
click to toggle source
# File lib/deas/runner.rb, line 14 def self.body_value(value) # http://www.rubydoc.info/github/rack/rack/master/file/SPEC#The_Body # "The Body must respond to each and must only yield String values" # String#each is a thing in 1.8.7, so account for it here return nil if value.to_s.empty? !value.respond_to?(:each) || value.kind_of?(String) ? [*value.to_s] : value end
new(handler_class, args = nil)
click to toggle source
# File lib/deas/runner.rb, line 26 def initialize(handler_class, args = nil) @handler_class = handler_class @status, @body = nil, nil @headers = Rack::Utils::HeaderHash.new.merge(@handler_class.default_headers) @handler = @handler_class.new(self) args ||= {} @request = args[:request] @route_path = args[:route_path].to_s @params = args[:params] || {} @logger = args[:logger] || Deas::NullLogger.new @router = args[:router] || Deas::Router.new @template_source = args[:template_source] || Deas::NullTemplateSource.new end
Public Instance Methods
body(value = nil)
click to toggle source
# File lib/deas/runner.rb, line 66 def body(value = nil) if !value.nil? @body = self.class.body_value(value) end @body end
content_type(extname, params = nil)
click to toggle source
# File lib/deas/runner.rb, line 73 def content_type(extname, params = nil) self.headers['Content-Type'] = get_content_type(extname, params) end
halt(*args)
click to toggle source
# File lib/deas/runner.rb, line 85 def halt(*args) self.status(args.shift) if args.first.instance_of?(::Fixnum) self.headers(args.shift) if args.first.kind_of?(::Hash) self.body(args.shift) if !args.first.to_s.empty? throw :halt end
headers(value = nil)
click to toggle source
# File lib/deas/runner.rb, line 61 def headers(value = nil) @headers.merge!(value) if !value.nil? @headers end
partial(template_name, locals = nil)
click to toggle source
# File lib/deas/runner.rb, line 139 def partial(template_name, locals = nil) source_partial(self.template_source, template_name, locals) end
redirect(location, *halt_args)
click to toggle source
# File lib/deas/runner.rb, line 92 def redirect(location, *halt_args) self.status(302) self.headers['Location'] = get_absolute_url(location) halt(*halt_args) end
render(template_name, locals = nil)
click to toggle source
# File lib/deas/runner.rb, line 127 def render(template_name, locals = nil) source_render(self.template_source, template_name, locals) end
run()
click to toggle source
# File lib/deas/runner.rb, line 45 def run raise NotImplementedError end
send_file(file_path, opts = nil)
click to toggle source
# File lib/deas/runner.rb, line 98 def send_file(file_path, opts = nil) path_name = Pathname.new(file_path) self.halt(404, []) if !path_name.exist? env = self.request.env mtime = path_name.mtime.httpdate.to_s self.halt(304, []) if env['HTTP_IF_MODIFIED_SINCE'] == mtime self.headers['Last-Modified'] ||= mtime self.headers['Content-Type'] ||= get_content_type(path_name.extname) opts ||= {} disposition = opts[:disposition] filename = opts[:filename] disposition ||= 'attachment' if !filename.nil? filename ||= path_name.basename if !disposition.nil? self.headers['Content-Disposition'] ||= "#{disposition};filename=\"#{filename}\"" end sfb = SendFileBody.new(env, path_name) self.body(sfb) self.headers['Content-Length'] ||= sfb.size.to_s self.headers['Content-Range'] ||= sfb.content_range if sfb.partial? self.status(sfb.partial? ? 206 : 200) self.halt # be consistent with halts above - `send_file` always halts end
source_partial(source, template_name, locals = nil)
click to toggle source
# File lib/deas/runner.rb, line 143 def source_partial(source, template_name, locals = nil) source.partial(template_name, locals || {}) end
source_render(source, template_name, locals = nil)
click to toggle source
# File lib/deas/runner.rb, line 131 def source_render(source, template_name, locals = nil) self.headers['Content-Type'] ||= get_content_type( File.extname(template_name), 'charset' => DEFAULT_CHARSET ) self.body(source.render(template_name, self.handler, locals || {})) end
splat()
click to toggle source
# File lib/deas/runner.rb, line 41 def splat @splat ||= parse_splat_value end
status(value = nil)
click to toggle source
# File lib/deas/runner.rb, line 56 def status(value = nil) @status = value if !value.nil? @status end
to_rack()
click to toggle source
# File lib/deas/runner.rb, line 49 def to_rack [ self.status || @handler_class.default_status, self.headers.to_hash, self.body || @handler_class.default_body ] end
Private Instance Methods
get_absolute_url(url)
click to toggle source
# File lib/deas/runner.rb, line 155 def get_absolute_url(url) return url if url =~ /\A[A-z][A-z0-9\+\.\-]*:/ File.join("#{request.env['rack.url_scheme']}://#{request.env['HTTP_HOST']}", url) end
get_content_type(extname, params = nil)
click to toggle source
# File lib/deas/runner.rb, line 149 def get_content_type(extname, params = nil) [ Rack::Mime.mime_type(extname, DEFAULT_MIME_TYPE), params ? params.map{ |k,v| "#{k}=#{v}" }.join(',') : nil ].compact.join(';') end
parse_splat_value()
click to toggle source
# File lib/deas/runner.rb, line 160 def parse_splat_value return nil if request.nil? || (path_info = request.env['PATH_INFO']).nil? regex = splat_value_parse_regex match = regex.match(path_info) if match.nil? raise SplatParseError, "could not parse the splat value: " \ "the PATH_INFO, `#{path_info.inspect}`, " \ "doesn't match " \ "the route, `#{self.route_path.inspect}`, " \ "using the route regex, `#{regex.inspect}`" end match.captures.first end
route_path_with_regex_placeholders()
click to toggle source
# File lib/deas/runner.rb, line 183 def route_path_with_regex_placeholders # Replace param values with regex placeholders b/c we don't care what # the values are just that "a param value goes here". Use gsub in the odd # case a placeholder is used more than once in a route. This is to help # ensure matching and capturing splats even on nonsense paths. sorted_param_names.inject(self.route_path) do |path, name| path.gsub(":#{name}", '.+?') end end
sorted_param_names()
click to toggle source
# File lib/deas/runner.rb, line 193 def sorted_param_names # Sort longer key names first so they will be processed first. This # ensures that shorter param names that compose longer param names won't # be subbed in the longer param name's place. self.params.keys.sort{ |a, b| b.size <=> a.size } end
splat_value_parse_regex()
click to toggle source
# File lib/deas/runner.rb, line 177 def splat_value_parse_regex # `sub` should suffice as only a single trailing splat is allowed. Replace # any splat with a capture placholder so we can extract the splat value. /^#{route_path_with_regex_placeholders.sub('*', '(.+?)')}$/ end