Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/flask/app.py: 25%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import annotations
3import collections.abc as cabc
4import os
5import sys
6import typing as t
7import weakref
8from datetime import timedelta
9from inspect import iscoroutinefunction
10from itertools import chain
11from types import TracebackType
12from urllib.parse import quote as _url_quote
14import click
15from werkzeug.datastructures import Headers
16from werkzeug.datastructures import ImmutableDict
17from werkzeug.exceptions import BadRequestKeyError
18from werkzeug.exceptions import HTTPException
19from werkzeug.exceptions import InternalServerError
20from werkzeug.routing import BuildError
21from werkzeug.routing import MapAdapter
22from werkzeug.routing import RequestRedirect
23from werkzeug.routing import RoutingException
24from werkzeug.routing import Rule
25from werkzeug.serving import is_running_from_reloader
26from werkzeug.wrappers import Response as BaseResponse
28from . import cli
29from . import typing as ft
30from .ctx import AppContext
31from .ctx import RequestContext
32from .globals import _cv_app
33from .globals import _cv_request
34from .globals import current_app
35from .globals import g
36from .globals import request
37from .globals import request_ctx
38from .globals import session
39from .helpers import get_debug_flag
40from .helpers import get_flashed_messages
41from .helpers import get_load_dotenv
42from .helpers import send_from_directory
43from .sansio.app import App
44from .sansio.scaffold import _sentinel
45from .sessions import SecureCookieSessionInterface
46from .sessions import SessionInterface
47from .signals import appcontext_tearing_down
48from .signals import got_request_exception
49from .signals import request_finished
50from .signals import request_started
51from .signals import request_tearing_down
52from .templating import Environment
53from .wrappers import Request
54from .wrappers import Response
56if t.TYPE_CHECKING: # pragma: no cover
57 from _typeshed.wsgi import StartResponse
58 from _typeshed.wsgi import WSGIEnvironment
60 from .testing import FlaskClient
61 from .testing import FlaskCliRunner
63T_shell_context_processor = t.TypeVar(
64 "T_shell_context_processor", bound=ft.ShellContextProcessorCallable
65)
66T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable)
67T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable)
68T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable)
69T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable)
72def _make_timedelta(value: timedelta | int | None) -> timedelta | None:
73 if value is None or isinstance(value, timedelta):
74 return value
76 return timedelta(seconds=value)
79class Flask(App):
80 """The flask object implements a WSGI application and acts as the central
81 object. It is passed the name of the module or package of the
82 application. Once it is created it will act as a central registry for
83 the view functions, the URL rules, template configuration and much more.
85 The name of the package is used to resolve resources from inside the
86 package or the folder the module is contained in depending on if the
87 package parameter resolves to an actual python package (a folder with
88 an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file).
90 For more information about resource loading, see :func:`open_resource`.
92 Usually you create a :class:`Flask` instance in your main module or
93 in the :file:`__init__.py` file of your package like this::
95 from flask import Flask
96 app = Flask(__name__)
98 .. admonition:: About the First Parameter
100 The idea of the first parameter is to give Flask an idea of what
101 belongs to your application. This name is used to find resources
102 on the filesystem, can be used by extensions to improve debugging
103 information and a lot more.
105 So it's important what you provide there. If you are using a single
106 module, `__name__` is always the correct value. If you however are
107 using a package, it's usually recommended to hardcode the name of
108 your package there.
110 For example if your application is defined in :file:`yourapplication/app.py`
111 you should create it with one of the two versions below::
113 app = Flask('yourapplication')
114 app = Flask(__name__.split('.')[0])
116 Why is that? The application will work even with `__name__`, thanks
117 to how resources are looked up. However it will make debugging more
118 painful. Certain extensions can make assumptions based on the
119 import name of your application. For example the Flask-SQLAlchemy
120 extension will look for the code in your application that triggered
121 an SQL query in debug mode. If the import name is not properly set
122 up, that debugging information is lost. (For example it would only
123 pick up SQL queries in `yourapplication.app` and not
124 `yourapplication.views.frontend`)
126 .. versionadded:: 0.7
127 The `static_url_path`, `static_folder`, and `template_folder`
128 parameters were added.
130 .. versionadded:: 0.8
131 The `instance_path` and `instance_relative_config` parameters were
132 added.
134 .. versionadded:: 0.11
135 The `root_path` parameter was added.
137 .. versionadded:: 1.0
138 The ``host_matching`` and ``static_host`` parameters were added.
140 .. versionadded:: 1.0
141 The ``subdomain_matching`` parameter was added. Subdomain
142 matching needs to be enabled manually now. Setting
143 :data:`SERVER_NAME` does not implicitly enable it.
145 :param import_name: the name of the application package
146 :param static_url_path: can be used to specify a different path for the
147 static files on the web. Defaults to the name
148 of the `static_folder` folder.
149 :param static_folder: The folder with static files that is served at
150 ``static_url_path``. Relative to the application ``root_path``
151 or an absolute path. Defaults to ``'static'``.
152 :param static_host: the host to use when adding the static route.
153 Defaults to None. Required when using ``host_matching=True``
154 with a ``static_folder`` configured.
155 :param host_matching: set ``url_map.host_matching`` attribute.
156 Defaults to False.
157 :param subdomain_matching: consider the subdomain relative to
158 :data:`SERVER_NAME` when matching routes. Defaults to False.
159 :param template_folder: the folder that contains the templates that should
160 be used by the application. Defaults to
161 ``'templates'`` folder in the root path of the
162 application.
163 :param instance_path: An alternative instance path for the application.
164 By default the folder ``'instance'`` next to the
165 package or module is assumed to be the instance
166 path.
167 :param instance_relative_config: if set to ``True`` relative filenames
168 for loading the config are assumed to
169 be relative to the instance path instead
170 of the application root.
171 :param root_path: The path to the root of the application files.
172 This should only be set manually when it can't be detected
173 automatically, such as for namespace packages.
174 """
176 default_config = ImmutableDict(
177 {
178 "DEBUG": None,
179 "TESTING": False,
180 "PROPAGATE_EXCEPTIONS": None,
181 "SECRET_KEY": None,
182 "PERMANENT_SESSION_LIFETIME": timedelta(days=31),
183 "USE_X_SENDFILE": False,
184 "SERVER_NAME": None,
185 "APPLICATION_ROOT": "/",
186 "SESSION_COOKIE_NAME": "session",
187 "SESSION_COOKIE_DOMAIN": None,
188 "SESSION_COOKIE_PATH": None,
189 "SESSION_COOKIE_HTTPONLY": True,
190 "SESSION_COOKIE_SECURE": False,
191 "SESSION_COOKIE_SAMESITE": None,
192 "SESSION_REFRESH_EACH_REQUEST": True,
193 "MAX_CONTENT_LENGTH": None,
194 "SEND_FILE_MAX_AGE_DEFAULT": None,
195 "TRAP_BAD_REQUEST_ERRORS": None,
196 "TRAP_HTTP_EXCEPTIONS": False,
197 "EXPLAIN_TEMPLATE_LOADING": False,
198 "PREFERRED_URL_SCHEME": "http",
199 "TEMPLATES_AUTO_RELOAD": None,
200 "MAX_COOKIE_SIZE": 4093,
201 }
202 )
204 #: The class that is used for request objects. See :class:`~flask.Request`
205 #: for more information.
206 request_class: type[Request] = Request
208 #: The class that is used for response objects. See
209 #: :class:`~flask.Response` for more information.
210 response_class: type[Response] = Response
212 #: the session interface to use. By default an instance of
213 #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here.
214 #:
215 #: .. versionadded:: 0.8
216 session_interface: SessionInterface = SecureCookieSessionInterface()
218 def __init__(
219 self,
220 import_name: str,
221 static_url_path: str | None = None,
222 static_folder: str | os.PathLike[str] | None = "static",
223 static_host: str | None = None,
224 host_matching: bool = False,
225 subdomain_matching: bool = False,
226 template_folder: str | os.PathLike[str] | None = "templates",
227 instance_path: str | None = None,
228 instance_relative_config: bool = False,
229 root_path: str | None = None,
230 ):
231 super().__init__(
232 import_name=import_name,
233 static_url_path=static_url_path,
234 static_folder=static_folder,
235 static_host=static_host,
236 host_matching=host_matching,
237 subdomain_matching=subdomain_matching,
238 template_folder=template_folder,
239 instance_path=instance_path,
240 instance_relative_config=instance_relative_config,
241 root_path=root_path,
242 )
244 #: The Click command group for registering CLI commands for this
245 #: object. The commands are available from the ``flask`` command
246 #: once the application has been discovered and blueprints have
247 #: been registered.
248 self.cli = cli.AppGroup()
250 # Set the name of the Click group in case someone wants to add
251 # the app's commands to another CLI tool.
252 self.cli.name = self.name
254 # Add a static route using the provided static_url_path, static_host,
255 # and static_folder if there is a configured static_folder.
256 # Note we do this without checking if static_folder exists.
257 # For one, it might be created while the server is running (e.g. during
258 # development). Also, Google App Engine stores static files somewhere
259 if self.has_static_folder:
260 assert (
261 bool(static_host) == host_matching
262 ), "Invalid static_host/host_matching combination"
263 # Use a weakref to avoid creating a reference cycle between the app
264 # and the view function (see #3761).
265 self_ref = weakref.ref(self)
266 self.add_url_rule(
267 f"{self.static_url_path}/<path:filename>",
268 endpoint="static",
269 host=static_host,
270 view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950
271 )
273 def get_send_file_max_age(self, filename: str | None) -> int | None:
274 """Used by :func:`send_file` to determine the ``max_age`` cache
275 value for a given file path if it wasn't passed.
277 By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from
278 the configuration of :data:`~flask.current_app`. This defaults
279 to ``None``, which tells the browser to use conditional requests
280 instead of a timed cache, which is usually preferable.
282 Note this is a duplicate of the same method in the Flask
283 class.
285 .. versionchanged:: 2.0
286 The default configuration is ``None`` instead of 12 hours.
288 .. versionadded:: 0.9
289 """
290 value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"]
292 if value is None:
293 return None
295 if isinstance(value, timedelta):
296 return int(value.total_seconds())
298 return value # type: ignore[no-any-return]
300 def send_static_file(self, filename: str) -> Response:
301 """The view function used to serve files from
302 :attr:`static_folder`. A route is automatically registered for
303 this view at :attr:`static_url_path` if :attr:`static_folder` is
304 set.
306 Note this is a duplicate of the same method in the Flask
307 class.
309 .. versionadded:: 0.5
311 """
312 if not self.has_static_folder:
313 raise RuntimeError("'static_folder' must be set to serve static_files.")
315 # send_file only knows to call get_send_file_max_age on the app,
316 # call it here so it works for blueprints too.
317 max_age = self.get_send_file_max_age(filename)
318 return send_from_directory(
319 t.cast(str, self.static_folder), filename, max_age=max_age
320 )
322 def open_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]:
323 """Open a resource file relative to :attr:`root_path` for
324 reading.
326 For example, if the file ``schema.sql`` is next to the file
327 ``app.py`` where the ``Flask`` app is defined, it can be opened
328 with:
330 .. code-block:: python
332 with app.open_resource("schema.sql") as f:
333 conn.executescript(f.read())
335 :param resource: Path to the resource relative to
336 :attr:`root_path`.
337 :param mode: Open the file in this mode. Only reading is
338 supported, valid values are "r" (or "rt") and "rb".
340 Note this is a duplicate of the same method in the Flask
341 class.
343 """
344 if mode not in {"r", "rt", "rb"}:
345 raise ValueError("Resources can only be opened for reading.")
347 return open(os.path.join(self.root_path, resource), mode)
349 def open_instance_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]:
350 """Opens a resource from the application's instance folder
351 (:attr:`instance_path`). Otherwise works like
352 :meth:`open_resource`. Instance resources can also be opened for
353 writing.
355 :param resource: the name of the resource. To access resources within
356 subfolders use forward slashes as separator.
357 :param mode: resource file opening mode, default is 'rb'.
358 """
359 return open(os.path.join(self.instance_path, resource), mode)
361 def create_jinja_environment(self) -> Environment:
362 """Create the Jinja environment based on :attr:`jinja_options`
363 and the various Jinja-related methods of the app. Changing
364 :attr:`jinja_options` after this will have no effect. Also adds
365 Flask-related globals and filters to the environment.
367 .. versionchanged:: 0.11
368 ``Environment.auto_reload`` set in accordance with
369 ``TEMPLATES_AUTO_RELOAD`` configuration option.
371 .. versionadded:: 0.5
372 """
373 options = dict(self.jinja_options)
375 if "autoescape" not in options:
376 options["autoescape"] = self.select_jinja_autoescape
378 if "auto_reload" not in options:
379 auto_reload = self.config["TEMPLATES_AUTO_RELOAD"]
381 if auto_reload is None:
382 auto_reload = self.debug
384 options["auto_reload"] = auto_reload
386 rv = self.jinja_environment(self, **options)
387 rv.globals.update(
388 url_for=self.url_for,
389 get_flashed_messages=get_flashed_messages,
390 config=self.config,
391 # request, session and g are normally added with the
392 # context processor for efficiency reasons but for imported
393 # templates we also want the proxies in there.
394 request=request,
395 session=session,
396 g=g,
397 )
398 rv.policies["json.dumps_function"] = self.json.dumps
399 return rv
401 def create_url_adapter(self, request: Request | None) -> MapAdapter | None:
402 """Creates a URL adapter for the given request. The URL adapter
403 is created at a point where the request context is not yet set
404 up so the request is passed explicitly.
406 .. versionadded:: 0.6
408 .. versionchanged:: 0.9
409 This can now also be called without a request object when the
410 URL adapter is created for the application context.
412 .. versionchanged:: 1.0
413 :data:`SERVER_NAME` no longer implicitly enables subdomain
414 matching. Use :attr:`subdomain_matching` instead.
415 """
416 if request is not None:
417 # If subdomain matching is disabled (the default), use the
418 # default subdomain in all cases. This should be the default
419 # in Werkzeug but it currently does not have that feature.
420 if not self.subdomain_matching:
421 subdomain = self.url_map.default_subdomain or None
422 else:
423 subdomain = None
425 return self.url_map.bind_to_environ(
426 request.environ,
427 server_name=self.config["SERVER_NAME"],
428 subdomain=subdomain,
429 )
430 # We need at the very least the server name to be set for this
431 # to work.
432 if self.config["SERVER_NAME"] is not None:
433 return self.url_map.bind(
434 self.config["SERVER_NAME"],
435 script_name=self.config["APPLICATION_ROOT"],
436 url_scheme=self.config["PREFERRED_URL_SCHEME"],
437 )
439 return None
441 def raise_routing_exception(self, request: Request) -> t.NoReturn:
442 """Intercept routing exceptions and possibly do something else.
444 In debug mode, intercept a routing redirect and replace it with
445 an error if the body will be discarded.
447 With modern Werkzeug this shouldn't occur, since it now uses a
448 308 status which tells the browser to resend the method and
449 body.
451 .. versionchanged:: 2.1
452 Don't intercept 307 and 308 redirects.
454 :meta private:
455 :internal:
456 """
457 if (
458 not self.debug
459 or not isinstance(request.routing_exception, RequestRedirect)
460 or request.routing_exception.code in {307, 308}
461 or request.method in {"GET", "HEAD", "OPTIONS"}
462 ):
463 raise request.routing_exception # type: ignore[misc]
465 from .debughelpers import FormDataRoutingRedirect
467 raise FormDataRoutingRedirect(request)
469 def update_template_context(self, context: dict[str, t.Any]) -> None:
470 """Update the template context with some commonly used variables.
471 This injects request, session, config and g into the template
472 context as well as everything template context processors want
473 to inject. Note that the as of Flask 0.6, the original values
474 in the context will not be overridden if a context processor
475 decides to return a value with the same key.
477 :param context: the context as a dictionary that is updated in place
478 to add extra variables.
479 """
480 names: t.Iterable[str | None] = (None,)
482 # A template may be rendered outside a request context.
483 if request:
484 names = chain(names, reversed(request.blueprints))
486 # The values passed to render_template take precedence. Keep a
487 # copy to re-apply after all context functions.
488 orig_ctx = context.copy()
490 for name in names:
491 if name in self.template_context_processors:
492 for func in self.template_context_processors[name]:
493 context.update(self.ensure_sync(func)())
495 context.update(orig_ctx)
497 def make_shell_context(self) -> dict[str, t.Any]:
498 """Returns the shell context for an interactive shell for this
499 application. This runs all the registered shell context
500 processors.
502 .. versionadded:: 0.11
503 """
504 rv = {"app": self, "g": g}
505 for processor in self.shell_context_processors:
506 rv.update(processor())
507 return rv
509 def run(
510 self,
511 host: str | None = None,
512 port: int | None = None,
513 debug: bool | None = None,
514 load_dotenv: bool = True,
515 **options: t.Any,
516 ) -> None:
517 """Runs the application on a local development server.
519 Do not use ``run()`` in a production setting. It is not intended to
520 meet security and performance requirements for a production server.
521 Instead, see :doc:`/deploying/index` for WSGI server recommendations.
523 If the :attr:`debug` flag is set the server will automatically reload
524 for code changes and show a debugger in case an exception happened.
526 If you want to run the application in debug mode, but disable the
527 code execution on the interactive debugger, you can pass
528 ``use_evalex=False`` as parameter. This will keep the debugger's
529 traceback screen active, but disable code execution.
531 It is not recommended to use this function for development with
532 automatic reloading as this is badly supported. Instead you should
533 be using the :command:`flask` command line script's ``run`` support.
535 .. admonition:: Keep in Mind
537 Flask will suppress any server error with a generic error page
538 unless it is in debug mode. As such to enable just the
539 interactive debugger without the code reloading, you have to
540 invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``.
541 Setting ``use_debugger`` to ``True`` without being in debug mode
542 won't catch any exceptions because there won't be any to
543 catch.
545 :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to
546 have the server available externally as well. Defaults to
547 ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable
548 if present.
549 :param port: the port of the webserver. Defaults to ``5000`` or the
550 port defined in the ``SERVER_NAME`` config variable if present.
551 :param debug: if given, enable or disable debug mode. See
552 :attr:`debug`.
553 :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv`
554 files to set environment variables. Will also change the working
555 directory to the directory containing the first file found.
556 :param options: the options to be forwarded to the underlying Werkzeug
557 server. See :func:`werkzeug.serving.run_simple` for more
558 information.
560 .. versionchanged:: 1.0
561 If installed, python-dotenv will be used to load environment
562 variables from :file:`.env` and :file:`.flaskenv` files.
564 The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`.
566 Threaded mode is enabled by default.
568 .. versionchanged:: 0.10
569 The default port is now picked from the ``SERVER_NAME``
570 variable.
571 """
572 # Ignore this call so that it doesn't start another server if
573 # the 'flask run' command is used.
574 if os.environ.get("FLASK_RUN_FROM_CLI") == "true":
575 if not is_running_from_reloader():
576 click.secho(
577 " * Ignoring a call to 'app.run()' that would block"
578 " the current 'flask' CLI command.\n"
579 " Only call 'app.run()' in an 'if __name__ =="
580 ' "__main__"\' guard.',
581 fg="red",
582 )
584 return
586 if get_load_dotenv(load_dotenv):
587 cli.load_dotenv()
589 # if set, env var overrides existing value
590 if "FLASK_DEBUG" in os.environ:
591 self.debug = get_debug_flag()
593 # debug passed to method overrides all other sources
594 if debug is not None:
595 self.debug = bool(debug)
597 server_name = self.config.get("SERVER_NAME")
598 sn_host = sn_port = None
600 if server_name:
601 sn_host, _, sn_port = server_name.partition(":")
603 if not host:
604 if sn_host:
605 host = sn_host
606 else:
607 host = "127.0.0.1"
609 if port or port == 0:
610 port = int(port)
611 elif sn_port:
612 port = int(sn_port)
613 else:
614 port = 5000
616 options.setdefault("use_reloader", self.debug)
617 options.setdefault("use_debugger", self.debug)
618 options.setdefault("threaded", True)
620 cli.show_server_banner(self.debug, self.name)
622 from werkzeug.serving import run_simple
624 try:
625 run_simple(t.cast(str, host), port, self, **options)
626 finally:
627 # reset the first request information if the development server
628 # reset normally. This makes it possible to restart the server
629 # without reloader and that stuff from an interactive shell.
630 self._got_first_request = False
632 def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> FlaskClient:
633 """Creates a test client for this application. For information
634 about unit testing head over to :doc:`/testing`.
636 Note that if you are testing for assertions or exceptions in your
637 application code, you must set ``app.testing = True`` in order for the
638 exceptions to propagate to the test client. Otherwise, the exception
639 will be handled by the application (not visible to the test client) and
640 the only indication of an AssertionError or other exception will be a
641 500 status code response to the test client. See the :attr:`testing`
642 attribute. For example::
644 app.testing = True
645 client = app.test_client()
647 The test client can be used in a ``with`` block to defer the closing down
648 of the context until the end of the ``with`` block. This is useful if
649 you want to access the context locals for testing::
651 with app.test_client() as c:
652 rv = c.get('/?vodka=42')
653 assert request.args['vodka'] == '42'
655 Additionally, you may pass optional keyword arguments that will then
656 be passed to the application's :attr:`test_client_class` constructor.
657 For example::
659 from flask.testing import FlaskClient
661 class CustomClient(FlaskClient):
662 def __init__(self, *args, **kwargs):
663 self._authentication = kwargs.pop("authentication")
664 super(CustomClient,self).__init__( *args, **kwargs)
666 app.test_client_class = CustomClient
667 client = app.test_client(authentication='Basic ....')
669 See :class:`~flask.testing.FlaskClient` for more information.
671 .. versionchanged:: 0.4
672 added support for ``with`` block usage for the client.
674 .. versionadded:: 0.7
675 The `use_cookies` parameter was added as well as the ability
676 to override the client to be used by setting the
677 :attr:`test_client_class` attribute.
679 .. versionchanged:: 0.11
680 Added `**kwargs` to support passing additional keyword arguments to
681 the constructor of :attr:`test_client_class`.
682 """
683 cls = self.test_client_class
684 if cls is None:
685 from .testing import FlaskClient as cls
686 return cls( # type: ignore
687 self, self.response_class, use_cookies=use_cookies, **kwargs
688 )
690 def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner:
691 """Create a CLI runner for testing CLI commands.
692 See :ref:`testing-cli`.
694 Returns an instance of :attr:`test_cli_runner_class`, by default
695 :class:`~flask.testing.FlaskCliRunner`. The Flask app object is
696 passed as the first argument.
698 .. versionadded:: 1.0
699 """
700 cls = self.test_cli_runner_class
702 if cls is None:
703 from .testing import FlaskCliRunner as cls
705 return cls(self, **kwargs) # type: ignore
707 def handle_http_exception(
708 self, e: HTTPException
709 ) -> HTTPException | ft.ResponseReturnValue:
710 """Handles an HTTP exception. By default this will invoke the
711 registered error handlers and fall back to returning the
712 exception as response.
714 .. versionchanged:: 1.0.3
715 ``RoutingException``, used internally for actions such as
716 slash redirects during routing, is not passed to error
717 handlers.
719 .. versionchanged:: 1.0
720 Exceptions are looked up by code *and* by MRO, so
721 ``HTTPException`` subclasses can be handled with a catch-all
722 handler for the base ``HTTPException``.
724 .. versionadded:: 0.3
725 """
726 # Proxy exceptions don't have error codes. We want to always return
727 # those unchanged as errors
728 if e.code is None:
729 return e
731 # RoutingExceptions are used internally to trigger routing
732 # actions, such as slash redirects raising RequestRedirect. They
733 # are not raised or handled in user code.
734 if isinstance(e, RoutingException):
735 return e
737 handler = self._find_error_handler(e, request.blueprints)
738 if handler is None:
739 return e
740 return self.ensure_sync(handler)(e) # type: ignore[no-any-return]
742 def handle_user_exception(
743 self, e: Exception
744 ) -> HTTPException | ft.ResponseReturnValue:
745 """This method is called whenever an exception occurs that
746 should be handled. A special case is :class:`~werkzeug
747 .exceptions.HTTPException` which is forwarded to the
748 :meth:`handle_http_exception` method. This function will either
749 return a response value or reraise the exception with the same
750 traceback.
752 .. versionchanged:: 1.0
753 Key errors raised from request data like ``form`` show the
754 bad key in debug mode rather than a generic bad request
755 message.
757 .. versionadded:: 0.7
758 """
759 if isinstance(e, BadRequestKeyError) and (
760 self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"]
761 ):
762 e.show_exception = True
764 if isinstance(e, HTTPException) and not self.trap_http_exception(e):
765 return self.handle_http_exception(e)
767 handler = self._find_error_handler(e, request.blueprints)
769 if handler is None:
770 raise
772 return self.ensure_sync(handler)(e) # type: ignore[no-any-return]
774 def handle_exception(self, e: Exception) -> Response:
775 """Handle an exception that did not have an error handler
776 associated with it, or that was raised from an error handler.
777 This always causes a 500 ``InternalServerError``.
779 Always sends the :data:`got_request_exception` signal.
781 If :data:`PROPAGATE_EXCEPTIONS` is ``True``, such as in debug
782 mode, the error will be re-raised so that the debugger can
783 display it. Otherwise, the original exception is logged, and
784 an :exc:`~werkzeug.exceptions.InternalServerError` is returned.
786 If an error handler is registered for ``InternalServerError`` or
787 ``500``, it will be used. For consistency, the handler will
788 always receive the ``InternalServerError``. The original
789 unhandled exception is available as ``e.original_exception``.
791 .. versionchanged:: 1.1.0
792 Always passes the ``InternalServerError`` instance to the
793 handler, setting ``original_exception`` to the unhandled
794 error.
796 .. versionchanged:: 1.1.0
797 ``after_request`` functions and other finalization is done
798 even for the default 500 response when there is no handler.
800 .. versionadded:: 0.3
801 """
802 exc_info = sys.exc_info()
803 got_request_exception.send(self, _async_wrapper=self.ensure_sync, exception=e)
804 propagate = self.config["PROPAGATE_EXCEPTIONS"]
806 if propagate is None:
807 propagate = self.testing or self.debug
809 if propagate:
810 # Re-raise if called with an active exception, otherwise
811 # raise the passed in exception.
812 if exc_info[1] is e:
813 raise
815 raise e
817 self.log_exception(exc_info)
818 server_error: InternalServerError | ft.ResponseReturnValue
819 server_error = InternalServerError(original_exception=e)
820 handler = self._find_error_handler(server_error, request.blueprints)
822 if handler is not None:
823 server_error = self.ensure_sync(handler)(server_error)
825 return self.finalize_request(server_error, from_error_handler=True)
827 def log_exception(
828 self,
829 exc_info: (tuple[type, BaseException, TracebackType] | tuple[None, None, None]),
830 ) -> None:
831 """Logs an exception. This is called by :meth:`handle_exception`
832 if debugging is disabled and right before the handler is called.
833 The default implementation logs the exception as error on the
834 :attr:`logger`.
836 .. versionadded:: 0.8
837 """
838 self.logger.error(
839 f"Exception on {request.path} [{request.method}]", exc_info=exc_info
840 )
842 def dispatch_request(self) -> ft.ResponseReturnValue:
843 """Does the request dispatching. Matches the URL and returns the
844 return value of the view or error handler. This does not have to
845 be a response object. In order to convert the return value to a
846 proper response object, call :func:`make_response`.
848 .. versionchanged:: 0.7
849 This no longer does the exception handling, this code was
850 moved to the new :meth:`full_dispatch_request`.
851 """
852 req = request_ctx.request
853 if req.routing_exception is not None:
854 self.raise_routing_exception(req)
855 rule: Rule = req.url_rule # type: ignore[assignment]
856 # if we provide automatic options for this URL and the
857 # request came with the OPTIONS method, reply automatically
858 if (
859 getattr(rule, "provide_automatic_options", False)
860 and req.method == "OPTIONS"
861 ):
862 return self.make_default_options_response()
863 # otherwise dispatch to the handler for that endpoint
864 view_args: dict[str, t.Any] = req.view_args # type: ignore[assignment]
865 return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
867 def full_dispatch_request(self) -> Response:
868 """Dispatches the request and on top of that performs request
869 pre and postprocessing as well as HTTP exception catching and
870 error handling.
872 .. versionadded:: 0.7
873 """
874 self._got_first_request = True
876 try:
877 request_started.send(self, _async_wrapper=self.ensure_sync)
878 rv = self.preprocess_request()
879 if rv is None:
880 rv = self.dispatch_request()
881 except Exception as e:
882 rv = self.handle_user_exception(e)
883 return self.finalize_request(rv)
885 def finalize_request(
886 self,
887 rv: ft.ResponseReturnValue | HTTPException,
888 from_error_handler: bool = False,
889 ) -> Response:
890 """Given the return value from a view function this finalizes
891 the request by converting it into a response and invoking the
892 postprocessing functions. This is invoked for both normal
893 request dispatching as well as error handlers.
895 Because this means that it might be called as a result of a
896 failure a special safe mode is available which can be enabled
897 with the `from_error_handler` flag. If enabled, failures in
898 response processing will be logged and otherwise ignored.
900 :internal:
901 """
902 response = self.make_response(rv)
903 try:
904 response = self.process_response(response)
905 request_finished.send(
906 self, _async_wrapper=self.ensure_sync, response=response
907 )
908 except Exception:
909 if not from_error_handler:
910 raise
911 self.logger.exception(
912 "Request finalizing failed with an error while handling an error"
913 )
914 return response
916 def make_default_options_response(self) -> Response:
917 """This method is called to create the default ``OPTIONS`` response.
918 This can be changed through subclassing to change the default
919 behavior of ``OPTIONS`` responses.
921 .. versionadded:: 0.7
922 """
923 adapter = request_ctx.url_adapter
924 methods = adapter.allowed_methods() # type: ignore[union-attr]
925 rv = self.response_class()
926 rv.allow.update(methods)
927 return rv
929 def ensure_sync(self, func: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]:
930 """Ensure that the function is synchronous for WSGI workers.
931 Plain ``def`` functions are returned as-is. ``async def``
932 functions are wrapped to run and wait for the response.
934 Override this method to change how the app runs async views.
936 .. versionadded:: 2.0
937 """
938 if iscoroutinefunction(func):
939 return self.async_to_sync(func)
941 return func
943 def async_to_sync(
944 self, func: t.Callable[..., t.Coroutine[t.Any, t.Any, t.Any]]
945 ) -> t.Callable[..., t.Any]:
946 """Return a sync function that will run the coroutine function.
948 .. code-block:: python
950 result = app.async_to_sync(func)(*args, **kwargs)
952 Override this method to change how the app converts async code
953 to be synchronously callable.
955 .. versionadded:: 2.0
956 """
957 try:
958 from asgiref.sync import async_to_sync as asgiref_async_to_sync
959 except ImportError:
960 raise RuntimeError(
961 "Install Flask with the 'async' extra in order to use async views."
962 ) from None
964 return asgiref_async_to_sync(func)
966 def url_for(
967 self,
968 /,
969 endpoint: str,
970 *,
971 _anchor: str | None = None,
972 _method: str | None = None,
973 _scheme: str | None = None,
974 _external: bool | None = None,
975 **values: t.Any,
976 ) -> str:
977 """Generate a URL to the given endpoint with the given values.
979 This is called by :func:`flask.url_for`, and can be called
980 directly as well.
982 An *endpoint* is the name of a URL rule, usually added with
983 :meth:`@app.route() <route>`, and usually the same name as the
984 view function. A route defined in a :class:`~flask.Blueprint`
985 will prepend the blueprint's name separated by a ``.`` to the
986 endpoint.
988 In some cases, such as email messages, you want URLs to include
989 the scheme and domain, like ``https://example.com/hello``. When
990 not in an active request, URLs will be external by default, but
991 this requires setting :data:`SERVER_NAME` so Flask knows what
992 domain to use. :data:`APPLICATION_ROOT` and
993 :data:`PREFERRED_URL_SCHEME` should also be configured as
994 needed. This config is only used when not in an active request.
996 Functions can be decorated with :meth:`url_defaults` to modify
997 keyword arguments before the URL is built.
999 If building fails for some reason, such as an unknown endpoint
1000 or incorrect values, the app's :meth:`handle_url_build_error`
1001 method is called. If that returns a string, that is returned,
1002 otherwise a :exc:`~werkzeug.routing.BuildError` is raised.
1004 :param endpoint: The endpoint name associated with the URL to
1005 generate. If this starts with a ``.``, the current blueprint
1006 name (if any) will be used.
1007 :param _anchor: If given, append this as ``#anchor`` to the URL.
1008 :param _method: If given, generate the URL associated with this
1009 method for the endpoint.
1010 :param _scheme: If given, the URL will have this scheme if it
1011 is external.
1012 :param _external: If given, prefer the URL to be internal
1013 (False) or require it to be external (True). External URLs
1014 include the scheme and domain. When not in an active
1015 request, URLs are external by default.
1016 :param values: Values to use for the variable parts of the URL
1017 rule. Unknown keys are appended as query string arguments,
1018 like ``?a=b&c=d``.
1020 .. versionadded:: 2.2
1021 Moved from ``flask.url_for``, which calls this method.
1022 """
1023 req_ctx = _cv_request.get(None)
1025 if req_ctx is not None:
1026 url_adapter = req_ctx.url_adapter
1027 blueprint_name = req_ctx.request.blueprint
1029 # If the endpoint starts with "." and the request matches a
1030 # blueprint, the endpoint is relative to the blueprint.
1031 if endpoint[:1] == ".":
1032 if blueprint_name is not None:
1033 endpoint = f"{blueprint_name}{endpoint}"
1034 else:
1035 endpoint = endpoint[1:]
1037 # When in a request, generate a URL without scheme and
1038 # domain by default, unless a scheme is given.
1039 if _external is None:
1040 _external = _scheme is not None
1041 else:
1042 app_ctx = _cv_app.get(None)
1044 # If called by helpers.url_for, an app context is active,
1045 # use its url_adapter. Otherwise, app.url_for was called
1046 # directly, build an adapter.
1047 if app_ctx is not None:
1048 url_adapter = app_ctx.url_adapter
1049 else:
1050 url_adapter = self.create_url_adapter(None)
1052 if url_adapter is None:
1053 raise RuntimeError(
1054 "Unable to build URLs outside an active request"
1055 " without 'SERVER_NAME' configured. Also configure"
1056 " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as"
1057 " needed."
1058 )
1060 # When outside a request, generate a URL with scheme and
1061 # domain by default.
1062 if _external is None:
1063 _external = True
1065 # It is an error to set _scheme when _external=False, in order
1066 # to avoid accidental insecure URLs.
1067 if _scheme is not None and not _external:
1068 raise ValueError("When specifying '_scheme', '_external' must be True.")
1070 self.inject_url_defaults(endpoint, values)
1072 try:
1073 rv = url_adapter.build( # type: ignore[union-attr]
1074 endpoint,
1075 values,
1076 method=_method,
1077 url_scheme=_scheme,
1078 force_external=_external,
1079 )
1080 except BuildError as error:
1081 values.update(
1082 _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external
1083 )
1084 return self.handle_url_build_error(error, endpoint, values)
1086 if _anchor is not None:
1087 _anchor = _url_quote(_anchor, safe="%!#$&'()*+,/:;=?@")
1088 rv = f"{rv}#{_anchor}"
1090 return rv
1092 def make_response(self, rv: ft.ResponseReturnValue) -> Response:
1093 """Convert the return value from a view function to an instance of
1094 :attr:`response_class`.
1096 :param rv: the return value from the view function. The view function
1097 must return a response. Returning ``None``, or the view ending
1098 without returning, is not allowed. The following types are allowed
1099 for ``view_rv``:
1101 ``str``
1102 A response object is created with the string encoded to UTF-8
1103 as the body.
1105 ``bytes``
1106 A response object is created with the bytes as the body.
1108 ``dict``
1109 A dictionary that will be jsonify'd before being returned.
1111 ``list``
1112 A list that will be jsonify'd before being returned.
1114 ``generator`` or ``iterator``
1115 A generator that returns ``str`` or ``bytes`` to be
1116 streamed as the response.
1118 ``tuple``
1119 Either ``(body, status, headers)``, ``(body, status)``, or
1120 ``(body, headers)``, where ``body`` is any of the other types
1121 allowed here, ``status`` is a string or an integer, and
1122 ``headers`` is a dictionary or a list of ``(key, value)``
1123 tuples. If ``body`` is a :attr:`response_class` instance,
1124 ``status`` overwrites the exiting value and ``headers`` are
1125 extended.
1127 :attr:`response_class`
1128 The object is returned unchanged.
1130 other :class:`~werkzeug.wrappers.Response` class
1131 The object is coerced to :attr:`response_class`.
1133 :func:`callable`
1134 The function is called as a WSGI application. The result is
1135 used to create a response object.
1137 .. versionchanged:: 2.2
1138 A generator will be converted to a streaming response.
1139 A list will be converted to a JSON response.
1141 .. versionchanged:: 1.1
1142 A dict will be converted to a JSON response.
1144 .. versionchanged:: 0.9
1145 Previously a tuple was interpreted as the arguments for the
1146 response object.
1147 """
1149 status = headers = None
1151 # unpack tuple returns
1152 if isinstance(rv, tuple):
1153 len_rv = len(rv)
1155 # a 3-tuple is unpacked directly
1156 if len_rv == 3:
1157 rv, status, headers = rv # type: ignore[misc]
1158 # decide if a 2-tuple has status or headers
1159 elif len_rv == 2:
1160 if isinstance(rv[1], (Headers, dict, tuple, list)):
1161 rv, headers = rv
1162 else:
1163 rv, status = rv # type: ignore[assignment,misc]
1164 # other sized tuples are not allowed
1165 else:
1166 raise TypeError(
1167 "The view function did not return a valid response tuple."
1168 " The tuple must have the form (body, status, headers),"
1169 " (body, status), or (body, headers)."
1170 )
1172 # the body must not be None
1173 if rv is None:
1174 raise TypeError(
1175 f"The view function for {request.endpoint!r} did not"
1176 " return a valid response. The function either returned"
1177 " None or ended without a return statement."
1178 )
1180 # make sure the body is an instance of the response class
1181 if not isinstance(rv, self.response_class):
1182 if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, cabc.Iterator):
1183 # let the response class set the status and headers instead of
1184 # waiting to do it manually, so that the class can handle any
1185 # special logic
1186 rv = self.response_class(
1187 rv,
1188 status=status,
1189 headers=headers, # type: ignore[arg-type]
1190 )
1191 status = headers = None
1192 elif isinstance(rv, (dict, list)):
1193 rv = self.json.response(rv)
1194 elif isinstance(rv, BaseResponse) or callable(rv):
1195 # evaluate a WSGI callable, or coerce a different response
1196 # class to the correct type
1197 try:
1198 rv = self.response_class.force_type(
1199 rv, # type: ignore[arg-type]
1200 request.environ,
1201 )
1202 except TypeError as e:
1203 raise TypeError(
1204 f"{e}\nThe view function did not return a valid"
1205 " response. The return type must be a string,"
1206 " dict, list, tuple with headers or status,"
1207 " Response instance, or WSGI callable, but it"
1208 f" was a {type(rv).__name__}."
1209 ).with_traceback(sys.exc_info()[2]) from None
1210 else:
1211 raise TypeError(
1212 "The view function did not return a valid"
1213 " response. The return type must be a string,"
1214 " dict, list, tuple with headers or status,"
1215 " Response instance, or WSGI callable, but it was a"
1216 f" {type(rv).__name__}."
1217 )
1219 rv = t.cast(Response, rv)
1220 # prefer the status if it was provided
1221 if status is not None:
1222 if isinstance(status, (str, bytes, bytearray)):
1223 rv.status = status
1224 else:
1225 rv.status_code = status
1227 # extend existing headers with provided headers
1228 if headers:
1229 rv.headers.update(headers) # type: ignore[arg-type]
1231 return rv
1233 def preprocess_request(self) -> ft.ResponseReturnValue | None:
1234 """Called before the request is dispatched. Calls
1235 :attr:`url_value_preprocessors` registered with the app and the
1236 current blueprint (if any). Then calls :attr:`before_request_funcs`
1237 registered with the app and the blueprint.
1239 If any :meth:`before_request` handler returns a non-None value, the
1240 value is handled as if it was the return value from the view, and
1241 further request handling is stopped.
1242 """
1243 names = (None, *reversed(request.blueprints))
1245 for name in names:
1246 if name in self.url_value_preprocessors:
1247 for url_func in self.url_value_preprocessors[name]:
1248 url_func(request.endpoint, request.view_args)
1250 for name in names:
1251 if name in self.before_request_funcs:
1252 for before_func in self.before_request_funcs[name]:
1253 rv = self.ensure_sync(before_func)()
1255 if rv is not None:
1256 return rv # type: ignore[no-any-return]
1258 return None
1260 def process_response(self, response: Response) -> Response:
1261 """Can be overridden in order to modify the response object
1262 before it's sent to the WSGI server. By default this will
1263 call all the :meth:`after_request` decorated functions.
1265 .. versionchanged:: 0.5
1266 As of Flask 0.5 the functions registered for after request
1267 execution are called in reverse order of registration.
1269 :param response: a :attr:`response_class` object.
1270 :return: a new response object or the same, has to be an
1271 instance of :attr:`response_class`.
1272 """
1273 ctx = request_ctx._get_current_object() # type: ignore[attr-defined]
1275 for func in ctx._after_request_functions:
1276 response = self.ensure_sync(func)(response)
1278 for name in chain(request.blueprints, (None,)):
1279 if name in self.after_request_funcs:
1280 for func in reversed(self.after_request_funcs[name]):
1281 response = self.ensure_sync(func)(response)
1283 if not self.session_interface.is_null_session(ctx.session):
1284 self.session_interface.save_session(self, ctx.session, response)
1286 return response
1288 def do_teardown_request(
1289 self,
1290 exc: BaseException | None = _sentinel, # type: ignore[assignment]
1291 ) -> None:
1292 """Called after the request is dispatched and the response is
1293 returned, right before the request context is popped.
1295 This calls all functions decorated with
1296 :meth:`teardown_request`, and :meth:`Blueprint.teardown_request`
1297 if a blueprint handled the request. Finally, the
1298 :data:`request_tearing_down` signal is sent.
1300 This is called by
1301 :meth:`RequestContext.pop() <flask.ctx.RequestContext.pop>`,
1302 which may be delayed during testing to maintain access to
1303 resources.
1305 :param exc: An unhandled exception raised while dispatching the
1306 request. Detected from the current exception information if
1307 not passed. Passed to each teardown function.
1309 .. versionchanged:: 0.9
1310 Added the ``exc`` argument.
1311 """
1312 if exc is _sentinel:
1313 exc = sys.exc_info()[1]
1315 for name in chain(request.blueprints, (None,)):
1316 if name in self.teardown_request_funcs:
1317 for func in reversed(self.teardown_request_funcs[name]):
1318 self.ensure_sync(func)(exc)
1320 request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
1322 def do_teardown_appcontext(
1323 self,
1324 exc: BaseException | None = _sentinel, # type: ignore[assignment]
1325 ) -> None:
1326 """Called right before the application context is popped.
1328 When handling a request, the application context is popped
1329 after the request context. See :meth:`do_teardown_request`.
1331 This calls all functions decorated with
1332 :meth:`teardown_appcontext`. Then the
1333 :data:`appcontext_tearing_down` signal is sent.
1335 This is called by
1336 :meth:`AppContext.pop() <flask.ctx.AppContext.pop>`.
1338 .. versionadded:: 0.9
1339 """
1340 if exc is _sentinel:
1341 exc = sys.exc_info()[1]
1343 for func in reversed(self.teardown_appcontext_funcs):
1344 self.ensure_sync(func)(exc)
1346 appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
1348 def app_context(self) -> AppContext:
1349 """Create an :class:`~flask.ctx.AppContext`. Use as a ``with``
1350 block to push the context, which will make :data:`current_app`
1351 point at this application.
1353 An application context is automatically pushed by
1354 :meth:`RequestContext.push() <flask.ctx.RequestContext.push>`
1355 when handling a request, and when running a CLI command. Use
1356 this to manually create a context outside of these situations.
1358 ::
1360 with app.app_context():
1361 init_db()
1363 See :doc:`/appcontext`.
1365 .. versionadded:: 0.9
1366 """
1367 return AppContext(self)
1369 def request_context(self, environ: WSGIEnvironment) -> RequestContext:
1370 """Create a :class:`~flask.ctx.RequestContext` representing a
1371 WSGI environment. Use a ``with`` block to push the context,
1372 which will make :data:`request` point at this request.
1374 See :doc:`/reqcontext`.
1376 Typically you should not call this from your own code. A request
1377 context is automatically pushed by the :meth:`wsgi_app` when
1378 handling a request. Use :meth:`test_request_context` to create
1379 an environment and context instead of this method.
1381 :param environ: a WSGI environment
1382 """
1383 return RequestContext(self, environ)
1385 def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext:
1386 """Create a :class:`~flask.ctx.RequestContext` for a WSGI
1387 environment created from the given values. This is mostly useful
1388 during testing, where you may want to run a function that uses
1389 request data without dispatching a full request.
1391 See :doc:`/reqcontext`.
1393 Use a ``with`` block to push the context, which will make
1394 :data:`request` point at the request for the created
1395 environment. ::
1397 with app.test_request_context(...):
1398 generate_report()
1400 When using the shell, it may be easier to push and pop the
1401 context manually to avoid indentation. ::
1403 ctx = app.test_request_context(...)
1404 ctx.push()
1405 ...
1406 ctx.pop()
1408 Takes the same arguments as Werkzeug's
1409 :class:`~werkzeug.test.EnvironBuilder`, with some defaults from
1410 the application. See the linked Werkzeug docs for most of the
1411 available arguments. Flask-specific behavior is listed here.
1413 :param path: URL path being requested.
1414 :param base_url: Base URL where the app is being served, which
1415 ``path`` is relative to. If not given, built from
1416 :data:`PREFERRED_URL_SCHEME`, ``subdomain``,
1417 :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.
1418 :param subdomain: Subdomain name to append to
1419 :data:`SERVER_NAME`.
1420 :param url_scheme: Scheme to use instead of
1421 :data:`PREFERRED_URL_SCHEME`.
1422 :param data: The request body, either as a string or a dict of
1423 form keys and values.
1424 :param json: If given, this is serialized as JSON and passed as
1425 ``data``. Also defaults ``content_type`` to
1426 ``application/json``.
1427 :param args: other positional arguments passed to
1428 :class:`~werkzeug.test.EnvironBuilder`.
1429 :param kwargs: other keyword arguments passed to
1430 :class:`~werkzeug.test.EnvironBuilder`.
1431 """
1432 from .testing import EnvironBuilder
1434 builder = EnvironBuilder(self, *args, **kwargs)
1436 try:
1437 return self.request_context(builder.get_environ())
1438 finally:
1439 builder.close()
1441 def wsgi_app(
1442 self, environ: WSGIEnvironment, start_response: StartResponse
1443 ) -> cabc.Iterable[bytes]:
1444 """The actual WSGI application. This is not implemented in
1445 :meth:`__call__` so that middlewares can be applied without
1446 losing a reference to the app object. Instead of doing this::
1448 app = MyMiddleware(app)
1450 It's a better idea to do this instead::
1452 app.wsgi_app = MyMiddleware(app.wsgi_app)
1454 Then you still have the original application object around and
1455 can continue to call methods on it.
1457 .. versionchanged:: 0.7
1458 Teardown events for the request and app contexts are called
1459 even if an unhandled error occurs. Other events may not be
1460 called depending on when an error occurs during dispatch.
1461 See :ref:`callbacks-and-errors`.
1463 :param environ: A WSGI environment.
1464 :param start_response: A callable accepting a status code,
1465 a list of headers, and an optional exception context to
1466 start the response.
1467 """
1468 ctx = self.request_context(environ)
1469 error: BaseException | None = None
1470 try:
1471 try:
1472 ctx.push()
1473 response = self.full_dispatch_request()
1474 except Exception as e:
1475 error = e
1476 response = self.handle_exception(e)
1477 except: # noqa: B001
1478 error = sys.exc_info()[1]
1479 raise
1480 return response(environ, start_response)
1481 finally:
1482 if "werkzeug.debug.preserve_context" in environ:
1483 environ["werkzeug.debug.preserve_context"](_cv_app.get())
1484 environ["werkzeug.debug.preserve_context"](_cv_request.get())
1486 if error is not None and self.should_ignore_error(error):
1487 error = None
1489 ctx.pop(error)
1491 def __call__(
1492 self, environ: WSGIEnvironment, start_response: StartResponse
1493 ) -> cabc.Iterable[bytes]:
1494 """The WSGI server calls the Flask application object as the
1495 WSGI application. This calls :meth:`wsgi_app`, which can be
1496 wrapped to apply middleware.
1497 """
1498 return self.wsgi_app(environ, start_response)