move url matching after opening session

This commit is contained in:
David Lord 2019-06-13 12:40:01 -07:00
parent 1ff98a2d21
commit c65863912b
No known key found for this signature in database
GPG Key ID: 7A1C87E3F5BC42A8
4 changed files with 26 additions and 17 deletions

View File

@ -71,6 +71,10 @@ Unreleased
- The ``flask run`` command no longer fails if Python is not built
with SSL support. Using the ``--cert`` option will show an
appropriate error message. :issue:`3211`
- URL matching now occurs after the request context is pushed, rather
than when it's created. This allows custom URL converters to access
the app and request contexts, such as to query a database for an id.
:issue:`3088`
.. _#2935: https://github.com/pallets/flask/issues/2935
.. _#2957: https://github.com/pallets/flask/issues/2957

View File

@ -347,8 +347,8 @@ class RequestContext(object):
of the request.
"""
try:
url_rule, self.request.view_args = self.url_adapter.match(return_rule=True)
self.request.url_rule = url_rule
result = self.url_adapter.match(return_rule=True)
self.request.url_rule, self.request.view_args = result
except HTTPException as e:
self.request.routing_exception = e
@ -381,9 +381,6 @@ class RequestContext(object):
_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
@ -395,6 +392,9 @@ class RequestContext(object):
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

View File

@ -1,9 +1,10 @@
from flask.globals import _app_ctx_stack
from werkzeug.routing import BaseConverter
from flask import has_request_context
from flask import url_for
def test_custom_converters(app, client):
from werkzeug.routing import BaseConverter
class ListConverter(BaseConverter):
def to_python(self, value):
return value.split(",")
@ -20,19 +21,20 @@ def test_custom_converters(app, client):
assert client.get("/1,2,3").data == b"1|2|3"
with app.test_request_context():
assert url_for("index", args=[4, 5, 6]) == "/4,5,6"
def test_model_converters(app, client):
from werkzeug.routing import BaseConverter
class ModelConverterTester(BaseConverter):
def test_context_available(app, client):
class ContextConverter(BaseConverter):
def to_python(self, value):
assert _app_ctx_stack.top is not None
assert has_request_context()
return value
app.url_map.converters["model"] = ModelConverterTester
app.url_map.converters["ctx"] = ContextConverter
@app.route("/<model:user_name>")
def index(user_name):
return user_name, 200
@app.route("/<ctx:name>")
def index(name):
return name
client.get("/admin").data
assert client.get("/admin").data == b"admin"

View File

@ -154,6 +154,9 @@ def test_blueprint_with_subdomain():
ctx = app.test_request_context("/", subdomain="xxx")
assert ctx.request.url == "http://xxx.example.com:1234/foo/"
with ctx:
assert ctx.request.blueprint == bp.name
rv = client.get("/", subdomain="xxx")
assert rv.data == b"http://xxx.example.com:1234/foo/"