class Forward::Static::App

Attributes

files[R]
path[RW]
root[RW]

Public Class Methods

new(root, app = nil) click to toggle source
# File lib/forward/static/app.rb, line 82
def initialize(root, app = nil)
  @root            = File.expand_path(root)
  @app             = app || Rack::File.new(@root)
  @listing_view    = File.read(File.expand_path('../directory.erb', __FILE__))
end

Public Instance Methods

_call(env) click to toggle source
# File lib/forward/static/app.rb, line 92
def _call(env)
  @env       = env
  @path_info = Rack::Utils.unescape(env['PATH_INFO'])

  if forbidden?
    render_404
  else
    @path = File.join(@root, @path_info)
    process
  end
end
call(env) click to toggle source
# File lib/forward/static/app.rb, line 88
def call(env)
  dup._call(env)
end

Private Instance Methods

forbidden?() click to toggle source
# File lib/forward/static/app.rb, line 106
def forbidden?
  @path_info =~ /\.\./
end
has_index?() click to toggle source
# File lib/forward/static/app.rb, line 117
def has_index?
  File.exist?(File.join(@path, 'index.html'))
end
process() click to toggle source
# File lib/forward/static/app.rb, line 121
def process
  return render_404 unless File.exist?(@path)

  @stat = File.stat(@path)

  raise Errno::ENOENT, 'No such file or directory' unless @stat.readable?

  if @stat.directory?
    return render_404 unless @path.end_with?('/')
    return render_directory_listing unless has_index?

    @env['PATH_INFO'] << 'index.html'
  end

  Rack::File.new(@root).call(@env)

rescue Errno::ENOENT, Errno::ELOOP => e
  Forward.logger.debug e
  Forward.logger.debug e.message
  render_404
end
render_404() click to toggle source
# File lib/forward/static/app.rb, line 144
def render_404
  body    = "Not Found: #{@path_info}\n"
  headers = {
    "Content-Type"   => "text/plain",
    "Content-Length" => Rack::Utils.bytesize(body).to_s,
    "X-Cascade"      => "pass"
  }

  [404, headers, [body]]
end
render_directory_listing() click to toggle source
# File lib/forward/static/app.rb, line 110
def render_directory_listing
  context = TemplateContext.new(@root, @path_info)
  body    = ERB.new(@listing_view).result(context.get_binding)

  [ 200, {'Content-Type' => 'text/html; charset=utf-8'}, [body] ]
end