In Files

Parent

Class Index [+]

Quicksearch

Rack::File

Rack::File serves files below the root directory given, according to the path info of the Rack request. e.g. when Rack::File.new(“/etc”) is used, you can access ‘passwd’ file as localhost:9292/passwd

Handlers can detect if bodies are a Rack::File, and use mechanisms like sendfile on the path.

Constants

SEPS
ALLOWED_VERBS
F

Attributes

root[RW]
path[RW]
cache_control[RW]

Public Class Methods

new(root, cache_control = nil) click to toggle source
    # File lib/rack/file.rb, line 24
24:     def initialize(root, cache_control = nil)
25:       @root = root
26:       @cache_control = cache_control
27:     end

Public Instance Methods

_call(env) click to toggle source
    # File lib/rack/file.rb, line 35
35:     def _call(env)
36:       unless ALLOWED_VERBS.include? env["REQUEST_METHOD"]
37:         return fail(405, "Method Not Allowed")
38:       end
39: 
40:       @path_info = Utils.unescape(env["PATH_INFO"])
41:       parts = @path_info.split SEPS
42: 
43:       parts.inject(0) do |depth, part|
44:         case part
45:         when '', '.'
46:           depth
47:         when '..'
48:           return fail(404, "Not Found") if depth - 1 < 0
49:           depth - 1
50:         else
51:           depth + 1
52:         end
53:       end
54: 
55:       @path = F.join(@root, *parts)
56: 
57:       available = begin
58:         F.file?(@path) && F.readable?(@path)
59:       rescue SystemCallError
60:         false
61:       end
62: 
63:       if available
64:         serving(env)
65:       else
66:         fail(404, "File not found: #{@path_info}")
67:       end
68:     end
call(env) click to toggle source
    # File lib/rack/file.rb, line 29
29:     def call(env)
30:       dup._call(env)
31:     end
each() click to toggle source
     # File lib/rack/file.rb, line 112
112:     def each
113:       F.open(@path, "rb") do |file|
114:         file.seek(@range.begin)
115:         remaining_len = @range.end-@range.begin+1
116:         while remaining_len > 0
117:           part = file.read([8192, remaining_len].min)
118:           break unless part
119:           remaining_len -= part.length
120: 
121:           yield part
122:         end
123:       end
124:     end
serving(env) click to toggle source
     # File lib/rack/file.rb, line 70
 70:     def serving(env)
 71:       last_modified = F.mtime(@path).httpdate
 72:       return [304, {}, []] if env['HTTP_IF_MODIFIED_SINCE'] == last_modified
 73:       response = [
 74:         200,
 75:         {
 76:           "Last-Modified"  => last_modified,
 77:           "Content-Type"   => Mime.mime_type(F.extname(@path), 'text/plain')
 78:         },
 79:         env["REQUEST_METHOD"] == "HEAD" ? [] : self
 80:       ]
 81:       response[1].merge! 'Cache-Control' => @cache_control if @cache_control
 82: 
 83:       # NOTE:
 84:       #   We check via File::size? whether this file provides size info
 85:       #   via stat (e.g. /proc files often don't), otherwise we have to
 86:       #   figure it out by reading the whole file into memory.
 87:       size = F.size?(@path) || Utils.bytesize(F.read(@path))
 88: 
 89:       ranges = Rack::Utils.byte_ranges(env, size)
 90:       if ranges.nil? || ranges.length > 1
 91:         # No ranges, or multiple ranges (which we don't support):
 92:         # TODO: Support multiple byte-ranges
 93:         response[0] = 200
 94:         @range = 0..size-1
 95:       elsif ranges.empty?
 96:         # Unsatisfiable. Return error, and file size:
 97:         response = fail(416, "Byte range unsatisfiable")
 98:         response[1]["Content-Range"] = "bytes */#{size}"
 99:         return response
100:       else
101:         # Partial content:
102:         @range = ranges[0]
103:         response[0] = 206
104:         response[1]["Content-Range"]  = "bytes #{@range.begin}-#{@range.end}/#{size}"
105:         size = @range.end - @range.begin + 1
106:       end
107: 
108:       response[1]["Content-Length"] = size.to_s
109:       response
110:     end

Private Instance Methods

fail(status, body) click to toggle source
     # File lib/rack/file.rb, line 128
128:     def fail(status, body)
129:       body += "\n"
130:       [
131:         status,
132:         {
133:           "Content-Type" => "text/plain",
134:           "Content-Length" => body.size.to_s,
135:           "X-Cascade" => "pass"
136:         },
137:         [body]
138:       ]
139:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.