Skip to content

Commit 6d30baa

Browse files
committed
feat: add Vary header to avoid browser returning the wrong cached content type for a resource
1 parent c52ade2 commit 6d30baa

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

lib/pact_broker/app.rb

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
require 'rack/pact_broker/no_auth'
1616
require 'rack/pact_broker/convert_404_to_hal'
1717
require 'rack/pact_broker/reset_thread_data'
18+
require 'rack/pact_broker/add_vary_header'
1819
require 'sucker_punch'
1920

2021
module PactBroker
@@ -151,6 +152,7 @@ def configure_middleware
151152
@app_builder.use Rack::PactBroker::ResetThreadData
152153
@app_builder.use Rack::PactBroker::StoreBaseURL
153154
@app_builder.use Rack::PactBroker::AddPactBrokerVersionHeader
155+
@app_builder.use Rack::PactBroker::AddVaryHeader
154156
@app_builder.use Rack::Static, :urls => ["/stylesheets", "/css", "/fonts", "/js", "/javascripts", "/images"], :root => PactBroker.project_root.join("public")
155157
@app_builder.use Rack::Static, :urls => ["/favicon.ico"], :root => PactBroker.project_root.join("public/images"), header_rules: [[:all, {'Content-Type' => 'image/x-icon'}]]
156158
@app_builder.use Rack::PactBroker::ConvertFileExtensionToAcceptHeader
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
=begin
2+
3+
This header should fix the situation where using the back button shows the json/csv instead of the html.
4+
5+
> Unlike intermediary caches (such as CDNs), browsers typically do not implement the capability to
6+
store multiple variations per URL. The rationale for this is that the things we typically use Vary
7+
for (mainly Accept-Encoding and Accept-Language) do not change frequently within the context of a
8+
single user. Accept-Encoding might (but probably doesn’t) change upon a browser upgrade, and
9+
Accept-Language would most likely only change if you edit your operating system’s language locale
10+
settings. It also happens to be a lot easier to implement Vary in this way, although some specification
11+
authors believe this was a mistake.
12+
13+
> It’s no great loss most of the time for a browser to store only one variation, but it is important
14+
that we don’t accidentally use a variation that isn’t valid anymore if the “varied on” data does
15+
happen to change.
16+
17+
> The compromise is to treat Vary as a validator, not a key. Browsers compute cache keys in the normal
18+
way (essentially, using the URL), and then if they score a hit, they check that the request satisfies any
19+
ry rules that are baked into the cached response. If it doesn’t, then the browser treats the request as a
20+
iss on the cache, and it moves on to the next layer of cache or out to the network. When a fresh response
21+
is received, it will then overwrite the cached version, even though it’s technically a different variation.
22+
23+
https://www.smashingmagazine.com/2017/11/understanding-vary-header/
24+
=end
25+
26+
module Rack
27+
module PactBroker
28+
class AddVaryHeader
29+
def initialize app
30+
@app = app
31+
end
32+
33+
def call(env)
34+
status, headers, body = @app.call(env)
35+
[status, { "Vary" => "Accept" }.merge(headers || {}), body]
36+
end
37+
end
38+
end
39+
end

lib/rack/pact_broker/convert_file_extension_to_accept_header.rb

+2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ module PactBroker
33
# If the HTML and the CSV group resources are both requested by the browser,
44
# Chrome gets confused by the content types, and when you click back, it tries to load the CSV
55
# instead of the HTML page. So we have to give the CSV resource a different URL (.csv)
6+
# Update: this should be fixed by lib/rack/pact_broker/add_vary_header.rb, but may as well
7+
# leave it now!
68

79
class ConvertFileExtensionToAcceptHeader
810

0 commit comments

Comments
 (0)