diff --git a/CHANGES.rst b/CHANGES.rst index 78951681..f3b2fab0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -60,6 +60,9 @@ Unreleased conditional requests instead of using a timed cache. :pr:`3828` - ``helpers.safe_join`` is deprecated. Use ``werkzeug.utils.safe_join`` instead. :pr:`3828` +- The request context does route matching before opening the session. + This could allow a session interface to change behavior based on + ``request.endpoint``. :issue:`3776` Version 1.1.2 diff --git a/src/flask/ctx.py b/src/flask/ctx.py index f69ff596..f9cb87d2 100644 --- a/src/flask/ctx.py +++ b/src/flask/ctx.py @@ -361,6 +361,9 @@ class RequestContext: _request_ctx_stack.push(self) + if self.url_adapter is not None: + self.match_request() + # Open the session at the moment that the request context is available. # This allows a custom open_session method to use the request context. # Only open a new session if this is the first time the request was @@ -372,9 +375,6 @@ class RequestContext: if self.session is None: self.session = session_interface.make_null_session(self.app) - if self.url_adapter is not None: - self.match_request() - def pop(self, exc=_sentinel): """Pops the request context and unbinds it by doing that. This will also trigger the execution of functions registered by the diff --git a/tests/test_session_interface.py b/tests/test_session_interface.py new file mode 100644 index 00000000..aa9ecafa --- /dev/null +++ b/tests/test_session_interface.py @@ -0,0 +1,22 @@ +import flask +from flask.sessions import SessionInterface + + +def test_open_session_endpoint_not_none(): + # Define a session interface that breaks if request.endpoint is None + class MySessionInterface(SessionInterface): + def save_session(self): + pass + + def open_session(self, _, request): + assert request.endpoint is not None + + def index(): + return "Hello World!" + + # Confirm a 200 response, indicating that request.endpoint was NOT None + app = flask.Flask(__name__) + app.route("/")(index) + app.session_interface = MySessionInterface() + response = app.test_client().open("/") + assert response.status_code == 200