use Rack::File for serving static files
This commit is contained in:
parent
3233c16ee6
commit
8d6a1b35bb
|
@ -187,9 +187,6 @@ module Sinatra
|
||||||
|
|
||||||
# Use the contents of the file at +path+ as the response body.
|
# Use the contents of the file at +path+ as the response body.
|
||||||
def send_file(path, opts={})
|
def send_file(path, opts={})
|
||||||
stat = File.stat(path)
|
|
||||||
last_modified(opts[:last_modified] || stat.mtime)
|
|
||||||
|
|
||||||
if opts[:type] or not response['Content-Type']
|
if opts[:type] or not response['Content-Type']
|
||||||
content_type opts[:type] || File.extname(path), :default => 'application/octet-stream'
|
content_type opts[:type] || File.extname(path), :default => 'application/octet-stream'
|
||||||
end
|
end
|
||||||
|
@ -200,58 +197,17 @@ module Sinatra
|
||||||
response['Content-Disposition'] = 'inline'
|
response['Content-Disposition'] = 'inline'
|
||||||
end
|
end
|
||||||
|
|
||||||
file_length = opts[:length] || stat.size
|
last_modified opts[:last_modified] if opts[:last_modified]
|
||||||
sf = StaticFile.open(path, 'rb')
|
|
||||||
if ! sf.parse_ranges(env, file_length)
|
file = Rack::File.new nil
|
||||||
response['Content-Range'] = "bytes */#{file_length}"
|
file.path = path
|
||||||
halt 416
|
result = file.serving env
|
||||||
elsif r=sf.range
|
result[1].each { |k,v| headers[k] ||= v }
|
||||||
response['Content-Range'] = "bytes #{r.begin}-#{r.end}/#{file_length}"
|
halt result[0], result[2]
|
||||||
response['Content-Length'] = (r.end - r.begin + 1).to_s
|
|
||||||
halt 206, sf
|
|
||||||
else
|
|
||||||
response['Content-Length'] ||= file_length.to_s
|
|
||||||
halt sf
|
|
||||||
end
|
|
||||||
rescue Errno::ENOENT
|
rescue Errno::ENOENT
|
||||||
not_found
|
not_found
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rack response body used to deliver static files. The file contents are
|
|
||||||
# generated iteratively in 8K chunks.
|
|
||||||
class StaticFile < ::File #:nodoc:
|
|
||||||
alias_method :to_path, :path
|
|
||||||
|
|
||||||
attr_accessor :range # a Range or nil
|
|
||||||
|
|
||||||
# Checks for byte-ranges in the request and sets self.range appropriately.
|
|
||||||
# Returns false if the ranges are unsatisfiable and the request should return 416.
|
|
||||||
def parse_ranges(env, size)
|
|
||||||
r = Rack::Utils.byte_ranges(env, size)
|
|
||||||
return false if r == [] # Unsatisfiable; report error
|
|
||||||
@range = r[0] if r && r.length == 1 # Ignore multiple-range requests for now
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
CHUNK_SIZE = 8192
|
|
||||||
|
|
||||||
def each
|
|
||||||
if @range
|
|
||||||
self.pos = @range.begin
|
|
||||||
length = @range.end - @range.begin + 1
|
|
||||||
while length > 0 && (buf = read([CHUNK_SIZE,length].min))
|
|
||||||
yield buf
|
|
||||||
length -= buf.length
|
|
||||||
end
|
|
||||||
else
|
|
||||||
rewind
|
|
||||||
while buf = read(CHUNK_SIZE)
|
|
||||||
yield buf
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Specify response freshness policy for HTTP caches (Cache-Control header).
|
# Specify response freshness policy for HTTP caches (Cache-Control header).
|
||||||
# Any number of non-value directives (:public, :private, :no_cache,
|
# Any number of non-value directives (:public, :private, :no_cache,
|
||||||
# :no_store, :must_revalidate, :proxy_revalidate) may be passed along with
|
# :no_store, :must_revalidate, :proxy_revalidate) may be passed along with
|
||||||
|
|
Loading…
Reference in New Issue