mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Make sure not to generate Link headers longer than 8kiB
This commit is contained in:
parent
ed8667df5c
commit
2cb25ab35d
2 changed files with 40 additions and 2 deletions
|
@ -521,13 +521,40 @@ module ActionView
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def send_preload_links_header(preload_links)
|
MAX_HEADER_SIZE = 8_000 # Some HTTP client and proxies have a 8kiB header limit
|
||||||
|
def send_preload_links_header(preload_links, max_header_size: MAX_HEADER_SIZE)
|
||||||
if respond_to?(:request) && request
|
if respond_to?(:request) && request
|
||||||
request.send_early_hints("Link" => preload_links.join("\n"))
|
request.send_early_hints("Link" => preload_links.join("\n"))
|
||||||
end
|
end
|
||||||
|
|
||||||
if respond_to?(:response) && response
|
if respond_to?(:response) && response
|
||||||
response.headers["Link"] = [response.headers["Link"].presence, *preload_links].compact.join(",")
|
header = response.headers["Link"]
|
||||||
|
header = header ? header.dup : +""
|
||||||
|
|
||||||
|
# rindex count characters not bytes, but we assume non-ascii characters
|
||||||
|
# are rare in urls, and we have a 192 bytes margin.
|
||||||
|
last_line_offset = header.rindex("\n")
|
||||||
|
last_line_size = if last_line_offset
|
||||||
|
header.bytesize - last_line_offset
|
||||||
|
else
|
||||||
|
header.bytesize
|
||||||
|
end
|
||||||
|
|
||||||
|
preload_links.each do |link|
|
||||||
|
if link.bytesize + last_line_size + 1 < max_header_size
|
||||||
|
unless header.empty?
|
||||||
|
header << ","
|
||||||
|
last_line_size += 1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
header << "\n"
|
||||||
|
last_line_size = 0
|
||||||
|
end
|
||||||
|
header << link
|
||||||
|
last_line_size += link.bytesize
|
||||||
|
end
|
||||||
|
|
||||||
|
response.headers["Link"] = header
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -529,6 +529,17 @@ class AssetTagHelperTest < ActionView::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_generate_links_under_the_max_size
|
||||||
|
with_preload_links_header do
|
||||||
|
100.times do |i|
|
||||||
|
stylesheet_link_tag("http://example.com/style.css?#{i}")
|
||||||
|
javascript_include_tag("http://example.com/all.js?#{i}")
|
||||||
|
end
|
||||||
|
lines = @response.headers["Link"].split("\n")
|
||||||
|
assert_equal 2, lines.size
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_not_preload_links_with_defer
|
def test_should_not_preload_links_with_defer
|
||||||
with_preload_links_header do
|
with_preload_links_header do
|
||||||
javascript_include_tag("http://example.com/all.js", defer: true)
|
javascript_include_tag("http://example.com/all.js", defer: true)
|
||||||
|
|
Loading…
Reference in a new issue