Ensure that cache-control headers are merged #6776
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Scenario
A developer added a before_filter that did:
response.headers['Cache-Control'] = 'no-transform'
in order to avoid mobile carriers from making invalid modifications to content.Issues
expires_* calls were no longer applied (see commit details), and as such, Rack::Cache begun caching all mobile renders.
Arguments
It may be considered that setting only "no-transform" should result in the above behavior. I would stand by this view point, to a large extent, but many developers find these areas confusing. During investigating the root causes, additional bugs or at least vague semantics were found that were also addressed. It can be argued that the commit aligns a little better with the documentation, and applies some notion of POLS, whereby Rails calls / data structures are authoritative. An alternative POLS for many developers may be that the "last modification to Cache-Control should win", in which case this is still a violation if the header is modified after expires_in in a conflicting way.
Extended commit message:
There are several aspects to this commit, that don't well fit into broken down
commits, so they are detailed here:
documented convention in ConditionalGet is not adhered to, in this case,
response.cache_control is ignored due to
return if self[CACHE_CONTROL].present?
converted to symbols directly, without underscores. This would lead to bugs.
directly in the @cache_control hash, and not respected in many cases
(somewhat adhering to the aforementioned documentation).
The general convention applied is that
expires_*
take precedence, but no longeroverwrite everything and
expires_*
are ALWAYS applied, even if the header isset.
I am still unhappy about the contents of this commit, and the code in general.
Ideally it should be refactored to no longer use :extras. I'd likely recommend
expanding @cache_control into a class, and giving it the power to handle the
merge in a more efficient fashion. Such a commit would be a larger change that
could have additional semantic changes for other libraries unless they utilize
expires_in in very standard ways.