Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ GEM
marcel (1.0.4)
mini_mime (1.1.5)
mini_portile2 (2.8.9)
minitest (5.25.5)
minitest (5.27.0)
minitest-mock (5.27.0)
net-imap (0.5.9)
date
net-protocol
Expand Down Expand Up @@ -207,6 +208,7 @@ PLATFORMS

DEPENDENCIES
debug
minitest-mock
propshaft!
rails (>= 7.0.1)
rake
Expand Down
12 changes: 11 additions & 1 deletion lib/propshaft/asset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
class Propshaft::Asset
attr_reader :path, :logical_path, :load_path

CONTENT_TYPES_WITH_UTF8_CHARSET = [ Mime::Type.lookup("text/html"), Mime::Type.lookup("text/css") ]

class << self
def extract_path_and_digest(digested_path)
digest = digested_path[/-([0-9a-zA-Z]{7,128})\.(?!digested)([^.]|.map)+\z/, 1]
Expand All @@ -27,7 +29,15 @@ def content(encoding: "ASCII-8BIT")
end

def content_type
Mime::Type.lookup_by_extension(logical_path.extname.from(1))
@content_type ||= Mime::Type.lookup_by_extension(logical_path.extname.from(1))
end

def content_type_with_charset
if content_type.in? CONTENT_TYPES_WITH_UTF8_CHARSET
"#{content_type}; charset=utf-8"
else
content_type
end
end

def length
Expand Down
2 changes: 1 addition & 1 deletion lib/propshaft/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def call(env)
200,
{
Rack::CONTENT_LENGTH => compiled_content.length.to_s,
Rack::CONTENT_TYPE => asset.content_type.to_s,
Rack::CONTENT_TYPE => asset.content_type_with_charset.to_s,
VARY => "Accept-Encoding",
Rack::ETAG => "\"#{asset.digest}\"",
Rack::CACHE_CONTROL => "public, max-age=31536000, immutable"
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/assets/first_path/test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<html><body>hello</body></html>
7 changes: 7 additions & 0 deletions test/propshaft/asset_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class Propshaft::AssetTest < ActiveSupport::TestCase
assert_equal "text/css", find_asset("another.css").content_type.to_s
end

test "content type with charset" do
assert_equal "text/plain", find_asset("one.txt").content_type_with_charset.to_s
assert_equal "text/javascript", find_asset("again.js").content_type_with_charset.to_s
assert_equal "text/css; charset=utf-8", find_asset("another.css").content_type_with_charset.to_s
assert_equal "text/html; charset=utf-8", find_asset("test.html").content_type_with_charset.to_s
end

test "length" do
assert_equal 19, find_asset("one.txt").length
end
Expand Down
18 changes: 17 additions & 1 deletion test/propshaft/server_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def call(env)

assert_equal 200, last_response.status
assert_equal last_response.body.bytesize.to_s, last_response.headers['content-length']
assert_equal "text/css", last_response.headers['content-type']
assert_equal "text/css; charset=utf-8", 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']
Expand All @@ -67,6 +67,22 @@ def call(env)
assert_equal 200, last_response.status
end

test "serve an HTML file with charset" do
asset = @assembly.load_path.find("test.html")
get "/assets/#{asset.digested_path}"

assert_equal 200, last_response.status
assert_equal "text/html; charset=utf-8", last_response.headers['content-type']
end

test "serve a JS file without charset" do
asset = @assembly.load_path.find("again.js")
get "/assets/#{asset.digested_path}"

assert_equal 200, last_response.status
assert_equal "text/javascript", last_response.headers['content-type']
end

test "not found" do
get "/assets/not-found.js"

Expand Down
Loading