From 5336800c4075e486357ad9e2013a07556e159c4c Mon Sep 17 00:00:00 2001 From: Sebastien Faure Date: Tue, 5 Sep 2023 15:34:57 +0200 Subject: [PATCH 1/2] Add service-worker-allowed header by default --- README.md | 5 ++++- lib/propshaft/server.rb | 21 ++++++++++----------- test/propshaft/server_test.rb | 25 +++++++++++++++++++------ 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index a18d46f..f5f2c41 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ If you need to put multiple files that refer to each other through Propshaft, li ## Improving performance in development -Before every request Propshaft checks if any asset was updated to decide if a cache sweep is needed. This verification is done using the application's configured file watcher which, by default, is `ActiveSupport::FileUpdateChecker`. +Before every request Propshaft checks if any asset was updated to decide if a cache sweep is needed. This verification is done using the application's configured file watcher which, by default, is `ActiveSupport::FileUpdateChecker`. If you have a lot of assets in your project, you can improve performance by adding the `listen` gem to the development group in your Gemfile, and this line to the `development.rb` environment file: @@ -37,6 +37,9 @@ If you have a lot of assets in your project, you can improve performance by addi config.file_watcher = ActiveSupport::EventedFileUpdateChecker ``` +## Service-Worker-Allowed Header + +A **"Service-Worker-Allowed"** header can be added through the `Rails.configuration.assets.service_worker_scope` variable in your environment configuration file. ## Migrating from Sprockets diff --git a/lib/propshaft/server.rb b/lib/propshaft/server.rb index 67be08e..254120c 100644 --- a/lib/propshaft/server.rb +++ b/lib/propshaft/server.rb @@ -10,18 +10,17 @@ def call(env) if (asset = @assembly.load_path.find(path)) && asset.fresh?(digest) compiled_content = @assembly.compilers.compile(asset) + headers = { + Rack::CONTENT_LENGTH => compiled_content.length.to_s, + Rack::CONTENT_TYPE => asset.content_type.to_s, + VARY => "Accept-Encoding", + Rack::ETAG => asset.digest, + Rack::CACHE_CONTROL => "public, max-age=31536000, immutable" + } - [ - 200, - { - Rack::CONTENT_LENGTH => compiled_content.length.to_s, - Rack::CONTENT_TYPE => asset.content_type.to_s, - VARY => "Accept-Encoding", - Rack::ETAG => asset.digest, - Rack::CACHE_CONTROL => "public, max-age=31536000, immutable" - }, - [ compiled_content ] - ] + headers.merge!("Service-Worker-Allowed" => Rails.configuration.assets.service_worker_scope) if Rails.configuration.assets.service_worker_scope + + [ 200, headers, [ compiled_content ] ] else [ 404, { Rack::CONTENT_TYPE => "text/plain", Rack::CONTENT_LENGTH => "9" }, [ "Not found" ] ] end diff --git a/test/propshaft/server_test.rb b/test/propshaft/server_test.rb index c94a1e3..f68e966 100644 --- a/test/propshaft/server_test.rb +++ b/test/propshaft/server_test.rb @@ -16,17 +16,30 @@ class Propshaft::ServerTest < ActiveSupport::TestCase end test "serve a compiled file" do + Rails.configuration.assets.stub :service_worker_scope, "/" do + asset = @assembly.load_path.find("foobar/source/test.css") + get "/#{asset.digested_path}" + + assert_equal 200, last_response.status + assert_equal "94", last_response.headers['content-length'] + assert_equal "text/css", last_response.headers['content-type'] + assert_equal "Accept-Encoding", last_response.headers['vary'] + assert_equal asset.digest, last_response.headers['etag'] + assert_equal "/", last_response.headers['service-worker-allowed'] + assert_equal "public, max-age=31536000, immutable", last_response.headers['cache-control'] + assert_equal ".hero { background: url(\"/foobar/source/file-3e6a129785ee3caf8eff23db339997e85334bfa9.jpg\") }\n", + last_response.body + end + end + + test "serve a compiled file without service-worker-allowed" do asset = @assembly.load_path.find("foobar/source/test.css") get "/#{asset.digested_path}" assert_equal 200, last_response.status - assert_equal "94", last_response.headers['content-length'] - assert_equal "text/css", last_response.headers['content-type'] - assert_equal "Accept-Encoding", last_response.headers['vary'] - assert_equal asset.digest, last_response.headers['etag'] - assert_equal "public, max-age=31536000, immutable", last_response.headers['cache-control'] + assert_nil last_response.headers['service-worker-allowed'] assert_equal ".hero { background: url(\"/foobar/source/file-3e6a129785ee3caf8eff23db339997e85334bfa9.jpg\") }\n", - last_response.body + last_response.body end test "serve a predigested file" do From 319f09a4abf88bccd1647694121e4567cb86eec5 Mon Sep 17 00:00:00 2001 From: Sebastien Faure Date: Wed, 17 Jan 2024 13:08:57 +0100 Subject: [PATCH 2/2] Add headers configuration variable --- README.md | 8 ++++++-- lib/propshaft/server.rb | 2 +- test/propshaft/server_test.rb | 28 ++++++++++++++++------------ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 26e9de6..4df12c5 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,13 @@ If you have a lot of assets in your project, you can improve performance by addi config.file_watcher = ActiveSupport::EventedFileUpdateChecker ``` -## Service-Worker-Allowed Header +## Custom Headers -A **"Service-Worker-Allowed"** header can be added through the `Rails.configuration.assets.service_worker_scope` variable in your environment configuration file. +Customs headers can be added through the `Rails.configuration.assets.headers` variable in your environment configuration file. Your headers will be merged with default headers, overriding existing headers. + +```ruby +Rails.configuration.assets.headers = {"service-worker-allowed" => "/", "cache-control" => "public, max-age=604800, immutable"} +``` ## Migrating from Sprockets diff --git a/lib/propshaft/server.rb b/lib/propshaft/server.rb index 9267fcd..22eb358 100644 --- a/lib/propshaft/server.rb +++ b/lib/propshaft/server.rb @@ -19,7 +19,7 @@ def call(env) Rack::CACHE_CONTROL => "public, max-age=31536000, immutable" } - headers.merge!("Service-Worker-Allowed" => Rails.configuration.assets.service_worker_scope) if Rails.configuration.assets.service_worker_scope + headers.merge!(Rails.configuration.assets.headers) if Rails.configuration.assets.headers [ 200, headers, [ compiled_content ] ] else diff --git a/test/propshaft/server_test.rb b/test/propshaft/server_test.rb index be6541b..63d924f 100644 --- a/test/propshaft/server_test.rb +++ b/test/propshaft/server_test.rb @@ -16,7 +16,21 @@ class Propshaft::ServerTest < ActiveSupport::TestCase end test "serve a compiled file" do - Rails.configuration.assets.stub :service_worker_scope, "/" do + asset = @assembly.load_path.find("foobar/source/test.css") + get "/#{asset.digested_path}" + + assert_equal 200, last_response.status + assert_equal "62", last_response.headers['content-length'] + assert_equal "text/css", last_response.headers['content-type'] + assert_equal "Accept-Encoding", last_response.headers['vary'] + assert_equal asset.digest, last_response.headers['etag'] + assert_equal "public, max-age=31536000, immutable", last_response.headers['cache-control'] + assert_equal ".hero { background: url(\"/foobar/source/file-3e6a1297.jpg\") }\n", + last_response.body + end + + test "serve a compiled file with custom headers" do + Rails.configuration.assets.stub :headers, {"service-worker-allowed" => "/", "cache-control" => "public, max-age=604800, immutable"} do asset = @assembly.load_path.find("foobar/source/test.css") get "/#{asset.digested_path}" @@ -25,23 +39,13 @@ class Propshaft::ServerTest < ActiveSupport::TestCase assert_equal "text/css", last_response.headers['content-type'] assert_equal "Accept-Encoding", last_response.headers['vary'] assert_equal asset.digest, last_response.headers['etag'] - assert_equal "public, max-age=31536000, immutable", last_response.headers['cache-control'] assert_equal "/", last_response.headers['service-worker-allowed'] + assert_equal "public, max-age=604800, immutable", last_response.headers['cache-control'] assert_equal ".hero { background: url(\"/foobar/source/file-3e6a1297.jpg\") }\n", last_response.body end end - test "serve a compiled file without service-worker-allowed" do - asset = @assembly.load_path.find("foobar/source/test.css") - get "/#{asset.digested_path}" - - assert_equal 200, last_response.status - assert_nil last_response.headers['service-worker-allowed'] - assert_equal ".hero { background: url(\"/foobar/source/file-3e6a1297.jpg\") }\n", - last_response.body - end - test "serve a predigested file" do asset = @assembly.load_path.find("file-already-abcdefVWXYZ0123456789_-.digested.css") get "/#{asset.digested_path}"