From 81f2ee7815cdc9321ab4f707791cafd3f98e4f4e Mon Sep 17 00:00:00 2001 From: Cris Ward Date: Thu, 28 Sep 2017 11:12:44 +0100 Subject: [PATCH 1/4] Fix for video in safari Video doesn't work safari. It seem to be to do with the content-range header. Safari initially asked for the first byte. However with a single byte request, the header outputs `bytes 0-0/1000` (if this file is 1000 bytes in size) It does work however if we make the end value 1. But removing the `-1` breaks it in chrome. So I suggest this change, which means the end can't be smaller than 1. --- src/kemal/helpers/helpers.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kemal/helpers/helpers.cr b/src/kemal/helpers/helpers.cr index 7e55681..87c8947 100644 --- a/src/kemal/helpers/helpers.cr +++ b/src/kemal/helpers/helpers.cr @@ -156,7 +156,7 @@ private def multipart(file, env : HTTP::Server::Context) 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 + env.response.headers["Content-Range"] = "bytes #{startb}-#{endb > 1 ? endb - 1 : 1}/#{fileb}" # MUST if startb > 1024 skipped = 0 From 6c11f943d0df6e399d42631004678daa08248a7e Mon Sep 17 00:00:00 2001 From: Cris Ward Date: Thu, 28 Sep 2017 12:07:26 +0100 Subject: [PATCH 2/4] Better fix for safari video bug This seems to work everywhere that I've tested. --- src/kemal/helpers/helpers.cr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kemal/helpers/helpers.cr b/src/kemal/helpers/helpers.cr index 87c8947..94b643c 100644 --- a/src/kemal/helpers/helpers.cr +++ b/src/kemal/helpers/helpers.cr @@ -149,14 +149,14 @@ private def multipart(file, env : HTTP::Server::Context) end if endb == 0 - endb = fileb + endb = fileb - 1 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 ? endb - 1 : 1}/#{fileb}" # MUST + env.response.headers["Content-Range"] = "bytes #{startb}-#{endb}/#{fileb}" # MUST if startb > 1024 skipped = 0 From 183ae42a54afe51955d4b3c3d865f05ad22f3306 Mon Sep 17 00:00:00 2001 From: Cris Ward Date: Thu, 28 Sep 2017 14:17:12 +0100 Subject: [PATCH 3/4] corrected content length --- src/kemal/helpers/helpers.cr | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/kemal/helpers/helpers.cr b/src/kemal/helpers/helpers.cr index 94b643c..0d192e3 100644 --- a/src/kemal/helpers/helpers.cr +++ b/src/kemal/helpers/helpers.cr @@ -152,9 +152,10 @@ private def multipart(file, env : HTTP::Server::Context) endb = fileb - 1 end - if startb < endb && endb <= fileb + if startb < endb && endb < fileb + content_length = 1 + endb - startb env.response.status_code = 206 - env.response.content_length = endb - startb + env.response.content_length = content_length env.response.headers["Accept-Ranges"] = "bytes" env.response.headers["Content-Range"] = "bytes #{startb}-#{endb}/#{fileb}" # MUST @@ -172,7 +173,7 @@ private def multipart(file, env : HTTP::Server::Context) file.skip(startb) end - IO.copy(file, env.response, endb - startb) + IO.copy(file, env.response, content_length) else env.response.content_length = fileb env.response.status_code = 200 # Range not satisfable, see 4.4 Note From 03daf2aee2a3322aeda2501395f8ce7224eb5bdf Mon Sep 17 00:00:00 2001 From: Cris Ward Date: Thu, 28 Sep 2017 16:02:37 +0100 Subject: [PATCH 4/4] Added `Accept-Ranges` header --- src/kemal/helpers/helpers.cr | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kemal/helpers/helpers.cr b/src/kemal/helpers/helpers.cr index 0d192e3..a0eb787 100644 --- a/src/kemal/helpers/helpers.cr +++ b/src/kemal/helpers/helpers.cr @@ -98,6 +98,7 @@ def send_file(env : HTTP::Server::Context, path : String, mime_type : String? = file_path = File.expand_path(path, Dir.current) mime_type ||= Kemal::Utils.mime_type(file_path) env.response.content_type = mime_type + env.response.headers["Accept-Ranges"] = "bytes" env.response.headers["X-Content-Type-Options"] = "nosniff" minsize = 860 # http://webmasters.stackexchange.com/questions/31750/what-is-recommended-minimum-object-size-for-gzip-performance-benefits ?? request_headers = env.request.headers