Skip to content

Commit 0c09ae5

Browse files
authored
Merge pull request rails#48405 from Shopify/refactor-preload-link-header
Stop appending preload links once the head is already 1kB
2 parents 1bdc5a6 + facc260 commit 0c09ae5

File tree

3 files changed

+22
-24
lines changed

3 files changed

+22
-24
lines changed

actionview/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
* Stop generating `Link preload` headers once it has reached 1KB.
2+
3+
Some proxies have trouble handling large headers, but more importantly preload links
4+
have diminishing returns so it's preferable not to go overboard with them.
5+
6+
If tighter control is needed, it's recommended to disable automatic generation of preloads
7+
and to generate them manually from the controller or from a middleware.
8+
9+
*Jean Boussier*
10+
111
* `simple_format` helper now handles a `:sanitize_options` - any extra options you want appending to the sanitize.
212

313
Before:

actionview/lib/action_view/helpers/asset_tag_helper.rb

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,10 @@ def resolve_link_as(extname, mime_type)
633633
end
634634
end
635635

636-
MAX_HEADER_SIZE = 8_000 # Some HTTP client and proxies have a 8kiB header limit
636+
# Some HTTP client and proxies have a 4kiB header limit, but more importantly
637+
# including preload links has diminishing returns so it's best to not go overboard
638+
MAX_HEADER_SIZE = 1_000 # :nodoc:
639+
637640
def send_preload_links_header(preload_links, max_header_size: MAX_HEADER_SIZE)
638641
return if preload_links.empty?
639642
response_present = respond_to?(:response) && response
@@ -644,30 +647,15 @@ def send_preload_links_header(preload_links, max_header_size: MAX_HEADER_SIZE)
644647
end
645648

646649
if response_present
647-
header = response.headers["Link"]
648-
header = header ? header.dup : +""
649-
650-
# rindex count characters not bytes, but we assume non-ascii characters
651-
# are rare in urls, and we have a 192 bytes margin.
652-
last_line_offset = header.rindex("\n")
653-
last_line_size = if last_line_offset
654-
header.bytesize - last_line_offset
655-
else
656-
header.bytesize
657-
end
658-
650+
header = +response.headers["Link"].to_s
659651
preload_links.each do |link|
660-
if link.bytesize + last_line_size + 1 < max_header_size
661-
unless header.empty?
662-
header << ","
663-
last_line_size += 1
664-
end
652+
break if header.bytesize + link.bytesize > max_header_size
653+
654+
if header.empty?
655+
header << link
665656
else
666-
header << "\n"
667-
last_line_size = 0
657+
header << "," << link
668658
end
669-
header << link
670-
last_line_size += link.bytesize
671659
end
672660

673661
response.headers["Link"] = header

actionview/test/template/asset_tag_helper_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,8 @@ def test_should_generate_links_under_the_max_size
648648
stylesheet_link_tag("http://example.com/style.css?#{i}")
649649
javascript_include_tag("http://example.com/all.js?#{i}")
650650
end
651-
lines = @response.headers["Link"].split("\n")
652-
assert_equal 2, lines.size
651+
links = @response.headers["Link"].count(",")
652+
assert_equal 14, links
653653
end
654654
end
655655

0 commit comments

Comments
 (0)