diff --git a/flask/sessions.py b/flask/sessions.py index 2dbd8b32..9d937be0 100644 --- a/flask/sessions.py +++ b/flask/sessions.py @@ -405,7 +405,7 @@ class SecureCookieSessionInterface(SessionInterface): # Add a "Vary: Cookie" header if the session was accessed at all. if session.accessed: - response.headers.add('Vary', 'Cookie') + self._patch_vary_cookie_header(response) if not self.should_set_cookie(app, session): return @@ -423,3 +423,16 @@ class SecureCookieSessionInterface(SessionInterface): path=path, secure=secure ) + + def _patch_vary_cookie_header(self, response): + """ + Add a 'Cookie' value to the 'Vary' header if one is not already present. + """ + header = response.headers.get('Vary', '') + headers = [h.strip() for h in header.split(',') if h] + + if not any(h.lower() == 'cookie' for h in headers): + headers.append('Cookie') + + updated_header = ', '.join(headers) + response.headers['Vary'] = updated_header diff --git a/tests/test_basic.py b/tests/test_basic.py index de56cb43..e4d6b2f9 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -520,15 +520,31 @@ def test_session_vary_cookie(app, client): def setdefault(): return flask.session.setdefault('test', 'default') + @app.route('/vary-cookie-header-set') + def vary_cookie_header_set(): + response = flask.Response() + response.headers['Vary'] = 'Cookie' + flask.session['test'] = 'test' + return response + + @app.route('/vary-header-set') + def vary_header_set(): + response = flask.Response() + response.headers['Vary'] = 'Accept-Encoding, Accept-Language' + flask.session['test'] = 'test' + return response + @app.route('/no-vary-header') def no_vary_header(): return '' - def expect(path, header=True): + def expect(path, header_value='Cookie'): rv = client.get(path) - if header: - assert rv.headers['Vary'] == 'Cookie' + if header_value: + # The 'Vary' key should exist in the headers only once. + assert len(rv.headers.get_all('Vary')) == 1 + assert rv.headers['Vary'] == header_value else: assert 'Vary' not in rv.headers @@ -536,7 +552,9 @@ def test_session_vary_cookie(app, client): expect('/get') expect('/getitem') expect('/setdefault') - expect('/no-vary-header', False) + expect('/vary-cookie-header-set') + expect('/vary-header-set', 'Accept-Encoding, Accept-Language, Cookie') + expect('/no-vary-header', None) def test_flashes(app, req_ctx):