"Fossies" - the Fresh Open Source Software Archive

Member "flask-1.1.2/tests/test_basic.py" (3 Apr 2020, 54249 Bytes) of package /linux/www/flask-1.1.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_basic.py": 1.1.1_vs_1.1.2.

    1 # -*- coding: utf-8 -*-
    2 """
    3     tests.basic
    4     ~~~~~~~~~~~~~~~~~~~~~
    5 
    6     The basic functionality.
    7 
    8     :copyright: 2010 Pallets
    9     :license: BSD-3-Clause
   10 """
   11 import re
   12 import sys
   13 import time
   14 import uuid
   15 from datetime import datetime
   16 from threading import Thread
   17 
   18 import pytest
   19 import werkzeug.serving
   20 from werkzeug.exceptions import BadRequest
   21 from werkzeug.exceptions import Forbidden
   22 from werkzeug.exceptions import NotFound
   23 from werkzeug.http import parse_date
   24 from werkzeug.routing import BuildError
   25 
   26 import flask
   27 from flask._compat import text_type
   28 
   29 
   30 def test_options_work(app, client):
   31     @app.route("/", methods=["GET", "POST"])
   32     def index():
   33         return "Hello World"
   34 
   35     rv = client.open("/", method="OPTIONS")
   36     assert sorted(rv.allow) == ["GET", "HEAD", "OPTIONS", "POST"]
   37     assert rv.data == b""
   38 
   39 
   40 def test_options_on_multiple_rules(app, client):
   41     @app.route("/", methods=["GET", "POST"])
   42     def index():
   43         return "Hello World"
   44 
   45     @app.route("/", methods=["PUT"])
   46     def index_put():
   47         return "Aha!"
   48 
   49     rv = client.open("/", method="OPTIONS")
   50     assert sorted(rv.allow) == ["GET", "HEAD", "OPTIONS", "POST", "PUT"]
   51 
   52 
   53 def test_provide_automatic_options_attr():
   54     app = flask.Flask(__name__)
   55 
   56     def index():
   57         return "Hello World!"
   58 
   59     index.provide_automatic_options = False
   60     app.route("/")(index)
   61     rv = app.test_client().open("/", method="OPTIONS")
   62     assert rv.status_code == 405
   63 
   64     app = flask.Flask(__name__)
   65 
   66     def index2():
   67         return "Hello World!"
   68 
   69     index2.provide_automatic_options = True
   70     app.route("/", methods=["OPTIONS"])(index2)
   71     rv = app.test_client().open("/", method="OPTIONS")
   72     assert sorted(rv.allow) == ["OPTIONS"]
   73 
   74 
   75 def test_provide_automatic_options_kwarg(app, client):
   76     def index():
   77         return flask.request.method
   78 
   79     def more():
   80         return flask.request.method
   81 
   82     app.add_url_rule("/", view_func=index, provide_automatic_options=False)
   83     app.add_url_rule(
   84         "/more",
   85         view_func=more,
   86         methods=["GET", "POST"],
   87         provide_automatic_options=False,
   88     )
   89     assert client.get("/").data == b"GET"
   90 
   91     rv = client.post("/")
   92     assert rv.status_code == 405
   93     assert sorted(rv.allow) == ["GET", "HEAD"]
   94 
   95     # Older versions of Werkzeug.test.Client don't have an options method
   96     if hasattr(client, "options"):
   97         rv = client.options("/")
   98     else:
   99         rv = client.open("/", method="OPTIONS")
  100 
  101     assert rv.status_code == 405
  102 
  103     rv = client.head("/")
  104     assert rv.status_code == 200
  105     assert not rv.data  # head truncates
  106     assert client.post("/more").data == b"POST"
  107     assert client.get("/more").data == b"GET"
  108 
  109     rv = client.delete("/more")
  110     assert rv.status_code == 405
  111     assert sorted(rv.allow) == ["GET", "HEAD", "POST"]
  112 
  113     if hasattr(client, "options"):
  114         rv = client.options("/more")
  115     else:
  116         rv = client.open("/more", method="OPTIONS")
  117 
  118     assert rv.status_code == 405
  119 
  120 
  121 def test_request_dispatching(app, client):
  122     @app.route("/")
  123     def index():
  124         return flask.request.method
  125 
  126     @app.route("/more", methods=["GET", "POST"])
  127     def more():
  128         return flask.request.method
  129 
  130     assert client.get("/").data == b"GET"
  131     rv = client.post("/")
  132     assert rv.status_code == 405
  133     assert sorted(rv.allow) == ["GET", "HEAD", "OPTIONS"]
  134     rv = client.head("/")
  135     assert rv.status_code == 200
  136     assert not rv.data  # head truncates
  137     assert client.post("/more").data == b"POST"
  138     assert client.get("/more").data == b"GET"
  139     rv = client.delete("/more")
  140     assert rv.status_code == 405
  141     assert sorted(rv.allow) == ["GET", "HEAD", "OPTIONS", "POST"]
  142 
  143 
  144 def test_disallow_string_for_allowed_methods(app):
  145     with pytest.raises(TypeError):
  146 
  147         @app.route("/", methods="GET POST")
  148         def index():
  149             return "Hey"
  150 
  151 
  152 def test_url_mapping(app, client):
  153     random_uuid4 = "7eb41166-9ebf-4d26-b771-ea3f54f8b383"
  154 
  155     def index():
  156         return flask.request.method
  157 
  158     def more():
  159         return flask.request.method
  160 
  161     def options():
  162         return random_uuid4
  163 
  164     app.add_url_rule("/", "index", index)
  165     app.add_url_rule("/more", "more", more, methods=["GET", "POST"])
  166 
  167     # Issue 1288: Test that automatic options are not added
  168     #             when non-uppercase 'options' in methods
  169     app.add_url_rule("/options", "options", options, methods=["options"])
  170 
  171     assert client.get("/").data == b"GET"
  172     rv = client.post("/")
  173     assert rv.status_code == 405
  174     assert sorted(rv.allow) == ["GET", "HEAD", "OPTIONS"]
  175     rv = client.head("/")
  176     assert rv.status_code == 200
  177     assert not rv.data  # head truncates
  178     assert client.post("/more").data == b"POST"
  179     assert client.get("/more").data == b"GET"
  180     rv = client.delete("/more")
  181     assert rv.status_code == 405
  182     assert sorted(rv.allow) == ["GET", "HEAD", "OPTIONS", "POST"]
  183     rv = client.open("/options", method="OPTIONS")
  184     assert rv.status_code == 200
  185     assert random_uuid4 in rv.data.decode("utf-8")
  186 
  187 
  188 def test_werkzeug_routing(app, client):
  189     from werkzeug.routing import Submount, Rule
  190 
  191     app.url_map.add(
  192         Submount("/foo", [Rule("/bar", endpoint="bar"), Rule("/", endpoint="index")])
  193     )
  194 
  195     def bar():
  196         return "bar"
  197 
  198     def index():
  199         return "index"
  200 
  201     app.view_functions["bar"] = bar
  202     app.view_functions["index"] = index
  203 
  204     assert client.get("/foo/").data == b"index"
  205     assert client.get("/foo/bar").data == b"bar"
  206 
  207 
  208 def test_endpoint_decorator(app, client):
  209     from werkzeug.routing import Submount, Rule
  210 
  211     app.url_map.add(
  212         Submount("/foo", [Rule("/bar", endpoint="bar"), Rule("/", endpoint="index")])
  213     )
  214 
  215     @app.endpoint("bar")
  216     def bar():
  217         return "bar"
  218 
  219     @app.endpoint("index")
  220     def index():
  221         return "index"
  222 
  223     assert client.get("/foo/").data == b"index"
  224     assert client.get("/foo/bar").data == b"bar"
  225 
  226 
  227 def test_session(app, client):
  228     @app.route("/set", methods=["POST"])
  229     def set():
  230         assert not flask.session.accessed
  231         assert not flask.session.modified
  232         flask.session["value"] = flask.request.form["value"]
  233         assert flask.session.accessed
  234         assert flask.session.modified
  235         return "value set"
  236 
  237     @app.route("/get")
  238     def get():
  239         assert not flask.session.accessed
  240         assert not flask.session.modified
  241         v = flask.session.get("value", "None")
  242         assert flask.session.accessed
  243         assert not flask.session.modified
  244         return v
  245 
  246     assert client.post("/set", data={"value": "42"}).data == b"value set"
  247     assert client.get("/get").data == b"42"
  248 
  249 
  250 def test_session_using_server_name(app, client):
  251     app.config.update(SERVER_NAME="example.com")
  252 
  253     @app.route("/")
  254     def index():
  255         flask.session["testing"] = 42
  256         return "Hello World"
  257 
  258     rv = client.get("/", "http://example.com/")
  259     assert "domain=.example.com" in rv.headers["set-cookie"].lower()
  260     assert "httponly" in rv.headers["set-cookie"].lower()
  261 
  262 
  263 def test_session_using_server_name_and_port(app, client):
  264     app.config.update(SERVER_NAME="example.com:8080")
  265 
  266     @app.route("/")
  267     def index():
  268         flask.session["testing"] = 42
  269         return "Hello World"
  270 
  271     rv = client.get("/", "http://example.com:8080/")
  272     assert "domain=.example.com" in rv.headers["set-cookie"].lower()
  273     assert "httponly" in rv.headers["set-cookie"].lower()
  274 
  275 
  276 def test_session_using_server_name_port_and_path(app, client):
  277     app.config.update(SERVER_NAME="example.com:8080", APPLICATION_ROOT="/foo")
  278 
  279     @app.route("/")
  280     def index():
  281         flask.session["testing"] = 42
  282         return "Hello World"
  283 
  284     rv = client.get("/", "http://example.com:8080/foo")
  285     assert "domain=example.com" in rv.headers["set-cookie"].lower()
  286     assert "path=/foo" in rv.headers["set-cookie"].lower()
  287     assert "httponly" in rv.headers["set-cookie"].lower()
  288 
  289 
  290 def test_session_using_application_root(app, client):
  291     class PrefixPathMiddleware(object):
  292         def __init__(self, app, prefix):
  293             self.app = app
  294             self.prefix = prefix
  295 
  296         def __call__(self, environ, start_response):
  297             environ["SCRIPT_NAME"] = self.prefix
  298             return self.app(environ, start_response)
  299 
  300     app.wsgi_app = PrefixPathMiddleware(app.wsgi_app, "/bar")
  301     app.config.update(APPLICATION_ROOT="/bar")
  302 
  303     @app.route("/")
  304     def index():
  305         flask.session["testing"] = 42
  306         return "Hello World"
  307 
  308     rv = client.get("/", "http://example.com:8080/")
  309     assert "path=/bar" in rv.headers["set-cookie"].lower()
  310 
  311 
  312 def test_session_using_session_settings(app, client):
  313     app.config.update(
  314         SERVER_NAME="www.example.com:8080",
  315         APPLICATION_ROOT="/test",
  316         SESSION_COOKIE_DOMAIN=".example.com",
  317         SESSION_COOKIE_HTTPONLY=False,
  318         SESSION_COOKIE_SECURE=True,
  319         SESSION_COOKIE_SAMESITE="Lax",
  320         SESSION_COOKIE_PATH="/",
  321     )
  322 
  323     @app.route("/")
  324     def index():
  325         flask.session["testing"] = 42
  326         return "Hello World"
  327 
  328     rv = client.get("/", "http://www.example.com:8080/test/")
  329     cookie = rv.headers["set-cookie"].lower()
  330     assert "domain=.example.com" in cookie
  331     assert "path=/" in cookie
  332     assert "secure" in cookie
  333     assert "httponly" not in cookie
  334     assert "samesite" in cookie
  335 
  336 
  337 def test_session_using_samesite_attribute(app, client):
  338     @app.route("/")
  339     def index():
  340         flask.session["testing"] = 42
  341         return "Hello World"
  342 
  343     app.config.update(SESSION_COOKIE_SAMESITE="invalid")
  344 
  345     with pytest.raises(ValueError):
  346         client.get("/")
  347 
  348     app.config.update(SESSION_COOKIE_SAMESITE=None)
  349     rv = client.get("/")
  350     cookie = rv.headers["set-cookie"].lower()
  351     assert "samesite" not in cookie
  352 
  353     app.config.update(SESSION_COOKIE_SAMESITE="Strict")
  354     rv = client.get("/")
  355     cookie = rv.headers["set-cookie"].lower()
  356     assert "samesite=strict" in cookie
  357 
  358     app.config.update(SESSION_COOKIE_SAMESITE="Lax")
  359     rv = client.get("/")
  360     cookie = rv.headers["set-cookie"].lower()
  361     assert "samesite=lax" in cookie
  362 
  363 
  364 def test_session_localhost_warning(recwarn, app, client):
  365     app.config.update(SERVER_NAME="localhost:5000")
  366 
  367     @app.route("/")
  368     def index():
  369         flask.session["testing"] = 42
  370         return "testing"
  371 
  372     rv = client.get("/", "http://localhost:5000/")
  373     assert "domain" not in rv.headers["set-cookie"].lower()
  374     w = recwarn.pop(UserWarning)
  375     assert '"localhost" is not a valid cookie domain' in str(w.message)
  376 
  377 
  378 def test_session_ip_warning(recwarn, app, client):
  379     app.config.update(SERVER_NAME="127.0.0.1:5000")
  380 
  381     @app.route("/")
  382     def index():
  383         flask.session["testing"] = 42
  384         return "testing"
  385 
  386     rv = client.get("/", "http://127.0.0.1:5000/")
  387     assert "domain=127.0.0.1" in rv.headers["set-cookie"].lower()
  388     w = recwarn.pop(UserWarning)
  389     assert "cookie domain is an IP" in str(w.message)
  390 
  391 
  392 def test_missing_session(app):
  393     app.secret_key = None
  394 
  395     def expect_exception(f, *args, **kwargs):
  396         e = pytest.raises(RuntimeError, f, *args, **kwargs)
  397         assert e.value.args and "session is unavailable" in e.value.args[0]
  398 
  399     with app.test_request_context():
  400         assert flask.session.get("missing_key") is None
  401         expect_exception(flask.session.__setitem__, "foo", 42)
  402         expect_exception(flask.session.pop, "foo")
  403 
  404 
  405 def test_session_expiration(app, client):
  406     permanent = True
  407 
  408     @app.route("/")
  409     def index():
  410         flask.session["test"] = 42
  411         flask.session.permanent = permanent
  412         return ""
  413 
  414     @app.route("/test")
  415     def test():
  416         return text_type(flask.session.permanent)
  417 
  418     rv = client.get("/")
  419     assert "set-cookie" in rv.headers
  420     match = re.search(r"(?i)\bexpires=([^;]+)", rv.headers["set-cookie"])
  421     expires = parse_date(match.group())
  422     expected = datetime.utcnow() + app.permanent_session_lifetime
  423     assert expires.year == expected.year
  424     assert expires.month == expected.month
  425     assert expires.day == expected.day
  426 
  427     rv = client.get("/test")
  428     assert rv.data == b"True"
  429 
  430     permanent = False
  431     rv = client.get("/")
  432     assert "set-cookie" in rv.headers
  433     match = re.search(r"\bexpires=([^;]+)", rv.headers["set-cookie"])
  434     assert match is None
  435 
  436 
  437 def test_session_stored_last(app, client):
  438     @app.after_request
  439     def modify_session(response):
  440         flask.session["foo"] = 42
  441         return response
  442 
  443     @app.route("/")
  444     def dump_session_contents():
  445         return repr(flask.session.get("foo"))
  446 
  447     assert client.get("/").data == b"None"
  448     assert client.get("/").data == b"42"
  449 
  450 
  451 def test_session_special_types(app, client):
  452     now = datetime.utcnow().replace(microsecond=0)
  453     the_uuid = uuid.uuid4()
  454 
  455     @app.route("/")
  456     def dump_session_contents():
  457         flask.session["t"] = (1, 2, 3)
  458         flask.session["b"] = b"\xff"
  459         flask.session["m"] = flask.Markup("<html>")
  460         flask.session["u"] = the_uuid
  461         flask.session["d"] = now
  462         flask.session["t_tag"] = {" t": "not-a-tuple"}
  463         flask.session["di_t_tag"] = {" t__": "not-a-tuple"}
  464         flask.session["di_tag"] = {" di": "not-a-dict"}
  465         return "", 204
  466 
  467     with client:
  468         client.get("/")
  469         s = flask.session
  470         assert s["t"] == (1, 2, 3)
  471         assert type(s["b"]) == bytes
  472         assert s["b"] == b"\xff"
  473         assert type(s["m"]) == flask.Markup
  474         assert s["m"] == flask.Markup("<html>")
  475         assert s["u"] == the_uuid
  476         assert s["d"] == now
  477         assert s["t_tag"] == {" t": "not-a-tuple"}
  478         assert s["di_t_tag"] == {" t__": "not-a-tuple"}
  479         assert s["di_tag"] == {" di": "not-a-dict"}
  480 
  481 
  482 def test_session_cookie_setting(app):
  483     is_permanent = True
  484 
  485     @app.route("/bump")
  486     def bump():
  487         rv = flask.session["foo"] = flask.session.get("foo", 0) + 1
  488         flask.session.permanent = is_permanent
  489         return str(rv)
  490 
  491     @app.route("/read")
  492     def read():
  493         return str(flask.session.get("foo", 0))
  494 
  495     def run_test(expect_header):
  496         with app.test_client() as c:
  497             assert c.get("/bump").data == b"1"
  498             assert c.get("/bump").data == b"2"
  499             assert c.get("/bump").data == b"3"
  500 
  501             rv = c.get("/read")
  502             set_cookie = rv.headers.get("set-cookie")
  503             assert (set_cookie is not None) == expect_header
  504             assert rv.data == b"3"
  505 
  506     is_permanent = True
  507     app.config["SESSION_REFRESH_EACH_REQUEST"] = True
  508     run_test(expect_header=True)
  509 
  510     is_permanent = True
  511     app.config["SESSION_REFRESH_EACH_REQUEST"] = False
  512     run_test(expect_header=False)
  513 
  514     is_permanent = False
  515     app.config["SESSION_REFRESH_EACH_REQUEST"] = True
  516     run_test(expect_header=False)
  517 
  518     is_permanent = False
  519     app.config["SESSION_REFRESH_EACH_REQUEST"] = False
  520     run_test(expect_header=False)
  521 
  522 
  523 def test_session_vary_cookie(app, client):
  524     @app.route("/set")
  525     def set_session():
  526         flask.session["test"] = "test"
  527         return ""
  528 
  529     @app.route("/get")
  530     def get():
  531         return flask.session.get("test")
  532 
  533     @app.route("/getitem")
  534     def getitem():
  535         return flask.session["test"]
  536 
  537     @app.route("/setdefault")
  538     def setdefault():
  539         return flask.session.setdefault("test", "default")
  540 
  541     @app.route("/vary-cookie-header-set")
  542     def vary_cookie_header_set():
  543         response = flask.Response()
  544         response.vary.add("Cookie")
  545         flask.session["test"] = "test"
  546         return response
  547 
  548     @app.route("/vary-header-set")
  549     def vary_header_set():
  550         response = flask.Response()
  551         response.vary.update(("Accept-Encoding", "Accept-Language"))
  552         flask.session["test"] = "test"
  553         return response
  554 
  555     @app.route("/no-vary-header")
  556     def no_vary_header():
  557         return ""
  558 
  559     def expect(path, header_value="Cookie"):
  560         rv = client.get(path)
  561 
  562         if header_value:
  563             # The 'Vary' key should exist in the headers only once.
  564             assert len(rv.headers.get_all("Vary")) == 1
  565             assert rv.headers["Vary"] == header_value
  566         else:
  567             assert "Vary" not in rv.headers
  568 
  569     expect("/set")
  570     expect("/get")
  571     expect("/getitem")
  572     expect("/setdefault")
  573     expect("/vary-cookie-header-set")
  574     expect("/vary-header-set", "Accept-Encoding, Accept-Language, Cookie")
  575     expect("/no-vary-header", None)
  576 
  577 
  578 def test_flashes(app, req_ctx):
  579     assert not flask.session.modified
  580     flask.flash("Zap")
  581     flask.session.modified = False
  582     flask.flash("Zip")
  583     assert flask.session.modified
  584     assert list(flask.get_flashed_messages()) == ["Zap", "Zip"]
  585 
  586 
  587 def test_extended_flashing(app):
  588     # Be sure app.testing=True below, else tests can fail silently.
  589     #
  590     # Specifically, if app.testing is not set to True, the AssertionErrors
  591     # in the view functions will cause a 500 response to the test client
  592     # instead of propagating exceptions.
  593 
  594     @app.route("/")
  595     def index():
  596         flask.flash(u"Hello World")
  597         flask.flash(u"Hello World", "error")
  598         flask.flash(flask.Markup(u"<em>Testing</em>"), "warning")
  599         return ""
  600 
  601     @app.route("/test/")
  602     def test():
  603         messages = flask.get_flashed_messages()
  604         assert list(messages) == [
  605             u"Hello World",
  606             u"Hello World",
  607             flask.Markup(u"<em>Testing</em>"),
  608         ]
  609         return ""
  610 
  611     @app.route("/test_with_categories/")
  612     def test_with_categories():
  613         messages = flask.get_flashed_messages(with_categories=True)
  614         assert len(messages) == 3
  615         assert list(messages) == [
  616             ("message", u"Hello World"),
  617             ("error", u"Hello World"),
  618             ("warning", flask.Markup(u"<em>Testing</em>")),
  619         ]
  620         return ""
  621 
  622     @app.route("/test_filter/")
  623     def test_filter():
  624         messages = flask.get_flashed_messages(
  625             category_filter=["message"], with_categories=True
  626         )
  627         assert list(messages) == [("message", u"Hello World")]
  628         return ""
  629 
  630     @app.route("/test_filters/")
  631     def test_filters():
  632         messages = flask.get_flashed_messages(
  633             category_filter=["message", "warning"], with_categories=True
  634         )
  635         assert list(messages) == [
  636             ("message", u"Hello World"),
  637             ("warning", flask.Markup(u"<em>Testing</em>")),
  638         ]
  639         return ""
  640 
  641     @app.route("/test_filters_without_returning_categories/")
  642     def test_filters2():
  643         messages = flask.get_flashed_messages(category_filter=["message", "warning"])
  644         assert len(messages) == 2
  645         assert messages[0] == u"Hello World"
  646         assert messages[1] == flask.Markup(u"<em>Testing</em>")
  647         return ""
  648 
  649     # Create new test client on each test to clean flashed messages.
  650 
  651     client = app.test_client()
  652     client.get("/")
  653     client.get("/test_with_categories/")
  654 
  655     client = app.test_client()
  656     client.get("/")
  657     client.get("/test_filter/")
  658 
  659     client = app.test_client()
  660     client.get("/")
  661     client.get("/test_filters/")
  662 
  663     client = app.test_client()
  664     client.get("/")
  665     client.get("/test_filters_without_returning_categories/")
  666 
  667 
  668 def test_request_processing(app, client):
  669     evts = []
  670 
  671     @app.before_request
  672     def before_request():
  673         evts.append("before")
  674 
  675     @app.after_request
  676     def after_request(response):
  677         response.data += b"|after"
  678         evts.append("after")
  679         return response
  680 
  681     @app.route("/")
  682     def index():
  683         assert "before" in evts
  684         assert "after" not in evts
  685         return "request"
  686 
  687     assert "after" not in evts
  688     rv = client.get("/").data
  689     assert "after" in evts
  690     assert rv == b"request|after"
  691 
  692 
  693 def test_request_preprocessing_early_return(app, client):
  694     evts = []
  695 
  696     @app.before_request
  697     def before_request1():
  698         evts.append(1)
  699 
  700     @app.before_request
  701     def before_request2():
  702         evts.append(2)
  703         return "hello"
  704 
  705     @app.before_request
  706     def before_request3():
  707         evts.append(3)
  708         return "bye"
  709 
  710     @app.route("/")
  711     def index():
  712         evts.append("index")
  713         return "damnit"
  714 
  715     rv = client.get("/").data.strip()
  716     assert rv == b"hello"
  717     assert evts == [1, 2]
  718 
  719 
  720 def test_after_request_processing(app, client):
  721     @app.route("/")
  722     def index():
  723         @flask.after_this_request
  724         def foo(response):
  725             response.headers["X-Foo"] = "a header"
  726             return response
  727 
  728         return "Test"
  729 
  730     resp = client.get("/")
  731     assert resp.status_code == 200
  732     assert resp.headers["X-Foo"] == "a header"
  733 
  734 
  735 def test_teardown_request_handler(app, client):
  736     called = []
  737 
  738     @app.teardown_request
  739     def teardown_request(exc):
  740         called.append(True)
  741         return "Ignored"
  742 
  743     @app.route("/")
  744     def root():
  745         return "Response"
  746 
  747     rv = client.get("/")
  748     assert rv.status_code == 200
  749     assert b"Response" in rv.data
  750     assert len(called) == 1
  751 
  752 
  753 def test_teardown_request_handler_debug_mode(app, client):
  754     called = []
  755 
  756     @app.teardown_request
  757     def teardown_request(exc):
  758         called.append(True)
  759         return "Ignored"
  760 
  761     @app.route("/")
  762     def root():
  763         return "Response"
  764 
  765     rv = client.get("/")
  766     assert rv.status_code == 200
  767     assert b"Response" in rv.data
  768     assert len(called) == 1
  769 
  770 
  771 def test_teardown_request_handler_error(app, client):
  772     called = []
  773     app.testing = False
  774 
  775     @app.teardown_request
  776     def teardown_request1(exc):
  777         assert type(exc) == ZeroDivisionError
  778         called.append(True)
  779         # This raises a new error and blows away sys.exc_info(), so we can
  780         # test that all teardown_requests get passed the same original
  781         # exception.
  782         try:
  783             raise TypeError()
  784         except Exception:
  785             pass
  786 
  787     @app.teardown_request
  788     def teardown_request2(exc):
  789         assert type(exc) == ZeroDivisionError
  790         called.append(True)
  791         # This raises a new error and blows away sys.exc_info(), so we can
  792         # test that all teardown_requests get passed the same original
  793         # exception.
  794         try:
  795             raise TypeError()
  796         except Exception:
  797             pass
  798 
  799     @app.route("/")
  800     def fails():
  801         1 // 0
  802 
  803     rv = client.get("/")
  804     assert rv.status_code == 500
  805     assert b"Internal Server Error" in rv.data
  806     assert len(called) == 2
  807 
  808 
  809 def test_before_after_request_order(app, client):
  810     called = []
  811 
  812     @app.before_request
  813     def before1():
  814         called.append(1)
  815 
  816     @app.before_request
  817     def before2():
  818         called.append(2)
  819 
  820     @app.after_request
  821     def after1(response):
  822         called.append(4)
  823         return response
  824 
  825     @app.after_request
  826     def after2(response):
  827         called.append(3)
  828         return response
  829 
  830     @app.teardown_request
  831     def finish1(exc):
  832         called.append(6)
  833 
  834     @app.teardown_request
  835     def finish2(exc):
  836         called.append(5)
  837 
  838     @app.route("/")
  839     def index():
  840         return "42"
  841 
  842     rv = client.get("/")
  843     assert rv.data == b"42"
  844     assert called == [1, 2, 3, 4, 5, 6]
  845 
  846 
  847 def test_error_handling(app, client):
  848     app.testing = False
  849 
  850     @app.errorhandler(404)
  851     def not_found(e):
  852         return "not found", 404
  853 
  854     @app.errorhandler(500)
  855     def internal_server_error(e):
  856         return "internal server error", 500
  857 
  858     @app.errorhandler(Forbidden)
  859     def forbidden(e):
  860         return "forbidden", 403
  861 
  862     @app.route("/")
  863     def index():
  864         flask.abort(404)
  865 
  866     @app.route("/error")
  867     def error():
  868         1 // 0
  869 
  870     @app.route("/forbidden")
  871     def error2():
  872         flask.abort(403)
  873 
  874     rv = client.get("/")
  875     assert rv.status_code == 404
  876     assert rv.data == b"not found"
  877     rv = client.get("/error")
  878     assert rv.status_code == 500
  879     assert b"internal server error" == rv.data
  880     rv = client.get("/forbidden")
  881     assert rv.status_code == 403
  882     assert b"forbidden" == rv.data
  883 
  884 
  885 def test_error_handler_unknown_code(app):
  886     with pytest.raises(KeyError) as exc_info:
  887         app.register_error_handler(999, lambda e: ("999", 999))
  888 
  889     assert "Use a subclass" in exc_info.value.args[0]
  890 
  891 
  892 def test_error_handling_processing(app, client):
  893     app.testing = False
  894 
  895     @app.errorhandler(500)
  896     def internal_server_error(e):
  897         return "internal server error", 500
  898 
  899     @app.route("/")
  900     def broken_func():
  901         1 // 0
  902 
  903     @app.after_request
  904     def after_request(resp):
  905         resp.mimetype = "text/x-special"
  906         return resp
  907 
  908     resp = client.get("/")
  909     assert resp.mimetype == "text/x-special"
  910     assert resp.data == b"internal server error"
  911 
  912 
  913 def test_baseexception_error_handling(app, client):
  914     app.testing = False
  915 
  916     @app.route("/")
  917     def broken_func():
  918         raise KeyboardInterrupt()
  919 
  920     with pytest.raises(KeyboardInterrupt):
  921         client.get("/")
  922 
  923         ctx = flask._request_ctx_stack.top
  924         assert ctx.preserved
  925         assert type(ctx._preserved_exc) is KeyboardInterrupt
  926 
  927 
  928 def test_before_request_and_routing_errors(app, client):
  929     @app.before_request
  930     def attach_something():
  931         flask.g.something = "value"
  932 
  933     @app.errorhandler(404)
  934     def return_something(error):
  935         return flask.g.something, 404
  936 
  937     rv = client.get("/")
  938     assert rv.status_code == 404
  939     assert rv.data == b"value"
  940 
  941 
  942 def test_user_error_handling(app, client):
  943     class MyException(Exception):
  944         pass
  945 
  946     @app.errorhandler(MyException)
  947     def handle_my_exception(e):
  948         assert isinstance(e, MyException)
  949         return "42"
  950 
  951     @app.route("/")
  952     def index():
  953         raise MyException()
  954 
  955     assert client.get("/").data == b"42"
  956 
  957 
  958 def test_http_error_subclass_handling(app, client):
  959     class ForbiddenSubclass(Forbidden):
  960         pass
  961 
  962     @app.errorhandler(ForbiddenSubclass)
  963     def handle_forbidden_subclass(e):
  964         assert isinstance(e, ForbiddenSubclass)
  965         return "banana"
  966 
  967     @app.errorhandler(403)
  968     def handle_403(e):
  969         assert not isinstance(e, ForbiddenSubclass)
  970         assert isinstance(e, Forbidden)
  971         return "apple"
  972 
  973     @app.route("/1")
  974     def index1():
  975         raise ForbiddenSubclass()
  976 
  977     @app.route("/2")
  978     def index2():
  979         flask.abort(403)
  980 
  981     @app.route("/3")
  982     def index3():
  983         raise Forbidden()
  984 
  985     assert client.get("/1").data == b"banana"
  986     assert client.get("/2").data == b"apple"
  987     assert client.get("/3").data == b"apple"
  988 
  989 
  990 def test_errorhandler_precedence(app, client):
  991     class E1(Exception):
  992         pass
  993 
  994     class E2(Exception):
  995         pass
  996 
  997     class E3(E1, E2):
  998         pass
  999 
 1000     @app.errorhandler(E2)
 1001     def handle_e2(e):
 1002         return "E2"
 1003 
 1004     @app.errorhandler(Exception)
 1005     def handle_exception(e):
 1006         return "Exception"
 1007 
 1008     @app.route("/E1")
 1009     def raise_e1():
 1010         raise E1
 1011 
 1012     @app.route("/E3")
 1013     def raise_e3():
 1014         raise E3
 1015 
 1016     rv = client.get("/E1")
 1017     assert rv.data == b"Exception"
 1018 
 1019     rv = client.get("/E3")
 1020     assert rv.data == b"E2"
 1021 
 1022 
 1023 def test_trapping_of_bad_request_key_errors(app, client):
 1024     @app.route("/key")
 1025     def fail():
 1026         flask.request.form["missing_key"]
 1027 
 1028     @app.route("/abort")
 1029     def allow_abort():
 1030         flask.abort(400)
 1031 
 1032     rv = client.get("/key")
 1033     assert rv.status_code == 400
 1034     assert b"missing_key" not in rv.data
 1035     rv = client.get("/abort")
 1036     assert rv.status_code == 400
 1037 
 1038     app.debug = True
 1039     with pytest.raises(KeyError) as e:
 1040         client.get("/key")
 1041     assert e.errisinstance(BadRequest)
 1042     assert "missing_key" in e.value.get_description()
 1043     rv = client.get("/abort")
 1044     assert rv.status_code == 400
 1045 
 1046     app.debug = False
 1047     app.config["TRAP_BAD_REQUEST_ERRORS"] = True
 1048     with pytest.raises(KeyError):
 1049         client.get("/key")
 1050     with pytest.raises(BadRequest):
 1051         client.get("/abort")
 1052 
 1053 
 1054 def test_trapping_of_all_http_exceptions(app, client):
 1055     app.config["TRAP_HTTP_EXCEPTIONS"] = True
 1056 
 1057     @app.route("/fail")
 1058     def fail():
 1059         flask.abort(404)
 1060 
 1061     with pytest.raises(NotFound):
 1062         client.get("/fail")
 1063 
 1064 
 1065 def test_error_handler_after_processor_error(app, client):
 1066     app.testing = False
 1067 
 1068     @app.before_request
 1069     def before_request():
 1070         if _trigger == "before":
 1071             1 // 0
 1072 
 1073     @app.after_request
 1074     def after_request(response):
 1075         if _trigger == "after":
 1076             1 // 0
 1077         return response
 1078 
 1079     @app.route("/")
 1080     def index():
 1081         return "Foo"
 1082 
 1083     @app.errorhandler(500)
 1084     def internal_server_error(e):
 1085         return "Hello Server Error", 500
 1086 
 1087     for _trigger in "before", "after":
 1088         rv = client.get("/")
 1089         assert rv.status_code == 500
 1090         assert rv.data == b"Hello Server Error"
 1091 
 1092 
 1093 def test_enctype_debug_helper(app, client):
 1094     from flask.debughelpers import DebugFilesKeyError
 1095 
 1096     app.debug = True
 1097 
 1098     @app.route("/fail", methods=["POST"])
 1099     def index():
 1100         return flask.request.files["foo"].filename
 1101 
 1102     # with statement is important because we leave an exception on the
 1103     # stack otherwise and we want to ensure that this is not the case
 1104     # to not negatively affect other tests.
 1105     with client:
 1106         with pytest.raises(DebugFilesKeyError) as e:
 1107             client.post("/fail", data={"foo": "index.txt"})
 1108         assert "no file contents were transmitted" in str(e.value)
 1109         assert 'This was submitted: "index.txt"' in str(e.value)
 1110 
 1111 
 1112 def test_response_types(app, client):
 1113     @app.route("/text")
 1114     def from_text():
 1115         return u"Hällo Wörld"
 1116 
 1117     @app.route("/bytes")
 1118     def from_bytes():
 1119         return u"Hällo Wörld".encode("utf-8")
 1120 
 1121     @app.route("/full_tuple")
 1122     def from_full_tuple():
 1123         return (
 1124             "Meh",
 1125             400,
 1126             {"X-Foo": "Testing", "Content-Type": "text/plain; charset=utf-8"},
 1127         )
 1128 
 1129     @app.route("/text_headers")
 1130     def from_text_headers():
 1131         return "Hello", {"X-Foo": "Test", "Content-Type": "text/plain; charset=utf-8"}
 1132 
 1133     @app.route("/text_status")
 1134     def from_text_status():
 1135         return "Hi, status!", 400
 1136 
 1137     @app.route("/response_headers")
 1138     def from_response_headers():
 1139         return (
 1140             flask.Response("Hello world", 404, {"X-Foo": "Baz"}),
 1141             {"X-Foo": "Bar", "X-Bar": "Foo"},
 1142         )
 1143 
 1144     @app.route("/response_status")
 1145     def from_response_status():
 1146         return app.response_class("Hello world", 400), 500
 1147 
 1148     @app.route("/wsgi")
 1149     def from_wsgi():
 1150         return NotFound()
 1151 
 1152     @app.route("/dict")
 1153     def from_dict():
 1154         return {"foo": "bar"}, 201
 1155 
 1156     assert client.get("/text").data == u"Hällo Wörld".encode("utf-8")
 1157     assert client.get("/bytes").data == u"Hällo Wörld".encode("utf-8")
 1158 
 1159     rv = client.get("/full_tuple")
 1160     assert rv.data == b"Meh"
 1161     assert rv.headers["X-Foo"] == "Testing"
 1162     assert rv.status_code == 400
 1163     assert rv.mimetype == "text/plain"
 1164 
 1165     rv = client.get("/text_headers")
 1166     assert rv.data == b"Hello"
 1167     assert rv.headers["X-Foo"] == "Test"
 1168     assert rv.status_code == 200
 1169     assert rv.mimetype == "text/plain"
 1170 
 1171     rv = client.get("/text_status")
 1172     assert rv.data == b"Hi, status!"
 1173     assert rv.status_code == 400
 1174     assert rv.mimetype == "text/html"
 1175 
 1176     rv = client.get("/response_headers")
 1177     assert rv.data == b"Hello world"
 1178     assert rv.headers.getlist("X-Foo") == ["Baz", "Bar"]
 1179     assert rv.headers["X-Bar"] == "Foo"
 1180     assert rv.status_code == 404
 1181 
 1182     rv = client.get("/response_status")
 1183     assert rv.data == b"Hello world"
 1184     assert rv.status_code == 500
 1185 
 1186     rv = client.get("/wsgi")
 1187     assert b"Not Found" in rv.data
 1188     assert rv.status_code == 404
 1189 
 1190     rv = client.get("/dict")
 1191     assert rv.json == {"foo": "bar"}
 1192     assert rv.status_code == 201
 1193 
 1194 
 1195 def test_response_type_errors():
 1196     app = flask.Flask(__name__)
 1197     app.testing = True
 1198 
 1199     @app.route("/none")
 1200     def from_none():
 1201         pass
 1202 
 1203     @app.route("/small_tuple")
 1204     def from_small_tuple():
 1205         return ("Hello",)
 1206 
 1207     @app.route("/large_tuple")
 1208     def from_large_tuple():
 1209         return "Hello", 234, {"X-Foo": "Bar"}, "???"
 1210 
 1211     @app.route("/bad_type")
 1212     def from_bad_type():
 1213         return True
 1214 
 1215     @app.route("/bad_wsgi")
 1216     def from_bad_wsgi():
 1217         return lambda: None
 1218 
 1219     c = app.test_client()
 1220 
 1221     with pytest.raises(TypeError) as e:
 1222         c.get("/none")
 1223         assert "returned None" in str(e.value)
 1224 
 1225     with pytest.raises(TypeError) as e:
 1226         c.get("/small_tuple")
 1227         assert "tuple must have the form" in str(e.value)
 1228 
 1229     pytest.raises(TypeError, c.get, "/large_tuple")
 1230 
 1231     with pytest.raises(TypeError) as e:
 1232         c.get("/bad_type")
 1233         assert "it was a bool" in str(e.value)
 1234 
 1235     pytest.raises(TypeError, c.get, "/bad_wsgi")
 1236 
 1237 
 1238 def test_make_response(app, req_ctx):
 1239     rv = flask.make_response()
 1240     assert rv.status_code == 200
 1241     assert rv.data == b""
 1242     assert rv.mimetype == "text/html"
 1243 
 1244     rv = flask.make_response("Awesome")
 1245     assert rv.status_code == 200
 1246     assert rv.data == b"Awesome"
 1247     assert rv.mimetype == "text/html"
 1248 
 1249     rv = flask.make_response("W00t", 404)
 1250     assert rv.status_code == 404
 1251     assert rv.data == b"W00t"
 1252     assert rv.mimetype == "text/html"
 1253 
 1254 
 1255 def test_make_response_with_response_instance(app, req_ctx):
 1256     rv = flask.make_response(flask.jsonify({"msg": "W00t"}), 400)
 1257     assert rv.status_code == 400
 1258     assert rv.data == b'{"msg":"W00t"}\n'
 1259     assert rv.mimetype == "application/json"
 1260 
 1261     rv = flask.make_response(flask.Response(""), 400)
 1262     assert rv.status_code == 400
 1263     assert rv.data == b""
 1264     assert rv.mimetype == "text/html"
 1265 
 1266     rv = flask.make_response(
 1267         flask.Response("", headers={"Content-Type": "text/html"}),
 1268         400,
 1269         [("X-Foo", "bar")],
 1270     )
 1271     assert rv.status_code == 400
 1272     assert rv.headers["Content-Type"] == "text/html"
 1273     assert rv.headers["X-Foo"] == "bar"
 1274 
 1275 
 1276 def test_jsonify_no_prettyprint(app, req_ctx):
 1277     app.config.update({"JSONIFY_PRETTYPRINT_REGULAR": False})
 1278     compressed_msg = b'{"msg":{"submsg":"W00t"},"msg2":"foobar"}\n'
 1279     uncompressed_msg = {"msg": {"submsg": "W00t"}, "msg2": "foobar"}
 1280 
 1281     rv = flask.make_response(flask.jsonify(uncompressed_msg), 200)
 1282     assert rv.data == compressed_msg
 1283 
 1284 
 1285 def test_jsonify_prettyprint(app, req_ctx):
 1286     app.config.update({"JSONIFY_PRETTYPRINT_REGULAR": True})
 1287     compressed_msg = {"msg": {"submsg": "W00t"}, "msg2": "foobar"}
 1288     pretty_response = (
 1289         b'{\n  "msg": {\n    "submsg": "W00t"\n  }, \n  "msg2": "foobar"\n}\n'
 1290     )
 1291 
 1292     rv = flask.make_response(flask.jsonify(compressed_msg), 200)
 1293     assert rv.data == pretty_response
 1294 
 1295 
 1296 def test_jsonify_mimetype(app, req_ctx):
 1297     app.config.update({"JSONIFY_MIMETYPE": "application/vnd.api+json"})
 1298     msg = {"msg": {"submsg": "W00t"}}
 1299     rv = flask.make_response(flask.jsonify(msg), 200)
 1300     assert rv.mimetype == "application/vnd.api+json"
 1301 
 1302 
 1303 @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires Python >= 3.7")
 1304 def test_json_dump_dataclass(app, req_ctx):
 1305     from dataclasses import make_dataclass
 1306 
 1307     Data = make_dataclass("Data", [("name", str)])
 1308     value = flask.json.dumps(Data("Flask"), app=app)
 1309     value = flask.json.loads(value, app=app)
 1310     assert value == {"name": "Flask"}
 1311 
 1312 
 1313 def test_jsonify_args_and_kwargs_check(app, req_ctx):
 1314     with pytest.raises(TypeError) as e:
 1315         flask.jsonify("fake args", kwargs="fake")
 1316     assert "behavior undefined" in str(e.value)
 1317 
 1318 
 1319 def test_url_generation(app, req_ctx):
 1320     @app.route("/hello/<name>", methods=["POST"])
 1321     def hello():
 1322         pass
 1323 
 1324     assert flask.url_for("hello", name="test x") == "/hello/test%20x"
 1325     assert (
 1326         flask.url_for("hello", name="test x", _external=True)
 1327         == "http://localhost/hello/test%20x"
 1328     )
 1329 
 1330 
 1331 def test_build_error_handler(app):
 1332     # Test base case, a URL which results in a BuildError.
 1333     with app.test_request_context():
 1334         pytest.raises(BuildError, flask.url_for, "spam")
 1335 
 1336     # Verify the error is re-raised if not the current exception.
 1337     try:
 1338         with app.test_request_context():
 1339             flask.url_for("spam")
 1340     except BuildError as err:
 1341         error = err
 1342     try:
 1343         raise RuntimeError("Test case where BuildError is not current.")
 1344     except RuntimeError:
 1345         pytest.raises(BuildError, app.handle_url_build_error, error, "spam", {})
 1346 
 1347     # Test a custom handler.
 1348     def handler(error, endpoint, values):
 1349         # Just a test.
 1350         return "/test_handler/"
 1351 
 1352     app.url_build_error_handlers.append(handler)
 1353     with app.test_request_context():
 1354         assert flask.url_for("spam") == "/test_handler/"
 1355 
 1356 
 1357 def test_build_error_handler_reraise(app):
 1358     # Test a custom handler which reraises the BuildError
 1359     def handler_raises_build_error(error, endpoint, values):
 1360         raise error
 1361 
 1362     app.url_build_error_handlers.append(handler_raises_build_error)
 1363 
 1364     with app.test_request_context():
 1365         pytest.raises(BuildError, flask.url_for, "not.existing")
 1366 
 1367 
 1368 def test_url_for_passes_special_values_to_build_error_handler(app):
 1369     @app.url_build_error_handlers.append
 1370     def handler(error, endpoint, values):
 1371         assert values == {
 1372             "_external": False,
 1373             "_anchor": None,
 1374             "_method": None,
 1375             "_scheme": None,
 1376         }
 1377         return "handled"
 1378 
 1379     with app.test_request_context():
 1380         flask.url_for("/")
 1381 
 1382 
 1383 def test_static_files(app, client):
 1384     rv = client.get("/static/index.html")
 1385     assert rv.status_code == 200
 1386     assert rv.data.strip() == b"<h1>Hello World!</h1>"
 1387     with app.test_request_context():
 1388         assert flask.url_for("static", filename="index.html") == "/static/index.html"
 1389     rv.close()
 1390 
 1391 
 1392 def test_static_url_path():
 1393     app = flask.Flask(__name__, static_url_path="/foo")
 1394     app.testing = True
 1395     rv = app.test_client().get("/foo/index.html")
 1396     assert rv.status_code == 200
 1397     rv.close()
 1398 
 1399     with app.test_request_context():
 1400         assert flask.url_for("static", filename="index.html") == "/foo/index.html"
 1401 
 1402 
 1403 def test_static_url_path_with_ending_slash():
 1404     app = flask.Flask(__name__, static_url_path="/foo/")
 1405     app.testing = True
 1406     rv = app.test_client().get("/foo/index.html")
 1407     assert rv.status_code == 200
 1408     rv.close()
 1409 
 1410     with app.test_request_context():
 1411         assert flask.url_for("static", filename="index.html") == "/foo/index.html"
 1412 
 1413 
 1414 def test_static_url_empty_path(app):
 1415     app = flask.Flask(__name__, static_folder="", static_url_path="")
 1416     rv = app.test_client().open("/static/index.html", method="GET")
 1417     assert rv.status_code == 200
 1418     rv.close()
 1419 
 1420 
 1421 def test_static_url_empty_path_default(app):
 1422     app = flask.Flask(__name__, static_folder="")
 1423     rv = app.test_client().open("/static/index.html", method="GET")
 1424     assert rv.status_code == 200
 1425     rv.close()
 1426 
 1427 
 1428 def test_static_folder_with_ending_slash():
 1429     app = flask.Flask(__name__, static_folder="static/")
 1430 
 1431     @app.route("/<path:path>")
 1432     def catch_all(path):
 1433         return path
 1434 
 1435     rv = app.test_client().get("/catch/all")
 1436     assert rv.data == b"catch/all"
 1437 
 1438 
 1439 def test_static_route_with_host_matching():
 1440     app = flask.Flask(__name__, host_matching=True, static_host="example.com")
 1441     c = app.test_client()
 1442     rv = c.get("http://example.com/static/index.html")
 1443     assert rv.status_code == 200
 1444     rv.close()
 1445     with app.test_request_context():
 1446         rv = flask.url_for("static", filename="index.html", _external=True)
 1447         assert rv == "http://example.com/static/index.html"
 1448     # Providing static_host without host_matching=True should error.
 1449     with pytest.raises(Exception):
 1450         flask.Flask(__name__, static_host="example.com")
 1451     # Providing host_matching=True with static_folder
 1452     # but without static_host should error.
 1453     with pytest.raises(Exception):
 1454         flask.Flask(__name__, host_matching=True)
 1455     # Providing host_matching=True without static_host
 1456     # but with static_folder=None should not error.
 1457     flask.Flask(__name__, host_matching=True, static_folder=None)
 1458 
 1459 
 1460 def test_request_locals():
 1461     assert repr(flask.g) == "<LocalProxy unbound>"
 1462     assert not flask.g
 1463 
 1464 
 1465 def test_server_name_subdomain():
 1466     app = flask.Flask(__name__, subdomain_matching=True)
 1467     client = app.test_client()
 1468 
 1469     @app.route("/")
 1470     def index():
 1471         return "default"
 1472 
 1473     @app.route("/", subdomain="foo")
 1474     def subdomain():
 1475         return "subdomain"
 1476 
 1477     app.config["SERVER_NAME"] = "dev.local:5000"
 1478     rv = client.get("/")
 1479     assert rv.data == b"default"
 1480 
 1481     rv = client.get("/", "http://dev.local:5000")
 1482     assert rv.data == b"default"
 1483 
 1484     rv = client.get("/", "https://dev.local:5000")
 1485     assert rv.data == b"default"
 1486 
 1487     app.config["SERVER_NAME"] = "dev.local:443"
 1488     rv = client.get("/", "https://dev.local")
 1489 
 1490     # Werkzeug 1.0 fixes matching https scheme with 443 port
 1491     if rv.status_code != 404:
 1492         assert rv.data == b"default"
 1493 
 1494     app.config["SERVER_NAME"] = "dev.local"
 1495     rv = client.get("/", "https://dev.local")
 1496     assert rv.data == b"default"
 1497 
 1498     # suppress Werkzeug 1.0 warning about name mismatch
 1499     with pytest.warns(None):
 1500         rv = client.get("/", "http://foo.localhost")
 1501         assert rv.status_code == 404
 1502 
 1503     rv = client.get("/", "http://foo.dev.local")
 1504     assert rv.data == b"subdomain"
 1505 
 1506 
 1507 def test_exception_propagation(app, client):
 1508     def apprunner(config_key):
 1509         @app.route("/")
 1510         def index():
 1511             1 // 0
 1512 
 1513         if config_key is not None:
 1514             app.config[config_key] = True
 1515             with pytest.raises(Exception):
 1516                 client.get("/")
 1517         else:
 1518             assert client.get("/").status_code == 500
 1519 
 1520     # we have to run this test in an isolated thread because if the
 1521     # debug flag is set to true and an exception happens the context is
 1522     # not torn down.  This causes other tests that run after this fail
 1523     # when they expect no exception on the stack.
 1524     for config_key in "TESTING", "PROPAGATE_EXCEPTIONS", "DEBUG", None:
 1525         t = Thread(target=apprunner, args=(config_key,))
 1526         t.start()
 1527         t.join()
 1528 
 1529 
 1530 @pytest.mark.parametrize("debug", [True, False])
 1531 @pytest.mark.parametrize("use_debugger", [True, False])
 1532 @pytest.mark.parametrize("use_reloader", [True, False])
 1533 @pytest.mark.parametrize("propagate_exceptions", [None, True, False])
 1534 def test_werkzeug_passthrough_errors(
 1535     monkeypatch, debug, use_debugger, use_reloader, propagate_exceptions, app
 1536 ):
 1537     rv = {}
 1538 
 1539     # Mocks werkzeug.serving.run_simple method
 1540     def run_simple_mock(*args, **kwargs):
 1541         rv["passthrough_errors"] = kwargs.get("passthrough_errors")
 1542 
 1543     monkeypatch.setattr(werkzeug.serving, "run_simple", run_simple_mock)
 1544     app.config["PROPAGATE_EXCEPTIONS"] = propagate_exceptions
 1545     app.run(debug=debug, use_debugger=use_debugger, use_reloader=use_reloader)
 1546 
 1547 
 1548 def test_max_content_length(app, client):
 1549     app.config["MAX_CONTENT_LENGTH"] = 64
 1550 
 1551     @app.before_request
 1552     def always_first():
 1553         flask.request.form["myfile"]
 1554         AssertionError()
 1555 
 1556     @app.route("/accept", methods=["POST"])
 1557     def accept_file():
 1558         flask.request.form["myfile"]
 1559         AssertionError()
 1560 
 1561     @app.errorhandler(413)
 1562     def catcher(error):
 1563         return "42"
 1564 
 1565     rv = client.post("/accept", data={"myfile": "foo" * 100})
 1566     assert rv.data == b"42"
 1567 
 1568 
 1569 def test_url_processors(app, client):
 1570     @app.url_defaults
 1571     def add_language_code(endpoint, values):
 1572         if flask.g.lang_code is not None and app.url_map.is_endpoint_expecting(
 1573             endpoint, "lang_code"
 1574         ):
 1575             values.setdefault("lang_code", flask.g.lang_code)
 1576 
 1577     @app.url_value_preprocessor
 1578     def pull_lang_code(endpoint, values):
 1579         flask.g.lang_code = values.pop("lang_code", None)
 1580 
 1581     @app.route("/<lang_code>/")
 1582     def index():
 1583         return flask.url_for("about")
 1584 
 1585     @app.route("/<lang_code>/about")
 1586     def about():
 1587         return flask.url_for("something_else")
 1588 
 1589     @app.route("/foo")
 1590     def something_else():
 1591         return flask.url_for("about", lang_code="en")
 1592 
 1593     assert client.get("/de/").data == b"/de/about"
 1594     assert client.get("/de/about").data == b"/foo"
 1595     assert client.get("/foo").data == b"/en/about"
 1596 
 1597 
 1598 def test_inject_blueprint_url_defaults(app):
 1599     bp = flask.Blueprint("foo.bar.baz", __name__, template_folder="template")
 1600 
 1601     @bp.url_defaults
 1602     def bp_defaults(endpoint, values):
 1603         values["page"] = "login"
 1604 
 1605     @bp.route("/<page>")
 1606     def view(page):
 1607         pass
 1608 
 1609     app.register_blueprint(bp)
 1610 
 1611     values = dict()
 1612     app.inject_url_defaults("foo.bar.baz.view", values)
 1613     expected = dict(page="login")
 1614     assert values == expected
 1615 
 1616     with app.test_request_context("/somepage"):
 1617         url = flask.url_for("foo.bar.baz.view")
 1618     expected = "/login"
 1619     assert url == expected
 1620 
 1621 
 1622 def test_nonascii_pathinfo(app, client):
 1623     @app.route(u"/киртест")
 1624     def index():
 1625         return "Hello World!"
 1626 
 1627     rv = client.get(u"/киртест")
 1628     assert rv.data == b"Hello World!"
 1629 
 1630 
 1631 def test_debug_mode_complains_after_first_request(app, client):
 1632     app.debug = True
 1633 
 1634     @app.route("/")
 1635     def index():
 1636         return "Awesome"
 1637 
 1638     assert not app.got_first_request
 1639     assert client.get("/").data == b"Awesome"
 1640     with pytest.raises(AssertionError) as e:
 1641 
 1642         @app.route("/foo")
 1643         def broken():
 1644             return "Meh"
 1645 
 1646     assert "A setup function was called" in str(e.value)
 1647 
 1648     app.debug = False
 1649 
 1650     @app.route("/foo")
 1651     def working():
 1652         return "Meh"
 1653 
 1654     assert client.get("/foo").data == b"Meh"
 1655     assert app.got_first_request
 1656 
 1657 
 1658 def test_before_first_request_functions(app, client):
 1659     got = []
 1660 
 1661     @app.before_first_request
 1662     def foo():
 1663         got.append(42)
 1664 
 1665     client.get("/")
 1666     assert got == [42]
 1667     client.get("/")
 1668     assert got == [42]
 1669     assert app.got_first_request
 1670 
 1671 
 1672 def test_before_first_request_functions_concurrent(app, client):
 1673     got = []
 1674 
 1675     @app.before_first_request
 1676     def foo():
 1677         time.sleep(0.2)
 1678         got.append(42)
 1679 
 1680     def get_and_assert():
 1681         client.get("/")
 1682         assert got == [42]
 1683 
 1684     t = Thread(target=get_and_assert)
 1685     t.start()
 1686     get_and_assert()
 1687     t.join()
 1688     assert app.got_first_request
 1689 
 1690 
 1691 def test_routing_redirect_debugging(app, client):
 1692     app.debug = True
 1693 
 1694     @app.route("/foo/", methods=["GET", "POST"])
 1695     def foo():
 1696         return "success"
 1697 
 1698     with client:
 1699         with pytest.raises(AssertionError) as e:
 1700             client.post("/foo", data={})
 1701         assert "http://localhost/foo/" in str(e.value)
 1702         assert ("Make sure to directly send your POST-request to this URL") in str(
 1703             e.value
 1704         )
 1705 
 1706         rv = client.get("/foo", data={}, follow_redirects=True)
 1707         assert rv.data == b"success"
 1708 
 1709     app.debug = False
 1710     with client:
 1711         rv = client.post("/foo", data={}, follow_redirects=True)
 1712         assert rv.data == b"success"
 1713 
 1714 
 1715 def test_route_decorator_custom_endpoint(app, client):
 1716     app.debug = True
 1717 
 1718     @app.route("/foo/")
 1719     def foo():
 1720         return flask.request.endpoint
 1721 
 1722     @app.route("/bar/", endpoint="bar")
 1723     def for_bar():
 1724         return flask.request.endpoint
 1725 
 1726     @app.route("/bar/123", endpoint="123")
 1727     def for_bar_foo():
 1728         return flask.request.endpoint
 1729 
 1730     with app.test_request_context():
 1731         assert flask.url_for("foo") == "/foo/"
 1732         assert flask.url_for("bar") == "/bar/"
 1733         assert flask.url_for("123") == "/bar/123"
 1734 
 1735     assert client.get("/foo/").data == b"foo"
 1736     assert client.get("/bar/").data == b"bar"
 1737     assert client.get("/bar/123").data == b"123"
 1738 
 1739 
 1740 def test_preserve_only_once(app, client):
 1741     app.debug = True
 1742 
 1743     @app.route("/fail")
 1744     def fail_func():
 1745         1 // 0
 1746 
 1747     for _x in range(3):
 1748         with pytest.raises(ZeroDivisionError):
 1749             client.get("/fail")
 1750 
 1751     assert flask._request_ctx_stack.top is not None
 1752     assert flask._app_ctx_stack.top is not None
 1753     # implicit appctx disappears too
 1754     flask._request_ctx_stack.top.pop()
 1755     assert flask._request_ctx_stack.top is None
 1756     assert flask._app_ctx_stack.top is None
 1757 
 1758 
 1759 def test_preserve_remembers_exception(app, client):
 1760     app.debug = True
 1761     errors = []
 1762 
 1763     @app.route("/fail")
 1764     def fail_func():
 1765         1 // 0
 1766 
 1767     @app.route("/success")
 1768     def success_func():
 1769         return "Okay"
 1770 
 1771     @app.teardown_request
 1772     def teardown_handler(exc):
 1773         errors.append(exc)
 1774 
 1775     # After this failure we did not yet call the teardown handler
 1776     with pytest.raises(ZeroDivisionError):
 1777         client.get("/fail")
 1778     assert errors == []
 1779 
 1780     # But this request triggers it, and it's an error
 1781     client.get("/success")
 1782     assert len(errors) == 2
 1783     assert isinstance(errors[0], ZeroDivisionError)
 1784 
 1785     # At this point another request does nothing.
 1786     client.get("/success")
 1787     assert len(errors) == 3
 1788     assert errors[1] is None
 1789 
 1790 
 1791 def test_get_method_on_g(app_ctx):
 1792     assert flask.g.get("x") is None
 1793     assert flask.g.get("x", 11) == 11
 1794     flask.g.x = 42
 1795     assert flask.g.get("x") == 42
 1796     assert flask.g.x == 42
 1797 
 1798 
 1799 def test_g_iteration_protocol(app_ctx):
 1800     flask.g.foo = 23
 1801     flask.g.bar = 42
 1802     assert "foo" in flask.g
 1803     assert "foos" not in flask.g
 1804     assert sorted(flask.g) == ["bar", "foo"]
 1805 
 1806 
 1807 def test_subdomain_basic_support():
 1808     app = flask.Flask(__name__, subdomain_matching=True)
 1809     app.config["SERVER_NAME"] = "localhost.localdomain"
 1810     client = app.test_client()
 1811 
 1812     @app.route("/")
 1813     def normal_index():
 1814         return "normal index"
 1815 
 1816     @app.route("/", subdomain="test")
 1817     def test_index():
 1818         return "test index"
 1819 
 1820     rv = client.get("/", "http://localhost.localdomain/")
 1821     assert rv.data == b"normal index"
 1822 
 1823     rv = client.get("/", "http://test.localhost.localdomain/")
 1824     assert rv.data == b"test index"
 1825 
 1826 
 1827 def test_subdomain_matching():
 1828     app = flask.Flask(__name__, subdomain_matching=True)
 1829     client = app.test_client()
 1830     app.config["SERVER_NAME"] = "localhost.localdomain"
 1831 
 1832     @app.route("/", subdomain="<user>")
 1833     def index(user):
 1834         return "index for %s" % user
 1835 
 1836     rv = client.get("/", "http://mitsuhiko.localhost.localdomain/")
 1837     assert rv.data == b"index for mitsuhiko"
 1838 
 1839 
 1840 def test_subdomain_matching_with_ports():
 1841     app = flask.Flask(__name__, subdomain_matching=True)
 1842     app.config["SERVER_NAME"] = "localhost.localdomain:3000"
 1843     client = app.test_client()
 1844 
 1845     @app.route("/", subdomain="<user>")
 1846     def index(user):
 1847         return "index for %s" % user
 1848 
 1849     rv = client.get("/", "http://mitsuhiko.localhost.localdomain:3000/")
 1850     assert rv.data == b"index for mitsuhiko"
 1851 
 1852 
 1853 @pytest.mark.parametrize("matching", (False, True))
 1854 def test_subdomain_matching_other_name(matching):
 1855     app = flask.Flask(__name__, subdomain_matching=matching)
 1856     app.config["SERVER_NAME"] = "localhost.localdomain:3000"
 1857     client = app.test_client()
 1858 
 1859     @app.route("/")
 1860     def index():
 1861         return "", 204
 1862 
 1863     # suppress Werkzeug 0.15 warning about name mismatch
 1864     with pytest.warns(None):
 1865         # ip address can't match name
 1866         rv = client.get("/", "http://127.0.0.1:3000/")
 1867         assert rv.status_code == 404 if matching else 204
 1868 
 1869     # allow all subdomains if matching is disabled
 1870     rv = client.get("/", "http://www.localhost.localdomain:3000/")
 1871     assert rv.status_code == 404 if matching else 204
 1872 
 1873 
 1874 def test_multi_route_rules(app, client):
 1875     @app.route("/")
 1876     @app.route("/<test>/")
 1877     def index(test="a"):
 1878         return test
 1879 
 1880     rv = client.open("/")
 1881     assert rv.data == b"a"
 1882     rv = client.open("/b/")
 1883     assert rv.data == b"b"
 1884 
 1885 
 1886 def test_multi_route_class_views(app, client):
 1887     class View(object):
 1888         def __init__(self, app):
 1889             app.add_url_rule("/", "index", self.index)
 1890             app.add_url_rule("/<test>/", "index", self.index)
 1891 
 1892         def index(self, test="a"):
 1893             return test
 1894 
 1895     _ = View(app)
 1896     rv = client.open("/")
 1897     assert rv.data == b"a"
 1898     rv = client.open("/b/")
 1899     assert rv.data == b"b"
 1900 
 1901 
 1902 def test_run_defaults(monkeypatch, app):
 1903     rv = {}
 1904 
 1905     # Mocks werkzeug.serving.run_simple method
 1906     def run_simple_mock(*args, **kwargs):
 1907         rv["result"] = "running..."
 1908 
 1909     monkeypatch.setattr(werkzeug.serving, "run_simple", run_simple_mock)
 1910     app.run()
 1911     assert rv["result"] == "running..."
 1912 
 1913 
 1914 def test_run_server_port(monkeypatch, app):
 1915     rv = {}
 1916 
 1917     # Mocks werkzeug.serving.run_simple method
 1918     def run_simple_mock(hostname, port, application, *args, **kwargs):
 1919         rv["result"] = "running on %s:%s ..." % (hostname, port)
 1920 
 1921     monkeypatch.setattr(werkzeug.serving, "run_simple", run_simple_mock)
 1922     hostname, port = "localhost", 8000
 1923     app.run(hostname, port, debug=True)
 1924     assert rv["result"] == "running on %s:%s ..." % (hostname, port)
 1925 
 1926 
 1927 @pytest.mark.parametrize(
 1928     "host,port,server_name,expect_host,expect_port",
 1929     (
 1930         (None, None, "pocoo.org:8080", "pocoo.org", 8080),
 1931         ("localhost", None, "pocoo.org:8080", "localhost", 8080),
 1932         (None, 80, "pocoo.org:8080", "pocoo.org", 80),
 1933         ("localhost", 80, "pocoo.org:8080", "localhost", 80),
 1934         ("localhost", 0, "localhost:8080", "localhost", 0),
 1935         (None, None, "localhost:8080", "localhost", 8080),
 1936         (None, None, "localhost:0", "localhost", 0),
 1937     ),
 1938 )
 1939 def test_run_from_config(
 1940     monkeypatch, host, port, server_name, expect_host, expect_port, app
 1941 ):
 1942     def run_simple_mock(hostname, port, *args, **kwargs):
 1943         assert hostname == expect_host
 1944         assert port == expect_port
 1945 
 1946     monkeypatch.setattr(werkzeug.serving, "run_simple", run_simple_mock)
 1947     app.config["SERVER_NAME"] = server_name
 1948     app.run(host, port)
 1949 
 1950 
 1951 def test_max_cookie_size(app, client, recwarn):
 1952     app.config["MAX_COOKIE_SIZE"] = 100
 1953 
 1954     # outside app context, default to Werkzeug static value,
 1955     # which is also the default config
 1956     response = flask.Response()
 1957     default = flask.Flask.default_config["MAX_COOKIE_SIZE"]
 1958     assert response.max_cookie_size == default
 1959 
 1960     # inside app context, use app config
 1961     with app.app_context():
 1962         assert flask.Response().max_cookie_size == 100
 1963 
 1964     @app.route("/")
 1965     def index():
 1966         r = flask.Response("", status=204)
 1967         r.set_cookie("foo", "bar" * 100)
 1968         return r
 1969 
 1970     client.get("/")
 1971     assert len(recwarn) == 1
 1972     w = recwarn.pop()
 1973     assert "cookie is too large" in str(w.message)
 1974 
 1975     app.config["MAX_COOKIE_SIZE"] = 0
 1976 
 1977     client.get("/")
 1978     assert len(recwarn) == 0