mirror of
https://gitea.invidious.io/iv-org/shard-kemal.git
synced 2024-08-15 00:53:36 +00:00
moved static file handler code to send_file (#330)
This commit is contained in:
parent
e276c0a278
commit
298a4b234b
2 changed files with 76 additions and 78 deletions
|
@ -81,7 +81,8 @@ def headers(env, additional_headers)
|
|||
env.response.headers.merge!(additional_headers)
|
||||
end
|
||||
|
||||
# Send a file with given path and default `application/octet-stream` mime_type.
|
||||
# Send a file with given path and base the mime-type on the file extension
|
||||
# or default `application/octet-stream` mime_type.
|
||||
#
|
||||
# send_file env, "./path/to/file"
|
||||
#
|
||||
|
@ -89,11 +90,82 @@ end
|
|||
#
|
||||
# send_file env, "./path/to/file", "image/jpeg"
|
||||
def send_file(env, path : String, mime_type : String? = nil)
|
||||
config = Kemal.config.serve_static
|
||||
file_path = File.expand_path(path, Dir.current)
|
||||
mime_type ||= "application/octet-stream"
|
||||
mime_type ||= Kemal::Utils.mime_type(file_path)
|
||||
env.response.content_type = mime_type
|
||||
env.response.content_length = File.size(file_path)
|
||||
minsize = 860 # http://webmasters.stackexchange.com/questions/31750/what-is-recommended-minimum-object-size-for-gzip-performance-benefits ??
|
||||
request_headers = env.request.headers
|
||||
filesize = File.size(file_path)
|
||||
File.open(file_path) do |file|
|
||||
if env.request.method == "GET" && env.request.headers.has_key?("Range")
|
||||
next multipart(file, env)
|
||||
end
|
||||
if request_headers.includes_word?("Accept-Encoding", "gzip") && config.is_a?(Hash) && config["gzip"] == true && filesize > minsize && Kemal::Utils.zip_types(file_path)
|
||||
env.response.headers["Content-Encoding"] = "gzip"
|
||||
Gzip::Writer.open(env.response) do |deflate|
|
||||
IO.copy(file, deflate)
|
||||
end
|
||||
elsif request_headers.includes_word?("Accept-Encoding", "deflate") && config.is_a?(Hash) && config["gzip"]? == true && filesize > minsize && Kemal::Utils.zip_types(file_path)
|
||||
env.response.headers["Content-Encoding"] = "deflate"
|
||||
Flate::Writer.new(env.response) do |deflate|
|
||||
IO.copy(file, deflate)
|
||||
end
|
||||
else
|
||||
env.response.content_length = filesize
|
||||
IO.copy(file, env.response)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private def multipart(file, env)
|
||||
# See http://httpwg.org/specs/rfc7233.html
|
||||
fileb = file.size
|
||||
|
||||
range = env.request.headers["Range"]
|
||||
match = range.match(/bytes=(\d{1,})-(\d{0,})/)
|
||||
|
||||
startb = 0
|
||||
endb = 0
|
||||
|
||||
if match
|
||||
if match.size >= 2
|
||||
startb = match[1].to_i { 0 }
|
||||
end
|
||||
|
||||
if match.size >= 3
|
||||
endb = match[2].to_i { 0 }
|
||||
end
|
||||
end
|
||||
|
||||
if endb == 0
|
||||
endb = fileb
|
||||
end
|
||||
|
||||
if startb < endb && endb <= fileb
|
||||
env.response.status_code = 206
|
||||
env.response.content_length = endb - startb
|
||||
env.response.headers["Accept-Ranges"] = "bytes"
|
||||
env.response.headers["Content-Range"] = "bytes #{startb}-#{endb - 1}/#{fileb}" # MUST
|
||||
|
||||
if startb > 1024
|
||||
skipped = 0
|
||||
# file.skip only accepts values less or equal to 1024 (buffer size, undocumented)
|
||||
until skipped + 1024 > startb
|
||||
file.skip(1024)
|
||||
skipped += 1024
|
||||
end
|
||||
if skipped - startb > 0
|
||||
file.skip(skipped - startb)
|
||||
end
|
||||
else
|
||||
file.skip(startb)
|
||||
end
|
||||
|
||||
IO.copy(file, env.response, endb - startb)
|
||||
else
|
||||
env.response.content_length = fileb
|
||||
env.response.status_code = 200 # Range not satisfable, see 4.4 Note
|
||||
IO.copy(file, env.response)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,29 +51,7 @@ module Kemal
|
|||
end
|
||||
elsif File.exists?(file_path)
|
||||
return if etag(context, file_path)
|
||||
minsize = 860 # http://webmasters.stackexchange.com/questions/31750/what-is-recommended-minimum-object-size-for-gzip-performance-benefits ??
|
||||
context.response.content_type = Utils.mime_type(file_path)
|
||||
request_headers = context.request.headers
|
||||
filesize = File.size(file_path)
|
||||
File.open(file_path) do |file|
|
||||
if context.request.method == "GET" && context.request.headers.has_key?("Range")
|
||||
next multipart(file, context)
|
||||
end
|
||||
if request_headers.includes_word?("Accept-Encoding", "gzip") && config.is_a?(Hash) && config["gzip"] == true && filesize > minsize && Utils.zip_types(file_path)
|
||||
context.response.headers["Content-Encoding"] = "gzip"
|
||||
Gzip::Writer.open(context.response) do |deflate|
|
||||
IO.copy(file, deflate)
|
||||
end
|
||||
elsif request_headers.includes_word?("Accept-Encoding", "deflate") && config.is_a?(Hash) && config["gzip"]? == true && filesize > minsize && Utils.zip_types(file_path)
|
||||
context.response.headers["Content-Encoding"] = "deflate"
|
||||
Flate::Writer.new(context.response) do |deflate|
|
||||
IO.copy(file, deflate)
|
||||
end
|
||||
else
|
||||
context.response.content_length = filesize
|
||||
IO.copy(file, context.response)
|
||||
end
|
||||
end
|
||||
send_file(context, file_path)
|
||||
else
|
||||
call_next(context)
|
||||
end
|
||||
|
@ -88,57 +66,5 @@ module Kemal
|
|||
context.response.status_code = 304 # not modified
|
||||
return true
|
||||
end
|
||||
|
||||
private def multipart(file, env)
|
||||
# See http://httpwg.org/specs/rfc7233.html
|
||||
fileb = file.size
|
||||
|
||||
range = env.request.headers["Range"]
|
||||
match = range.match(/bytes=(\d{1,})-(\d{0,})/)
|
||||
|
||||
startb = 0
|
||||
endb = 0
|
||||
|
||||
if match
|
||||
if match.size >= 2
|
||||
startb = match[1].to_i { 0 }
|
||||
end
|
||||
|
||||
if match.size >= 3
|
||||
endb = match[2].to_i { 0 }
|
||||
end
|
||||
end
|
||||
|
||||
if endb == 0
|
||||
endb = fileb
|
||||
end
|
||||
|
||||
if startb < endb && endb <= fileb
|
||||
env.response.status_code = 206
|
||||
env.response.content_length = endb - startb
|
||||
env.response.headers["Accept-Ranges"] = "bytes"
|
||||
env.response.headers["Content-Range"] = "bytes #{startb}-#{endb - 1}/#{fileb}" # MUST
|
||||
|
||||
if startb > 1024
|
||||
skipped = 0
|
||||
# file.skip only accepts values less or equal to 1024 (buffer size, undocumented)
|
||||
until skipped + 1024 > startb
|
||||
file.skip(1024)
|
||||
skipped += 1024
|
||||
end
|
||||
if skipped - startb > 0
|
||||
file.skip(skipped - startb)
|
||||
end
|
||||
else
|
||||
file.skip(startb)
|
||||
end
|
||||
|
||||
IO.copy(file, env.response, endb - startb)
|
||||
else
|
||||
env.response.content_length = fileb
|
||||
env.response.status_code = 200 # Range not satisfable, see 4.4 Note
|
||||
IO.copy(file, env.response)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue