Class: Rack::Directory
Relationships & Source Files | |
Namespace Children | |
Classes:
| |
Inherits: | Object |
Defined in: | lib/rack/directory.rb |
Overview
Directory
serves entries below the #root given, according to the path info of the ::Rack
request. If a directory is found, the file’s contents will be presented in an html based index. If a file is found, the env will be passed to the specified app
.
If app
is not specified, a Files
of the same #root will be used.
Constant Summary
-
DIR_FILE =
# File 'lib/rack/directory.rb', line 20"<tr><td class='name'><a href='%s'>%s</a></td><td class='size'>%s</td><td class='type'>%s</td><td class='mtime'>%s</td></tr>\n"
-
DIR_PAGE_FOOTER =
# File 'lib/rack/directory.rb', line 43<<-PAGE </table> <hr /> </body></html> PAGE
-
DIR_PAGE_HEADER =
# File 'lib/rack/directory.rb', line 21<<-PAGE <html><head> <title>%s</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <style type='text/css'> table { width:100%%; } .name { text-align:left; } .size, .mtime { text-align:right; } .type { width:11em; } .mtime { width:15em; } </style> </head><body> <h1>%s</h1> <hr /> <table> <tr> <th class='name'>Name</th> <th class='size'>Size</th> <th class='type'>Type</th> <th class='mtime'>Last Modified</th> </tr> PAGE
-
FILESIZE_FORMAT =
Stolen from Ramaze
[ ['%.1fT', 1 << 40], ['%.1fG', 1 << 30], ['%.1fM', 1 << 20], ['%.1fK', 1 << 10], ]
Class Method Summary
-
.new(root, app = nil) ⇒ Directory
constructor
Set the root directory and application for serving files.
Instance Attribute Summary
-
#root
readonly
The root of the directory hierarchy.
Instance Method Summary
- #call(env)
-
#check_bad_request(path_info)
::Rack
response to use for requests with invalid paths, or nil if path is valid. -
#check_forbidden(path_info)
::Rack
response to use for requests with paths outside the root, or nil if path is inside the root. -
#entity_not_found(path_info)
::Rack
response to use for unreadable and non-file, non-directory entries. -
#filesize_format(int)
Provide human readable file sizes.
-
#get(env)
Internals of request handling.
-
#list_directory(path_info, path, script_name)
::Rack
response to use for directories under the root. -
#list_path(env, path, path_info, script_name)
::Rack
response to use for files and directories under the root. -
#stat(path)
File::Stat
for the given path, but return nil for missing/bad entries.
Constructor Details
.new(root, app = nil) ⇒ Directory
Set the root directory and application for serving files.
Instance Attribute Details
#root (readonly)
The root of the directory hierarchy. Only requests for files and directories inside of the root directory are supported.
# File 'lib/rack/directory.rb', line 80
attr_reader :root
Instance Method Details
#call(env)
[ GitHub ]# File 'lib/rack/directory.rb', line 89
def call(env) # strip body if this is a HEAD call @head.call env end
#check_bad_request(path_info)
::Rack
response to use for requests with invalid paths, or nil if path is valid.
# File 'lib/rack/directory.rb', line 109
def check_bad_request(path_info) return if Utils.valid_path?(path_info) body = "Bad Request\n" [400, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.bytesize.to_s, "x-cascade" => "pass" }, [body]] end
#check_forbidden(path_info)
::Rack
response to use for requests with paths outside the root, or nil if path is inside the root.
# File 'lib/rack/directory.rb', line 119
def check_forbidden(path_info) return unless path_info.include? ".." return if ::File. (::File.join(@root, path_info)).start_with?(@root) body = "Forbidden\n" [403, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.bytesize.to_s, "x-cascade" => "pass" }, [body]] end
#entity_not_found(path_info)
::Rack
response to use for unreadable and non-file, non-directory entries.
# File 'lib/rack/directory.rb', line 181
def entity_not_found(path_info) body = "Entity not found: #{path_info}\n" [404, { CONTENT_TYPE => "text/plain", CONTENT_LENGTH => body.bytesize.to_s, "x-cascade" => "pass" }, [body]] end
#filesize_format(int)
Provide human readable file sizes
# File 'lib/rack/directory.rb', line 197
def filesize_format(int) FILESIZE_FORMAT.each do |format, size| return format % (int.to_f / size) if int >= size end "#{int}B" end
#get(env)
Internals of request handling. Similar to call but does not remove body for HEAD requests.
# File 'lib/rack/directory.rb', line 96
def get(env) script_name = env[SCRIPT_NAME] path_info = Utils.unescape_path(env[PATH_INFO]) if client_error_response = check_bad_request(path_info) || check_forbidden(path_info) client_error_response else path = ::File.join(@root, path_info) list_path(env, path, path_info, script_name) end end
#list_directory(path_info, path, script_name)
::Rack
response to use for directories under the root.
# File 'lib/rack/directory.rb', line 130
def list_directory(path_info, path, script_name) url_head = (script_name.split('/') + path_info.split('/')).map do |part| Utils.escape_path part end # Globbing not safe as path could contain glob metacharacters body = DirectoryBody.new(@root, path, ->(basename) do stat = stat(::File.join(path, basename)) next unless stat url = ::File.join(*url_head + [Utils.escape_path(basename)]) mtime = stat.mtime.httpdate if stat.directory? type = 'directory' size = '-' url << '/' if basename == '..' basename = 'Parent Directory' else basename << '/' end else type = Mime.mime_type(::File.extname(basename)) size = filesize_format(stat.size) end [ url, basename, size, type, mtime ] end) [ 200, { CONTENT_TYPE => 'text/html; charset=utf-8' }, body ] end
#list_path(env, path, path_info, script_name)
::Rack
response to use for files and directories under the root. Unreadable and non-file, non-directory entries will get a 404 response.
# File 'lib/rack/directory.rb', line 171
def list_path(env, path, path_info, script_name) if (stat = stat(path)) && stat.readable? return @app.call(env) if stat.file? return list_directory(path_info, path, script_name) if stat.directory? end entity_not_found(path_info) end
#stat(path)
File::Stat
for the given path, but return nil for missing/bad entries.
# File 'lib/rack/directory.rb', line 163
def stat(path) ::File.stat(path) rescue Errno::ENOENT, Errno::ELOOP return nil end