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)