From 7ab6980c8ba15912df13dd1e78242803e8104dd6 Mon Sep 17 00:00:00 2001 From: Lex Date: Sat, 16 Mar 2024 22:48:54 +0800 Subject: [PATCH] Add vary cookie for accessed session as per flask --- examples/hello.py | 5 +++++ src/flask_session/base.py | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/examples/hello.py b/examples/hello.py index 16599b3c..4afc2c1a 100644 --- a/examples/hello.py +++ b/examples/hello.py @@ -29,5 +29,10 @@ def delete(): return "deleted" +@app.route("/") +def hello(): + return "hello world" + + if __name__ == "__main__": app.run(debug=True) diff --git a/src/flask_session/base.py b/src/flask_session/base.py index 6733e373..04c6473c 100644 --- a/src/flask_session/base.py +++ b/src/flask_session/base.py @@ -38,6 +38,13 @@ class ServerSideSession(CallbackDict, SessionMixin): dict) then this must be set to ``True`` manually when modifying that data. The session cookie will only be written to the response if this is ``True``. + .. attribute:: accessed + + When data is read (or attempted read) or written, this is set to ``True``. Used by + :class:`.ServerSideSessionInterface` to add a ``Vary: Cookie`` + header, which allows caching proxies to cache different pages for + different users. + Default is ``False``. .. attribute:: permanent @@ -59,12 +66,26 @@ def __init__( ): def on_update(self) -> None: self.modified = True + self.accessed = True CallbackDict.__init__(self, initial, on_update) self.sid = sid if permanent: self.permanent = permanent self.modified = False + self.accessed = False + + def __getitem__(self, key: str) -> Any: + self.accessed = True + return super().__getitem__(key) + + def get(self, key: str, default: Any = None) -> Any: + self.accessed = True + return super().get(key, default) + + def setdefault(self, key: str, default: Any = None) -> Any: + self.accessed = True + return super().setdefault(key, default) def clear(self) -> None: """Clear the session except for the '_permanent' key.""" @@ -262,6 +283,12 @@ def save_session( # Generate a prefixed session id store_id = self._get_store_id(session.sid) + # Add a "Vary: Cookie" header if the session was accessed at all. + # This assumes the app is checking the session values in a request that + # behaves differently based on those values. ie. session.get("is_authenticated") + if session.accessed: + response.vary.add("Cookie") + # If the session is empty, do not save it to the database or set a cookie if not session: # If the session was deleted (empty and modified), delete the saved session from the database and tell the client to delete the cookie