Set Vary for the request headers PutLocale reads - #21
Merged
Merged
Conversation
A locale taken from Accept-Language, the session or a cookie changes the response for the same URL, so a shared cache must key it on those headers. Add accept-language and cookie for each such source consulted, merged with any existing Vary value.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Before
plug Localize.Plug.PutLocale, from: [:session, :accept_language], two requests to the same URL with an empty session:Problem
cache-control(max-age=0, private, must-revalidate) keeps compliant shared caches out, so this only hurts apps that turn on public caching. Those apps have no easy way to know which headersPutLocaleread.After
PutLocaleaddsaccept-languagefor:accept_languageandcookiefor:sessionand:cookie, for every one of these sources it read, not only the one that decided: withfrom: [:cookie, :query],?locale=destill givesvary: cookie, because a cookie would have won. Sources that are part of the URL (:query,:path,:route,:host) add nothing. Existing values are kept, matched case-insensitively, andvary: *is left alone.Details
Cause:
Localize.Plug.PutLocale.call/2inlib/localize/plug/put_locale.exnever setvary.Design:
locale_from_params/3now also returns the sources it consulted, andput_vary/2maps them to header names and merges them into the existingvaryvalue. This replacesreturn_if_valid_locale/1. On by default, not opt-in: a missingvarygives wrong content from a public cache, while an extravaryonly splits that cache, and with the default privatecache-controlit changes nothing. This followsPlug.Static, which setsvary: Accept-Encodingwhen it negotiates the encoding. An app that wants a better hit rate can put the locale in the URL (:route,:path,:query). The moduledoc says that a{Module, function}source that reads a header must add its ownvary.Tests: new
call/2 - Vary response headertests intest/plug/put_locale_test.exs: header-decided, a query win after an empty cookie, the default after an empty cookie and an invalid header, a URL-only win, merging withAccept-Encoding, and*. They fail onmain.Checks:
mix test(273 passed),mix format --check-formatted,mix compile --warnings-as-errors.mix credo --strictreports only the existingSigil_q.InterpolationTestmodule-name issue.AI disclosure: AI models helped us find this issue, write the change, and review it.