lib/regurgitator/local_file.rb in regurgitator-0.0.0 vs lib/regurgitator/local_file.rb in regurgitator-0.1.0

- old
+ new

@@ -16,33 +16,61 @@ def initialize(env, path, uri, stat) if modified_since = env["HTTP_IF_MODIFIED_SINCE"] modified_since?(modified_since, stat) or return end + size = stat.size - @response = [ 200, { - "Content-Type" => "application/octet-stream", # always ".fid" - "Content-Length" => stat.size.to_s, - "Last-Modified" => stat.mtime.httpdate, - } ] + headers = { + "Content-Type" => "application/octet-stream", # always ".fid" + "Content-Length" => size.to_s, + "Last-Modified" => stat.mtime.httpdate, + "Accept-Ranges" => "bytes", + } + @response = [ 200, headers ] + + ranges = Rack::Utils.byte_ranges(env, size) + if nil == ranges || ranges.size > 1 + @range = nil + elsif @range = ranges[0] + @response[0] = 206 + headers["Content-Range"] = "bytes #{@range.begin}-#{@range.end}/#{size}" + headers["Content-Length"] = (@range.end - @range.begin + 1).to_s + else + @response[0] = 416 + headers["Content-Range"] = "bytes */#{size}" + @response << [] + return + end + case env["REQUEST_METHOD"] when "GET" @to_path, @uri = path, uri @response << self when "HEAD" @response << [] else - abort "Unexpected REQUEST_METHOD=#{env['REQUEST_METHOD']}" + raise "BUG: Unexpected REQUEST_METHOD=#{env['REQUEST_METHOD']}" end end # normal Rack HTTP server endpoint, used if the server can't handle # +to_path+ def each - buf = "" File.open(@to_path) do |fp| - while fp.read(0x4000, buf) - yield buf + buf = "" + max = 0x4000 + if @range + fp.seek(@range.begin) + len = @range.end - @range.begin + 1 + while len > 0 && fp.read(len > max ? max : len, buf) + len -= buf.size + yield buf + end + else + while fp.read(0x4000, buf) + yield buf + end end end end def modified_since?(modified_since, stat)