Support gzip compression of JS view assets (#1813)

This commit is contained in:
Jonatan Kłosko 2023-03-21 17:45:27 +01:00 committed by GitHub
parent 4a0a958509
commit de310c0c36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 6 deletions

View file

@ -285,6 +285,7 @@ defmodule Livebook.Session do
unless non_empty_dir?(local_assets_path) do
{:ok, archive_binary} = Runtime.read_file(runtime, archive_path)
extract_archive!(archive_binary, local_assets_path)
gzip_files(local_assets_path)
end
end
@ -2198,6 +2199,15 @@ defmodule Livebook.Session do
end
end
defp gzip_files(path) do
for path <- Path.wildcard(Path.join(path, "**")), File.regular?(path) do
with {:ok, content} <- File.read(path) do
compressed = :zlib.gzip(content)
File.write(path <> ".gz", compressed)
end
end
end
defp registered_file_path(session_id, {:file, file_id}) do
%{path: session_dir} = session_tmp_dir(session_id)
Path.join([session_dir, "registered_files", file_id])

View file

@ -117,16 +117,35 @@ defmodule LivebookWeb.SessionController do
case lookup_asset(hash, asset_path) do
{:ok, local_asset_path} ->
conn
|> put_content_type(asset_path)
|> cache_permanently()
|> send_file(200, local_asset_path)
conn =
conn
|> put_content_type(asset_path)
|> cache_permanently()
local_asset_path_gz = local_asset_path <> ".gz"
if accept_encoding?(conn, "gzip") and File.exists?(local_asset_path_gz) do
conn
|> put_resp_header("content-encoding", "gzip")
|> put_resp_header("vary", "Accept-Encoding")
|> send_file(200, local_asset_path_gz)
else
send_file(conn, 200, local_asset_path)
end
:error ->
send_resp(conn, 404, "Not found")
end
end
defp accept_encoding?(conn, encoding) do
encoding? = &String.contains?(&1, [encoding, "*"])
Enum.any?(get_req_header(conn, "accept-encoding"), fn accept ->
accept |> Plug.Conn.Utils.list() |> Enum.any?(encoding?)
end)
end
defp ensure_asset?(session_id, hash, asset_path) do
case lookup_asset(hash, asset_path) do
{:ok, _local_asset_path} ->

View file

@ -172,7 +172,7 @@ defmodule LivebookWeb.SessionControllerTest do
test "skips the session if assets are in cache", %{conn: conn} do
%{notebook: notebook, hash: hash} = notebook_with_js_output()
# Fetch the assets for the first time
conn = start_session_and_request_asset(conn, notebook, hash)
start_session_and_request_asset(conn, notebook, hash)
# Use nonexistent session, so any communication would fail
random_session_id = Livebook.Utils.random_node_aware_id()
@ -196,13 +196,27 @@ defmodule LivebookWeb.SessionControllerTest do
test "returns the requests asset if available in cache", %{conn: conn} do
%{notebook: notebook, hash: hash} = notebook_with_js_output()
# Fetch the assets for the first time
conn = start_session_and_request_asset(conn, notebook, hash)
start_session_and_request_asset(conn, notebook, hash)
conn = get(conn, ~p"/public/sessions/assets/#{hash}/main.js")
assert conn.status == 200
assert "export function init(" <> _ = conn.resp_body
end
test "supports gzip compression", %{conn: conn} do
%{notebook: notebook, hash: hash} = notebook_with_js_output()
start_session_and_request_asset(conn, notebook, hash)
conn =
conn
|> put_req_header("accept-encoding", "gzip")
|> get(~p"/public/sessions/assets/#{hash}/main.js")
assert conn.status == 200
assert "export function init(" <> _ = :zlib.gunzip(conn.resp_body)
end
end
defp start_session_and_request_asset(conn, notebook, hash) do