Class: Heel::RackApp

Inherits:
Object
  • Object
show all
Defined in:
lib/heel/rackapp.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ RackApp

Returns a new instance of RackApp.



21
22
23
24
25
26
27
28
29
30
# File 'lib/heel/rackapp.rb', line 21

def initialize(options = {})
  @ignore_globs               = options[:ignore_globs] ||= %w( *~ .htaccess . )
  @document_root              = options[:document_root] ||= Dir.pwd
  @directory_listing_allowed  = options[:directory_listing_allowed] ||= true
  @directory_index_html       = options[:directory_index_html] ||= "index.html"
  @using_icons                = options[:using_icons] ||= true
  @icon_url                   = options[:icon_url] ||= "/heel_icons"
  @highlighting               = options[:highlighting] ||= false
  @options                    = options
end

Instance Attribute Details

#directory_index_htmlObject (readonly)

Returns the value of attribute directory_index_html.



15
16
17
# File 'lib/heel/rackapp.rb', line 15

def directory_index_html
  @directory_index_html
end

#document_rootObject (readonly)

Returns the value of attribute document_root.



14
15
16
# File 'lib/heel/rackapp.rb', line 14

def document_root
  @document_root
end

#highlightingObject (readonly)

Returns the value of attribute highlighting.



17
18
19
# File 'lib/heel/rackapp.rb', line 17

def highlighting
  @highlighting
end

#icon_urlObject (readonly)

Returns the value of attribute icon_url.



16
17
18
# File 'lib/heel/rackapp.rb', line 16

def icon_url
  @icon_url
end

#ignore_globsObject (readonly)

Returns the value of attribute ignore_globs.



18
19
20
# File 'lib/heel/rackapp.rb', line 18

def ignore_globs
  @ignore_globs
end

Instance Method Details

#call(env) ⇒ Object

interface to rack, env is a hash

returns [ status, headers, body ]



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/heel/rackapp.rb', line 148

def call(env)
  req = Heel::Request.new(env, document_root)
  if req.get? then
    if req.forbidden? or should_ignore?(req.request_path) then
      return ErrorResponse.new(req.path_info,"You do not have permissionto view #{req.path_info}",403).finish 
    end
    return ErrorResponse.new(req.path_info, "File not found: #{req.path_info}",404).finish unless req.found?
    return directory_index_response(req)                           if req.for_directory?
    return file_response(req)                                      if req.for_file?
  else
    return ErrorResponse.new(req.path_info,
                             "Method #{req.request_method} Not Allowed. Only GET is honored.", 
                             405, 
                             { "Allow" => "GET" }).finish
  end
end

#directory_index_response(req) ⇒ Object

formulate a directory index response



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/heel/rackapp.rb', line 62

def directory_index_response(req)
  response = ::Rack::Response.new
  dir_index = File.join(req.request_path, directory_index_html) 
  if File.file?(dir_index) && File.readable?(dir_index) then
    response['Content-Type']   = mime_map.mime_type_of(dir_index).to_s
    response.write( File.read( dir_index ) )
  elsif directory_listing_allowed? then
    body                       = directory_indexer.index_page_for(req)
    response['Content-Type']   = 'text/html'
    response.write( body )
  else
    return ::Heel::ErrorResponse.new(req.path_info,"Directory index is forbidden", 403).finish
  end
  return response.finish
end

#directory_index_template_fileObject



44
45
46
# File 'lib/heel/rackapp.rb', line 44

def directory_index_template_file
  @directory_index_template_file ||= Heel::Configuration.data_path("listing.rhtml")
end

#directory_indexerObject



48
49
50
# File 'lib/heel/rackapp.rb', line 48

def directory_indexer
  @directory_indexer ||= DirectoryIndexer.new( directory_index_template_file, @options )
end

#directory_listing_allowed?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/heel/rackapp.rb', line 32

def directory_listing_allowed?
  @directory_listing_allowed
end

#file_response(req) ⇒ Object

formulate a file content response. Possibly a rouge highlighted file if it is a type that rouge can deal with and the file is not already an html file.



119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/heel/rackapp.rb', line 119

def file_response(req)
  response = ::Rack::Response.new
  response['Last-Modified'] = req.stat.mtime.rfc822
  file_type = mime_map.mime_type_of(req.request_path)

  if highlighting? and req.highlighting? then
    if file_type && (file_type != 'text/html') then
      body                       =  highlight_contents(req, file_type)
      response['Content-Type']   = 'text/html'
      response['Content-Length'] = body.length.to_s
      response.write( body )
      return response.finish
    end
  end

  # fall through to a default file return
  response['Content-Type'] = file_type.to_s
  File.open( req.request_path ) do |f|
    while p = f.read( 8192 ) do
      response.write( p )
    end
  end
  return response.finish
end

#highlight_contents(req, file_type) ⇒ Object



86
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
# File 'lib/heel/rackapp.rb', line 86

def highlight_contents(req, file_type)
  source = slurp_path(req.request_path)
  # only do a rouge type check if we are going to use rouge in the
  # response
  lexer = ::Rouge::Lexer.guess(
    filename: req.request_path,
    source: source,
    mime_type: file_type
  )

  formatter = ::Rouge::Formatters::HTMLPygments.new(::Rouge::Formatters::HTML.new)
  content = formatter.format(lexer.lex(source))

  body = <<-EOM
  <html>
    <head>
      <title>#{req.path_info}</title>
      <link href='/heel_css/syntax-highlighting.css' rel='stylesheet' type='text/css'>
    </head>
    <body>
      #{content}
    </body>
  </html>
  EOM

  return body
end

#highlighting?Boolean

Returns:

  • (Boolean)


36
37
38
# File 'lib/heel/rackapp.rb', line 36

def highlighting?
  @highlighting
end

#mime_mapObject



40
41
42
# File 'lib/heel/rackapp.rb', line 40

def mime_map
  @mime_map ||= Heel::MimeMap.new
end

#should_ignore?(fname) ⇒ Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
# File 'lib/heel/rackapp.rb', line 53

def should_ignore?(fname)
  ignore_globs.each do |glob|
    return true if ::File.fnmatch(glob,fname)
  end
  false 
end

#slurp_path(path) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/heel/rackapp.rb', line 78

def slurp_path(path)
  source = nil
  File.open(path, 'rt:bom|utf-8') do |f|
    source = f.read
  end
  return source
end