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)
|
env.response.headers.merge!(additional_headers)
|
||||||
end
|
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"
|
# send_file env, "./path/to/file"
|
||||||
#
|
#
|
||||||
|
@ -89,11 +90,82 @@ end
|
||||||
#
|
#
|
||||||
# send_file env, "./path/to/file", "image/jpeg"
|
# send_file env, "./path/to/file", "image/jpeg"
|
||||||
def send_file(env, path : String, mime_type : String? = nil)
|
def send_file(env, path : String, mime_type : String? = nil)
|
||||||
|
config = Kemal.config.serve_static
|
||||||
file_path = File.expand_path(path, Dir.current)
|
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_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|
|
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)
|
IO.copy(file, env.response)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,29 +51,7 @@ module Kemal
|
||||||
end
|
end
|
||||||
elsif File.exists?(file_path)
|
elsif File.exists?(file_path)
|
||||||
return if etag(context, 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 ??
|
send_file(context, file_path)
|
||||||
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
|
|
||||||
else
|
else
|
||||||
call_next(context)
|
call_next(context)
|
||||||
end
|
end
|
||||||
|
@ -88,57 +66,5 @@ module Kemal
|
||||||
context.response.status_code = 304 # not modified
|
context.response.status_code = 304 # not modified
|
||||||
return true
|
return true
|
||||||
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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue