flask/tests/test_reqctx.py

250 lines
6.5 KiB
Python
Raw Permalink Normal View History

2026-05-01 20:17:23 -07:00
from __future__ import annotations
import collections.abc as cabc
2022-02-08 12:05:17 -08:00
import warnings
2026-05-01 20:17:23 -07:00
from concurrent import futures
2022-02-08 12:05:17 -08:00
2014-09-02 05:26:52 +02:00
import pytest
import flask
from flask.sessions import SecureCookieSessionInterface
from flask.sessions import SessionInterface
2026-05-01 20:17:23 -07:00
from flask.testing import FlaskClient
2014-09-03 21:02:03 +02:00
def test_teardown_on_pop(app):
2014-09-03 20:56:10 +02:00
buffer = []
2014-09-03 20:56:10 +02:00
@app.teardown_request
def end_of_request(exception):
buffer.append(exception)
ctx = app.test_request_context()
ctx.push()
assert buffer == []
ctx.pop()
assert buffer == [None]
def test_teardown_with_previous_exception(app):
2014-09-03 20:56:10 +02:00
buffer = []
2014-09-03 20:56:10 +02:00
@app.teardown_request
def end_of_request(exception):
buffer.append(exception)
try:
raise Exception("dummy")
2014-09-03 20:56:10 +02:00
except Exception:
pass
with app.test_request_context():
assert buffer == []
assert buffer == [None]
def test_teardown_with_handled_exception(app):
buffer = []
@app.teardown_request
def end_of_request(exception):
buffer.append(exception)
with app.test_request_context():
assert buffer == []
try:
raise Exception("dummy")
except Exception:
pass
assert buffer == [None]
def test_proper_test_request_context(app):
app.config.update(SERVER_NAME="localhost.localdomain:5000")
@app.route("/")
2014-09-03 20:56:10 +02:00
def index():
return None
@app.route("/", subdomain="foo")
2014-09-03 20:56:10 +02:00
def sub():
return None
with app.test_request_context("/"):
assert (
flask.url_for("index", _external=True)
== "http://localhost.localdomain:5000/"
)
with app.test_request_context("/"):
assert (
flask.url_for("sub", _external=True)
== "http://foo.localhost.localdomain:5000/"
)
2014-09-02 05:26:52 +02:00
# suppress Werkzeug 0.15 warning about name mismatch
2022-02-08 12:05:17 -08:00
with warnings.catch_warnings():
warnings.filterwarnings(
"ignore", "Current server name", UserWarning, "flask.app"
)
with app.test_request_context(
"/", environ_overrides={"HTTP_HOST": "localhost"}
):
2014-09-02 05:26:52 +02:00
pass
app.config.update(SERVER_NAME="localhost")
with app.test_request_context("/", environ_overrides={"SERVER_NAME": "localhost"}):
2014-09-03 20:56:10 +02:00
pass
app.config.update(SERVER_NAME="localhost:80")
with app.test_request_context(
"/", environ_overrides={"SERVER_NAME": "localhost:80"}
):
2014-09-03 20:56:10 +02:00
pass
def test_context_binding(app):
@app.route("/")
2014-09-03 20:56:10 +02:00
def index():
2020-04-04 11:39:03 -07:00
return f"Hello {flask.request.args['name']}!"
@app.route("/meh")
2014-09-03 20:56:10 +02:00
def meh():
return flask.request.url
with app.test_request_context("/?name=World"):
assert index() == "Hello World!"
with app.test_request_context("/meh"):
assert meh() == "http://localhost/meh"
2022-07-05 06:33:03 -07:00
assert not flask.request
2014-09-03 20:56:10 +02:00
def test_context_test(app):
2014-09-03 20:56:10 +02:00
assert not flask.request
assert not flask.has_request_context()
ctx = app.test_request_context()
ctx.push()
try:
assert flask.request
assert flask.has_request_context()
finally:
ctx.pop()
2014-09-03 20:56:10 +02:00
def test_manual_context_binding(app):
@app.route("/")
2014-09-03 20:56:10 +02:00
def index():
2020-04-04 11:39:03 -07:00
return f"Hello {flask.request.args['name']}!"
2014-09-03 20:56:10 +02:00
ctx = app.test_request_context("/?name=World")
2014-09-03 20:56:10 +02:00
ctx.push()
assert index() == "Hello World!"
2014-09-03 20:56:10 +02:00
ctx.pop()
with pytest.raises(RuntimeError):
2014-09-03 20:56:10 +02:00
index()
2026-05-01 20:17:23 -07:00
def test_copy_context_thread(
request: pytest.FixtureRequest, app: flask.Flask, client: FlaskClient
) -> None:
executor = futures.ThreadPoolExecutor(max_workers=2)
request.addfinalizer(lambda: executor.shutdown(cancel_futures=True))
result: cabc.Iterator[int] | None = None
@app.route("/")
def index():
flask.session["fizz"] = "buzz"
@flask.copy_current_request_context
def work(n: int) -> int:
assert flask.current_app == app
assert flask.request.path == "/"
assert flask.request.args["foo"] == "bar"
assert flask.session["fizz"] == "buzz"
return n
nonlocal result
result = executor.map(work, range(10))
return "Hello World!"
rv = client.get(query_string={"foo": "bar"})
assert rv.text == "Hello World!"
assert result is not None
assert set(result) == set(range(10))
def test_session_error_pops_context():
class SessionError(Exception):
pass
class FailingSessionInterface(SessionInterface):
def open_session(self, app, request):
raise SessionError()
class CustomFlask(flask.Flask):
session_interface = FailingSessionInterface()
app = CustomFlask(__name__)
@app.route("/")
def index():
# shouldn't get here
2019-05-31 14:53:26 -04:00
AssertionError()
response = app.test_client().get("/")
assert response.status_code == 500
assert not flask.request
assert not flask.current_app
def test_session_dynamic_cookie_name():
# This session interface will use a cookie with a different name if the
# requested url ends with the string "dynamic_cookie"
class PathAwareSessionInterface(SecureCookieSessionInterface):
def get_cookie_name(self, app):
if flask.request.url.endswith("dynamic_cookie"):
return "dynamic_cookie_name"
else:
2020-04-04 09:43:06 -07:00
return super().get_cookie_name(app)
class CustomFlask(flask.Flask):
session_interface = PathAwareSessionInterface()
app = CustomFlask(__name__)
app.secret_key = "secret_key"
@app.route("/set", methods=["POST"])
def set():
flask.session["value"] = flask.request.form["value"]
return "value set"
@app.route("/get")
def get():
v = flask.session.get("value", "None")
return v
@app.route("/set_dynamic_cookie", methods=["POST"])
def set_dynamic_cookie():
flask.session["value"] = flask.request.form["value"]
return "value set"
@app.route("/get_dynamic_cookie")
def get_dynamic_cookie():
v = flask.session.get("value", "None")
return v
test_client = app.test_client()
# first set the cookie in both /set urls but each with a different value
assert test_client.post("/set", data={"value": "42"}).data == b"value set"
assert (
test_client.post("/set_dynamic_cookie", data={"value": "616"}).data
== b"value set"
)
# now check that the relevant values come back - meaning that different
# cookies are being used for the urls that end with "dynamic cookie"
assert test_client.get("/get").data == b"42"
assert test_client.get("/get_dynamic_cookie").data == b"616"