Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/flask/app.py: 58%
581 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-09 06:08 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-09 06:08 +0000
1from __future__ import annotations
3import logging
4import os
5import sys
6import typing as t
7import weakref
8from collections.abc import Iterator as _abc_Iterator
9from datetime import timedelta
10from inspect import iscoroutinefunction
11from itertools import chain
12from types import TracebackType
13from urllib.parse import quote as _url_quote
15import click
16from werkzeug.datastructures import Headers
17from werkzeug.datastructures import ImmutableDict
18from werkzeug.exceptions import Aborter
19from werkzeug.exceptions import BadRequest
20from werkzeug.exceptions import BadRequestKeyError
21from werkzeug.exceptions import HTTPException
22from werkzeug.exceptions import InternalServerError
23from werkzeug.routing import BuildError
24from werkzeug.routing import Map
25from werkzeug.routing import MapAdapter
26from werkzeug.routing import RequestRedirect
27from werkzeug.routing import RoutingException
28from werkzeug.routing import Rule
29from werkzeug.serving import is_running_from_reloader
30from werkzeug.utils import cached_property
31from werkzeug.utils import redirect as _wz_redirect
32from werkzeug.wrappers import Response as BaseResponse
34from . import cli
35from . import typing as ft
36from .config import Config
37from .config import ConfigAttribute
38from .ctx import _AppCtxGlobals
39from .ctx import AppContext
40from .ctx import RequestContext
41from .globals import _cv_app
42from .globals import _cv_request
43from .globals import g
44from .globals import request
45from .globals import request_ctx
46from .globals import session
47from .helpers import _split_blueprint_path
48from .helpers import get_debug_flag
49from .helpers import get_flashed_messages
50from .helpers import get_load_dotenv
51from .json.provider import DefaultJSONProvider
52from .json.provider import JSONProvider
53from .logging import create_logger
54from .scaffold import _endpoint_from_view_func
55from .scaffold import _sentinel
56from .scaffold import find_package
57from .scaffold import Scaffold
58from .scaffold import setupmethod
59from .sessions import SecureCookieSessionInterface
60from .sessions import SessionInterface
61from .signals import appcontext_tearing_down
62from .signals import got_request_exception
63from .signals import request_finished
64from .signals import request_started
65from .signals import request_tearing_down
66from .templating import DispatchingJinjaLoader
67from .templating import Environment
68from .wrappers import Request
69from .wrappers import Response
71if t.TYPE_CHECKING: # pragma: no cover
72 from .blueprints import Blueprint
73 from .testing import FlaskClient
74 from .testing import FlaskCliRunner
76T_shell_context_processor = t.TypeVar(
77 "T_shell_context_processor", bound=ft.ShellContextProcessorCallable
78)
79T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable)
80T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable)
81T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable)
82T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable)
85def _make_timedelta(value: timedelta | int | None) -> timedelta | None:
86 if value is None or isinstance(value, timedelta):
87 return value
89 return timedelta(seconds=value)
92class Flask(Scaffold):
93 """The flask object implements a WSGI application and acts as the central
94 object. It is passed the name of the module or package of the
95 application. Once it is created it will act as a central registry for
96 the view functions, the URL rules, template configuration and much more.
98 The name of the package is used to resolve resources from inside the
99 package or the folder the module is contained in depending on if the
100 package parameter resolves to an actual python package (a folder with
101 an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file).
103 For more information about resource loading, see :func:`open_resource`.
105 Usually you create a :class:`Flask` instance in your main module or
106 in the :file:`__init__.py` file of your package like this::
108 from flask import Flask
109 app = Flask(__name__)
111 .. admonition:: About the First Parameter
113 The idea of the first parameter is to give Flask an idea of what
114 belongs to your application. This name is used to find resources
115 on the filesystem, can be used by extensions to improve debugging
116 information and a lot more.
118 So it's important what you provide there. If you are using a single
119 module, `__name__` is always the correct value. If you however are
120 using a package, it's usually recommended to hardcode the name of
121 your package there.
123 For example if your application is defined in :file:`yourapplication/app.py`
124 you should create it with one of the two versions below::
126 app = Flask('yourapplication')
127 app = Flask(__name__.split('.')[0])
129 Why is that? The application will work even with `__name__`, thanks
130 to how resources are looked up. However it will make debugging more
131 painful. Certain extensions can make assumptions based on the
132 import name of your application. For example the Flask-SQLAlchemy
133 extension will look for the code in your application that triggered
134 an SQL query in debug mode. If the import name is not properly set
135 up, that debugging information is lost. (For example it would only
136 pick up SQL queries in `yourapplication.app` and not
137 `yourapplication.views.frontend`)
139 .. versionadded:: 0.7
140 The `static_url_path`, `static_folder`, and `template_folder`
141 parameters were added.
143 .. versionadded:: 0.8
144 The `instance_path` and `instance_relative_config` parameters were
145 added.
147 .. versionadded:: 0.11
148 The `root_path` parameter was added.
150 .. versionadded:: 1.0
151 The ``host_matching`` and ``static_host`` parameters were added.
153 .. versionadded:: 1.0
154 The ``subdomain_matching`` parameter was added. Subdomain
155 matching needs to be enabled manually now. Setting
156 :data:`SERVER_NAME` does not implicitly enable it.
158 :param import_name: the name of the application package
159 :param static_url_path: can be used to specify a different path for the
160 static files on the web. Defaults to the name
161 of the `static_folder` folder.
162 :param static_folder: The folder with static files that is served at
163 ``static_url_path``. Relative to the application ``root_path``
164 or an absolute path. Defaults to ``'static'``.
165 :param static_host: the host to use when adding the static route.
166 Defaults to None. Required when using ``host_matching=True``
167 with a ``static_folder`` configured.
168 :param host_matching: set ``url_map.host_matching`` attribute.
169 Defaults to False.
170 :param subdomain_matching: consider the subdomain relative to
171 :data:`SERVER_NAME` when matching routes. Defaults to False.
172 :param template_folder: the folder that contains the templates that should
173 be used by the application. Defaults to
174 ``'templates'`` folder in the root path of the
175 application.
176 :param instance_path: An alternative instance path for the application.
177 By default the folder ``'instance'`` next to the
178 package or module is assumed to be the instance
179 path.
180 :param instance_relative_config: if set to ``True`` relative filenames
181 for loading the config are assumed to
182 be relative to the instance path instead
183 of the application root.
184 :param root_path: The path to the root of the application files.
185 This should only be set manually when it can't be detected
186 automatically, such as for namespace packages.
187 """
189 #: The class that is used for request objects. See :class:`~flask.Request`
190 #: for more information.
191 request_class = Request
193 #: The class that is used for response objects. See
194 #: :class:`~flask.Response` for more information.
195 response_class = Response
197 #: The class of the object assigned to :attr:`aborter`, created by
198 #: :meth:`create_aborter`. That object is called by
199 #: :func:`flask.abort` to raise HTTP errors, and can be
200 #: called directly as well.
201 #:
202 #: Defaults to :class:`werkzeug.exceptions.Aborter`.
203 #:
204 #: .. versionadded:: 2.2
205 aborter_class = Aborter
207 #: The class that is used for the Jinja environment.
208 #:
209 #: .. versionadded:: 0.11
210 jinja_environment = Environment
212 #: The class that is used for the :data:`~flask.g` instance.
213 #:
214 #: Example use cases for a custom class:
215 #:
216 #: 1. Store arbitrary attributes on flask.g.
217 #: 2. Add a property for lazy per-request database connectors.
218 #: 3. Return None instead of AttributeError on unexpected attributes.
219 #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g.
220 #:
221 #: In Flask 0.9 this property was called `request_globals_class` but it
222 #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the
223 #: flask.g object is now application context scoped.
224 #:
225 #: .. versionadded:: 0.10
226 app_ctx_globals_class = _AppCtxGlobals
228 #: The class that is used for the ``config`` attribute of this app.
229 #: Defaults to :class:`~flask.Config`.
230 #:
231 #: Example use cases for a custom class:
232 #:
233 #: 1. Default values for certain config options.
234 #: 2. Access to config values through attributes in addition to keys.
235 #:
236 #: .. versionadded:: 0.11
237 config_class = Config
239 #: The testing flag. Set this to ``True`` to enable the test mode of
240 #: Flask extensions (and in the future probably also Flask itself).
241 #: For example this might activate test helpers that have an
242 #: additional runtime cost which should not be enabled by default.
243 #:
244 #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the
245 #: default it's implicitly enabled.
246 #:
247 #: This attribute can also be configured from the config with the
248 #: ``TESTING`` configuration key. Defaults to ``False``.
249 testing = ConfigAttribute("TESTING")
251 #: If a secret key is set, cryptographic components can use this to
252 #: sign cookies and other things. Set this to a complex random value
253 #: when you want to use the secure cookie for instance.
254 #:
255 #: This attribute can also be configured from the config with the
256 #: :data:`SECRET_KEY` configuration key. Defaults to ``None``.
257 secret_key = ConfigAttribute("SECRET_KEY")
259 #: A :class:`~datetime.timedelta` which is used to set the expiration
260 #: date of a permanent session. The default is 31 days which makes a
261 #: permanent session survive for roughly one month.
262 #:
263 #: This attribute can also be configured from the config with the
264 #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to
265 #: ``timedelta(days=31)``
266 permanent_session_lifetime = ConfigAttribute(
267 "PERMANENT_SESSION_LIFETIME", get_converter=_make_timedelta
268 )
270 json_provider_class: type[JSONProvider] = DefaultJSONProvider
271 """A subclass of :class:`~flask.json.provider.JSONProvider`. An
272 instance is created and assigned to :attr:`app.json` when creating
273 the app.
275 The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses
276 Python's built-in :mod:`json` library. A different provider can use
277 a different JSON library.
279 .. versionadded:: 2.2
280 """
282 #: Options that are passed to the Jinja environment in
283 #: :meth:`create_jinja_environment`. Changing these options after
284 #: the environment is created (accessing :attr:`jinja_env`) will
285 #: have no effect.
286 #:
287 #: .. versionchanged:: 1.1.0
288 #: This is a ``dict`` instead of an ``ImmutableDict`` to allow
289 #: easier configuration.
290 #:
291 jinja_options: dict = {}
293 #: Default configuration parameters.
294 default_config = ImmutableDict(
295 {
296 "DEBUG": None,
297 "TESTING": False,
298 "PROPAGATE_EXCEPTIONS": None,
299 "SECRET_KEY": None,
300 "PERMANENT_SESSION_LIFETIME": timedelta(days=31),
301 "USE_X_SENDFILE": False,
302 "SERVER_NAME": None,
303 "APPLICATION_ROOT": "/",
304 "SESSION_COOKIE_NAME": "session",
305 "SESSION_COOKIE_DOMAIN": None,
306 "SESSION_COOKIE_PATH": None,
307 "SESSION_COOKIE_HTTPONLY": True,
308 "SESSION_COOKIE_SECURE": False,
309 "SESSION_COOKIE_SAMESITE": None,
310 "SESSION_REFRESH_EACH_REQUEST": True,
311 "MAX_CONTENT_LENGTH": None,
312 "SEND_FILE_MAX_AGE_DEFAULT": None,
313 "TRAP_BAD_REQUEST_ERRORS": None,
314 "TRAP_HTTP_EXCEPTIONS": False,
315 "EXPLAIN_TEMPLATE_LOADING": False,
316 "PREFERRED_URL_SCHEME": "http",
317 "TEMPLATES_AUTO_RELOAD": None,
318 "MAX_COOKIE_SIZE": 4093,
319 }
320 )
322 #: The rule object to use for URL rules created. This is used by
323 #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`.
324 #:
325 #: .. versionadded:: 0.7
326 url_rule_class = Rule
328 #: The map object to use for storing the URL rules and routing
329 #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`.
330 #:
331 #: .. versionadded:: 1.1.0
332 url_map_class = Map
334 #: The :meth:`test_client` method creates an instance of this test
335 #: client class. Defaults to :class:`~flask.testing.FlaskClient`.
336 #:
337 #: .. versionadded:: 0.7
338 test_client_class: type[FlaskClient] | None = None
340 #: The :class:`~click.testing.CliRunner` subclass, by default
341 #: :class:`~flask.testing.FlaskCliRunner` that is used by
342 #: :meth:`test_cli_runner`. Its ``__init__`` method should take a
343 #: Flask app object as the first argument.
344 #:
345 #: .. versionadded:: 1.0
346 test_cli_runner_class: type[FlaskCliRunner] | None = None
348 #: the session interface to use. By default an instance of
349 #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here.
350 #:
351 #: .. versionadded:: 0.8
352 session_interface: SessionInterface = SecureCookieSessionInterface()
354 def __init__(
355 self,
356 import_name: str,
357 static_url_path: str | None = None,
358 static_folder: str | os.PathLike | None = "static",
359 static_host: str | None = None,
360 host_matching: bool = False,
361 subdomain_matching: bool = False,
362 template_folder: str | os.PathLike | None = "templates",
363 instance_path: str | None = None,
364 instance_relative_config: bool = False,
365 root_path: str | None = None,
366 ):
367 super().__init__(
368 import_name=import_name,
369 static_folder=static_folder,
370 static_url_path=static_url_path,
371 template_folder=template_folder,
372 root_path=root_path,
373 )
375 if instance_path is None:
376 instance_path = self.auto_find_instance_path()
377 elif not os.path.isabs(instance_path):
378 raise ValueError(
379 "If an instance path is provided it must be absolute."
380 " A relative path was given instead."
381 )
383 #: Holds the path to the instance folder.
384 #:
385 #: .. versionadded:: 0.8
386 self.instance_path = instance_path
388 #: The configuration dictionary as :class:`Config`. This behaves
389 #: exactly like a regular dictionary but supports additional methods
390 #: to load a config from files.
391 self.config = self.make_config(instance_relative_config)
393 #: An instance of :attr:`aborter_class` created by
394 #: :meth:`make_aborter`. This is called by :func:`flask.abort`
395 #: to raise HTTP errors, and can be called directly as well.
396 #:
397 #: .. versionadded:: 2.2
398 #: Moved from ``flask.abort``, which calls this object.
399 self.aborter = self.make_aborter()
401 self.json: JSONProvider = self.json_provider_class(self)
402 """Provides access to JSON methods. Functions in ``flask.json``
403 will call methods on this provider when the application context
404 is active. Used for handling JSON requests and responses.
406 An instance of :attr:`json_provider_class`. Can be customized by
407 changing that attribute on a subclass, or by assigning to this
408 attribute afterwards.
410 The default, :class:`~flask.json.provider.DefaultJSONProvider`,
411 uses Python's built-in :mod:`json` library. A different provider
412 can use a different JSON library.
414 .. versionadded:: 2.2
415 """
417 #: A list of functions that are called by
418 #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a
419 #: :exc:`~werkzeug.routing.BuildError`. Each function is called
420 #: with ``error``, ``endpoint`` and ``values``. If a function
421 #: returns ``None`` or raises a ``BuildError``, it is skipped.
422 #: Otherwise, its return value is returned by ``url_for``.
423 #:
424 #: .. versionadded:: 0.9
425 self.url_build_error_handlers: list[
426 t.Callable[[Exception, str, dict[str, t.Any]], str]
427 ] = []
429 #: A list of functions that are called when the application context
430 #: is destroyed. Since the application context is also torn down
431 #: if the request ends this is the place to store code that disconnects
432 #: from databases.
433 #:
434 #: .. versionadded:: 0.9
435 self.teardown_appcontext_funcs: list[ft.TeardownCallable] = []
437 #: A list of shell context processor functions that should be run
438 #: when a shell context is created.
439 #:
440 #: .. versionadded:: 0.11
441 self.shell_context_processors: list[ft.ShellContextProcessorCallable] = []
443 #: Maps registered blueprint names to blueprint objects. The
444 #: dict retains the order the blueprints were registered in.
445 #: Blueprints can be registered multiple times, this dict does
446 #: not track how often they were attached.
447 #:
448 #: .. versionadded:: 0.7
449 self.blueprints: dict[str, Blueprint] = {}
451 #: a place where extensions can store application specific state. For
452 #: example this is where an extension could store database engines and
453 #: similar things.
454 #:
455 #: The key must match the name of the extension module. For example in
456 #: case of a "Flask-Foo" extension in `flask_foo`, the key would be
457 #: ``'foo'``.
458 #:
459 #: .. versionadded:: 0.7
460 self.extensions: dict = {}
462 #: The :class:`~werkzeug.routing.Map` for this instance. You can use
463 #: this to change the routing converters after the class was created
464 #: but before any routes are connected. Example::
465 #:
466 #: from werkzeug.routing import BaseConverter
467 #:
468 #: class ListConverter(BaseConverter):
469 #: def to_python(self, value):
470 #: return value.split(',')
471 #: def to_url(self, values):
472 #: return ','.join(super(ListConverter, self).to_url(value)
473 #: for value in values)
474 #:
475 #: app = Flask(__name__)
476 #: app.url_map.converters['list'] = ListConverter
477 self.url_map = self.url_map_class()
479 self.url_map.host_matching = host_matching
480 self.subdomain_matching = subdomain_matching
482 # tracks internally if the application already handled at least one
483 # request.
484 self._got_first_request = False
486 # Add a static route using the provided static_url_path, static_host,
487 # and static_folder if there is a configured static_folder.
488 # Note we do this without checking if static_folder exists.
489 # For one, it might be created while the server is running (e.g. during
490 # development). Also, Google App Engine stores static files somewhere
491 if self.has_static_folder:
492 assert (
493 bool(static_host) == host_matching
494 ), "Invalid static_host/host_matching combination"
495 # Use a weakref to avoid creating a reference cycle between the app
496 # and the view function (see #3761).
497 self_ref = weakref.ref(self)
498 self.add_url_rule(
499 f"{self.static_url_path}/<path:filename>",
500 endpoint="static",
501 host=static_host,
502 view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950
503 )
505 # Set the name of the Click group in case someone wants to add
506 # the app's commands to another CLI tool.
507 self.cli.name = self.name
509 def _check_setup_finished(self, f_name: str) -> None:
510 if self._got_first_request:
511 raise AssertionError(
512 f"The setup method '{f_name}' can no longer be called"
513 " on the application. It has already handled its first"
514 " request, any changes will not be applied"
515 " consistently.\n"
516 "Make sure all imports, decorators, functions, etc."
517 " needed to set up the application are done before"
518 " running it."
519 )
521 @cached_property
522 def name(self) -> str: # type: ignore
523 """The name of the application. This is usually the import name
524 with the difference that it's guessed from the run file if the
525 import name is main. This name is used as a display name when
526 Flask needs the name of the application. It can be set and overridden
527 to change the value.
529 .. versionadded:: 0.8
530 """
531 if self.import_name == "__main__":
532 fn = getattr(sys.modules["__main__"], "__file__", None)
533 if fn is None:
534 return "__main__"
535 return os.path.splitext(os.path.basename(fn))[0]
536 return self.import_name
538 @cached_property
539 def logger(self) -> logging.Logger:
540 """A standard Python :class:`~logging.Logger` for the app, with
541 the same name as :attr:`name`.
543 In debug mode, the logger's :attr:`~logging.Logger.level` will
544 be set to :data:`~logging.DEBUG`.
546 If there are no handlers configured, a default handler will be
547 added. See :doc:`/logging` for more information.
549 .. versionchanged:: 1.1.0
550 The logger takes the same name as :attr:`name` rather than
551 hard-coding ``"flask.app"``.
553 .. versionchanged:: 1.0.0
554 Behavior was simplified. The logger is always named
555 ``"flask.app"``. The level is only set during configuration,
556 it doesn't check ``app.debug`` each time. Only one format is
557 used, not different ones depending on ``app.debug``. No
558 handlers are removed, and a handler is only added if no
559 handlers are already configured.
561 .. versionadded:: 0.3
562 """
563 return create_logger(self)
565 @cached_property
566 def jinja_env(self) -> Environment:
567 """The Jinja environment used to load templates.
569 The environment is created the first time this property is
570 accessed. Changing :attr:`jinja_options` after that will have no
571 effect.
572 """
573 return self.create_jinja_environment()
575 @property
576 def got_first_request(self) -> bool:
577 """This attribute is set to ``True`` if the application started
578 handling the first request.
580 .. deprecated:: 2.3
581 Will be removed in Flask 2.4.
583 .. versionadded:: 0.8
584 """
585 import warnings
587 warnings.warn(
588 "'got_first_request' is deprecated and will be removed in Flask 2.4.",
589 DeprecationWarning,
590 stacklevel=2,
591 )
592 return self._got_first_request
594 def make_config(self, instance_relative: bool = False) -> Config:
595 """Used to create the config attribute by the Flask constructor.
596 The `instance_relative` parameter is passed in from the constructor
597 of Flask (there named `instance_relative_config`) and indicates if
598 the config should be relative to the instance path or the root path
599 of the application.
601 .. versionadded:: 0.8
602 """
603 root_path = self.root_path
604 if instance_relative:
605 root_path = self.instance_path
606 defaults = dict(self.default_config)
607 defaults["DEBUG"] = get_debug_flag()
608 return self.config_class(root_path, defaults)
610 def make_aborter(self) -> Aborter:
611 """Create the object to assign to :attr:`aborter`. That object
612 is called by :func:`flask.abort` to raise HTTP errors, and can
613 be called directly as well.
615 By default, this creates an instance of :attr:`aborter_class`,
616 which defaults to :class:`werkzeug.exceptions.Aborter`.
618 .. versionadded:: 2.2
619 """
620 return self.aborter_class()
622 def auto_find_instance_path(self) -> str:
623 """Tries to locate the instance path if it was not provided to the
624 constructor of the application class. It will basically calculate
625 the path to a folder named ``instance`` next to your main file or
626 the package.
628 .. versionadded:: 0.8
629 """
630 prefix, package_path = find_package(self.import_name)
631 if prefix is None:
632 return os.path.join(package_path, "instance")
633 return os.path.join(prefix, "var", f"{self.name}-instance")
635 def open_instance_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]:
636 """Opens a resource from the application's instance folder
637 (:attr:`instance_path`). Otherwise works like
638 :meth:`open_resource`. Instance resources can also be opened for
639 writing.
641 :param resource: the name of the resource. To access resources within
642 subfolders use forward slashes as separator.
643 :param mode: resource file opening mode, default is 'rb'.
644 """
645 return open(os.path.join(self.instance_path, resource), mode)
647 def create_jinja_environment(self) -> Environment:
648 """Create the Jinja environment based on :attr:`jinja_options`
649 and the various Jinja-related methods of the app. Changing
650 :attr:`jinja_options` after this will have no effect. Also adds
651 Flask-related globals and filters to the environment.
653 .. versionchanged:: 0.11
654 ``Environment.auto_reload`` set in accordance with
655 ``TEMPLATES_AUTO_RELOAD`` configuration option.
657 .. versionadded:: 0.5
658 """
659 options = dict(self.jinja_options)
661 if "autoescape" not in options:
662 options["autoescape"] = self.select_jinja_autoescape
664 if "auto_reload" not in options:
665 auto_reload = self.config["TEMPLATES_AUTO_RELOAD"]
667 if auto_reload is None:
668 auto_reload = self.debug
670 options["auto_reload"] = auto_reload
672 rv = self.jinja_environment(self, **options)
673 rv.globals.update(
674 url_for=self.url_for,
675 get_flashed_messages=get_flashed_messages,
676 config=self.config,
677 # request, session and g are normally added with the
678 # context processor for efficiency reasons but for imported
679 # templates we also want the proxies in there.
680 request=request,
681 session=session,
682 g=g,
683 )
684 rv.policies["json.dumps_function"] = self.json.dumps
685 return rv
687 def create_global_jinja_loader(self) -> DispatchingJinjaLoader:
688 """Creates the loader for the Jinja2 environment. Can be used to
689 override just the loader and keeping the rest unchanged. It's
690 discouraged to override this function. Instead one should override
691 the :meth:`jinja_loader` function instead.
693 The global loader dispatches between the loaders of the application
694 and the individual blueprints.
696 .. versionadded:: 0.7
697 """
698 return DispatchingJinjaLoader(self)
700 def select_jinja_autoescape(self, filename: str) -> bool:
701 """Returns ``True`` if autoescaping should be active for the given
702 template name. If no template name is given, returns `True`.
704 .. versionchanged:: 2.2
705 Autoescaping is now enabled by default for ``.svg`` files.
707 .. versionadded:: 0.5
708 """
709 if filename is None:
710 return True
711 return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg"))
713 def update_template_context(self, context: dict) -> None:
714 """Update the template context with some commonly used variables.
715 This injects request, session, config and g into the template
716 context as well as everything template context processors want
717 to inject. Note that the as of Flask 0.6, the original values
718 in the context will not be overridden if a context processor
719 decides to return a value with the same key.
721 :param context: the context as a dictionary that is updated in place
722 to add extra variables.
723 """
724 names: t.Iterable[str | None] = (None,)
726 # A template may be rendered outside a request context.
727 if request:
728 names = chain(names, reversed(request.blueprints))
730 # The values passed to render_template take precedence. Keep a
731 # copy to re-apply after all context functions.
732 orig_ctx = context.copy()
734 for name in names:
735 if name in self.template_context_processors:
736 for func in self.template_context_processors[name]:
737 context.update(func())
739 context.update(orig_ctx)
741 def make_shell_context(self) -> dict:
742 """Returns the shell context for an interactive shell for this
743 application. This runs all the registered shell context
744 processors.
746 .. versionadded:: 0.11
747 """
748 rv = {"app": self, "g": g}
749 for processor in self.shell_context_processors:
750 rv.update(processor())
751 return rv
753 @property
754 def debug(self) -> bool:
755 """Whether debug mode is enabled. When using ``flask run`` to start the
756 development server, an interactive debugger will be shown for unhandled
757 exceptions, and the server will be reloaded when code changes. This maps to the
758 :data:`DEBUG` config key. It may not behave as expected if set late.
760 **Do not enable debug mode when deploying in production.**
762 Default: ``False``
763 """
764 return self.config["DEBUG"]
766 @debug.setter
767 def debug(self, value: bool) -> None:
768 self.config["DEBUG"] = value
770 if self.config["TEMPLATES_AUTO_RELOAD"] is None:
771 self.jinja_env.auto_reload = value
773 def run(
774 self,
775 host: str | None = None,
776 port: int | None = None,
777 debug: bool | None = None,
778 load_dotenv: bool = True,
779 **options: t.Any,
780 ) -> None:
781 """Runs the application on a local development server.
783 Do not use ``run()`` in a production setting. It is not intended to
784 meet security and performance requirements for a production server.
785 Instead, see :doc:`/deploying/index` for WSGI server recommendations.
787 If the :attr:`debug` flag is set the server will automatically reload
788 for code changes and show a debugger in case an exception happened.
790 If you want to run the application in debug mode, but disable the
791 code execution on the interactive debugger, you can pass
792 ``use_evalex=False`` as parameter. This will keep the debugger's
793 traceback screen active, but disable code execution.
795 It is not recommended to use this function for development with
796 automatic reloading as this is badly supported. Instead you should
797 be using the :command:`flask` command line script's ``run`` support.
799 .. admonition:: Keep in Mind
801 Flask will suppress any server error with a generic error page
802 unless it is in debug mode. As such to enable just the
803 interactive debugger without the code reloading, you have to
804 invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``.
805 Setting ``use_debugger`` to ``True`` without being in debug mode
806 won't catch any exceptions because there won't be any to
807 catch.
809 :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to
810 have the server available externally as well. Defaults to
811 ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable
812 if present.
813 :param port: the port of the webserver. Defaults to ``5000`` or the
814 port defined in the ``SERVER_NAME`` config variable if present.
815 :param debug: if given, enable or disable debug mode. See
816 :attr:`debug`.
817 :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv`
818 files to set environment variables. Will also change the working
819 directory to the directory containing the first file found.
820 :param options: the options to be forwarded to the underlying Werkzeug
821 server. See :func:`werkzeug.serving.run_simple` for more
822 information.
824 .. versionchanged:: 1.0
825 If installed, python-dotenv will be used to load environment
826 variables from :file:`.env` and :file:`.flaskenv` files.
828 The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`.
830 Threaded mode is enabled by default.
832 .. versionchanged:: 0.10
833 The default port is now picked from the ``SERVER_NAME``
834 variable.
835 """
836 # Ignore this call so that it doesn't start another server if
837 # the 'flask run' command is used.
838 if os.environ.get("FLASK_RUN_FROM_CLI") == "true":
839 if not is_running_from_reloader():
840 click.secho(
841 " * Ignoring a call to 'app.run()' that would block"
842 " the current 'flask' CLI command.\n"
843 " Only call 'app.run()' in an 'if __name__ =="
844 ' "__main__"\' guard.',
845 fg="red",
846 )
848 return
850 if get_load_dotenv(load_dotenv):
851 cli.load_dotenv()
853 # if set, env var overrides existing value
854 if "FLASK_DEBUG" in os.environ:
855 self.debug = get_debug_flag()
857 # debug passed to method overrides all other sources
858 if debug is not None:
859 self.debug = bool(debug)
861 server_name = self.config.get("SERVER_NAME")
862 sn_host = sn_port = None
864 if server_name:
865 sn_host, _, sn_port = server_name.partition(":")
867 if not host:
868 if sn_host:
869 host = sn_host
870 else:
871 host = "127.0.0.1"
873 if port or port == 0:
874 port = int(port)
875 elif sn_port:
876 port = int(sn_port)
877 else:
878 port = 5000
880 options.setdefault("use_reloader", self.debug)
881 options.setdefault("use_debugger", self.debug)
882 options.setdefault("threaded", True)
884 cli.show_server_banner(self.debug, self.name)
886 from werkzeug.serving import run_simple
888 try:
889 run_simple(t.cast(str, host), port, self, **options)
890 finally:
891 # reset the first request information if the development server
892 # reset normally. This makes it possible to restart the server
893 # without reloader and that stuff from an interactive shell.
894 self._got_first_request = False
896 def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> FlaskClient:
897 """Creates a test client for this application. For information
898 about unit testing head over to :doc:`/testing`.
900 Note that if you are testing for assertions or exceptions in your
901 application code, you must set ``app.testing = True`` in order for the
902 exceptions to propagate to the test client. Otherwise, the exception
903 will be handled by the application (not visible to the test client) and
904 the only indication of an AssertionError or other exception will be a
905 500 status code response to the test client. See the :attr:`testing`
906 attribute. For example::
908 app.testing = True
909 client = app.test_client()
911 The test client can be used in a ``with`` block to defer the closing down
912 of the context until the end of the ``with`` block. This is useful if
913 you want to access the context locals for testing::
915 with app.test_client() as c:
916 rv = c.get('/?vodka=42')
917 assert request.args['vodka'] == '42'
919 Additionally, you may pass optional keyword arguments that will then
920 be passed to the application's :attr:`test_client_class` constructor.
921 For example::
923 from flask.testing import FlaskClient
925 class CustomClient(FlaskClient):
926 def __init__(self, *args, **kwargs):
927 self._authentication = kwargs.pop("authentication")
928 super(CustomClient,self).__init__( *args, **kwargs)
930 app.test_client_class = CustomClient
931 client = app.test_client(authentication='Basic ....')
933 See :class:`~flask.testing.FlaskClient` for more information.
935 .. versionchanged:: 0.4
936 added support for ``with`` block usage for the client.
938 .. versionadded:: 0.7
939 The `use_cookies` parameter was added as well as the ability
940 to override the client to be used by setting the
941 :attr:`test_client_class` attribute.
943 .. versionchanged:: 0.11
944 Added `**kwargs` to support passing additional keyword arguments to
945 the constructor of :attr:`test_client_class`.
946 """
947 cls = self.test_client_class
948 if cls is None:
949 from .testing import FlaskClient as cls
950 return cls( # type: ignore
951 self, self.response_class, use_cookies=use_cookies, **kwargs
952 )
954 def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner:
955 """Create a CLI runner for testing CLI commands.
956 See :ref:`testing-cli`.
958 Returns an instance of :attr:`test_cli_runner_class`, by default
959 :class:`~flask.testing.FlaskCliRunner`. The Flask app object is
960 passed as the first argument.
962 .. versionadded:: 1.0
963 """
964 cls = self.test_cli_runner_class
966 if cls is None:
967 from .testing import FlaskCliRunner as cls
969 return cls(self, **kwargs) # type: ignore
971 @setupmethod
972 def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None:
973 """Register a :class:`~flask.Blueprint` on the application. Keyword
974 arguments passed to this method will override the defaults set on the
975 blueprint.
977 Calls the blueprint's :meth:`~flask.Blueprint.register` method after
978 recording the blueprint in the application's :attr:`blueprints`.
980 :param blueprint: The blueprint to register.
981 :param url_prefix: Blueprint routes will be prefixed with this.
982 :param subdomain: Blueprint routes will match on this subdomain.
983 :param url_defaults: Blueprint routes will use these default values for
984 view arguments.
985 :param options: Additional keyword arguments are passed to
986 :class:`~flask.blueprints.BlueprintSetupState`. They can be
987 accessed in :meth:`~flask.Blueprint.record` callbacks.
989 .. versionchanged:: 2.0.1
990 The ``name`` option can be used to change the (pre-dotted)
991 name the blueprint is registered with. This allows the same
992 blueprint to be registered multiple times with unique names
993 for ``url_for``.
995 .. versionadded:: 0.7
996 """
997 blueprint.register(self, options)
999 def iter_blueprints(self) -> t.ValuesView[Blueprint]:
1000 """Iterates over all blueprints by the order they were registered.
1002 .. versionadded:: 0.11
1003 """
1004 return self.blueprints.values()
1006 @setupmethod
1007 def add_url_rule(
1008 self,
1009 rule: str,
1010 endpoint: str | None = None,
1011 view_func: ft.RouteCallable | None = None,
1012 provide_automatic_options: bool | None = None,
1013 **options: t.Any,
1014 ) -> None:
1015 if endpoint is None:
1016 endpoint = _endpoint_from_view_func(view_func) # type: ignore
1017 options["endpoint"] = endpoint
1018 methods = options.pop("methods", None)
1020 # if the methods are not given and the view_func object knows its
1021 # methods we can use that instead. If neither exists, we go with
1022 # a tuple of only ``GET`` as default.
1023 if methods is None:
1024 methods = getattr(view_func, "methods", None) or ("GET",)
1025 if isinstance(methods, str):
1026 raise TypeError(
1027 "Allowed methods must be a list of strings, for"
1028 ' example: @app.route(..., methods=["POST"])'
1029 )
1030 methods = {item.upper() for item in methods}
1032 # Methods that should always be added
1033 required_methods = set(getattr(view_func, "required_methods", ()))
1035 # starting with Flask 0.8 the view_func object can disable and
1036 # force-enable the automatic options handling.
1037 if provide_automatic_options is None:
1038 provide_automatic_options = getattr(
1039 view_func, "provide_automatic_options", None
1040 )
1042 if provide_automatic_options is None:
1043 if "OPTIONS" not in methods:
1044 provide_automatic_options = True
1045 required_methods.add("OPTIONS")
1046 else:
1047 provide_automatic_options = False
1049 # Add the required methods now.
1050 methods |= required_methods
1052 rule = self.url_rule_class(rule, methods=methods, **options)
1053 rule.provide_automatic_options = provide_automatic_options # type: ignore
1055 self.url_map.add(rule)
1056 if view_func is not None:
1057 old_func = self.view_functions.get(endpoint)
1058 if old_func is not None and old_func != view_func:
1059 raise AssertionError(
1060 "View function mapping is overwriting an existing"
1061 f" endpoint function: {endpoint}"
1062 )
1063 self.view_functions[endpoint] = view_func
1065 @setupmethod
1066 def template_filter(
1067 self, name: str | None = None
1068 ) -> t.Callable[[T_template_filter], T_template_filter]:
1069 """A decorator that is used to register custom template filter.
1070 You can specify a name for the filter, otherwise the function
1071 name will be used. Example::
1073 @app.template_filter()
1074 def reverse(s):
1075 return s[::-1]
1077 :param name: the optional name of the filter, otherwise the
1078 function name will be used.
1079 """
1081 def decorator(f: T_template_filter) -> T_template_filter:
1082 self.add_template_filter(f, name=name)
1083 return f
1085 return decorator
1087 @setupmethod
1088 def add_template_filter(
1089 self, f: ft.TemplateFilterCallable, name: str | None = None
1090 ) -> None:
1091 """Register a custom template filter. Works exactly like the
1092 :meth:`template_filter` decorator.
1094 :param name: the optional name of the filter, otherwise the
1095 function name will be used.
1096 """
1097 self.jinja_env.filters[name or f.__name__] = f
1099 @setupmethod
1100 def template_test(
1101 self, name: str | None = None
1102 ) -> t.Callable[[T_template_test], T_template_test]:
1103 """A decorator that is used to register custom template test.
1104 You can specify a name for the test, otherwise the function
1105 name will be used. Example::
1107 @app.template_test()
1108 def is_prime(n):
1109 if n == 2:
1110 return True
1111 for i in range(2, int(math.ceil(math.sqrt(n))) + 1):
1112 if n % i == 0:
1113 return False
1114 return True
1116 .. versionadded:: 0.10
1118 :param name: the optional name of the test, otherwise the
1119 function name will be used.
1120 """
1122 def decorator(f: T_template_test) -> T_template_test:
1123 self.add_template_test(f, name=name)
1124 return f
1126 return decorator
1128 @setupmethod
1129 def add_template_test(
1130 self, f: ft.TemplateTestCallable, name: str | None = None
1131 ) -> None:
1132 """Register a custom template test. Works exactly like the
1133 :meth:`template_test` decorator.
1135 .. versionadded:: 0.10
1137 :param name: the optional name of the test, otherwise the
1138 function name will be used.
1139 """
1140 self.jinja_env.tests[name or f.__name__] = f
1142 @setupmethod
1143 def template_global(
1144 self, name: str | None = None
1145 ) -> t.Callable[[T_template_global], T_template_global]:
1146 """A decorator that is used to register a custom template global function.
1147 You can specify a name for the global function, otherwise the function
1148 name will be used. Example::
1150 @app.template_global()
1151 def double(n):
1152 return 2 * n
1154 .. versionadded:: 0.10
1156 :param name: the optional name of the global function, otherwise the
1157 function name will be used.
1158 """
1160 def decorator(f: T_template_global) -> T_template_global:
1161 self.add_template_global(f, name=name)
1162 return f
1164 return decorator
1166 @setupmethod
1167 def add_template_global(
1168 self, f: ft.TemplateGlobalCallable, name: str | None = None
1169 ) -> None:
1170 """Register a custom template global function. Works exactly like the
1171 :meth:`template_global` decorator.
1173 .. versionadded:: 0.10
1175 :param name: the optional name of the global function, otherwise the
1176 function name will be used.
1177 """
1178 self.jinja_env.globals[name or f.__name__] = f
1180 @setupmethod
1181 def teardown_appcontext(self, f: T_teardown) -> T_teardown:
1182 """Registers a function to be called when the application
1183 context is popped. The application context is typically popped
1184 after the request context for each request, at the end of CLI
1185 commands, or after a manually pushed context ends.
1187 .. code-block:: python
1189 with app.app_context():
1190 ...
1192 When the ``with`` block exits (or ``ctx.pop()`` is called), the
1193 teardown functions are called just before the app context is
1194 made inactive. Since a request context typically also manages an
1195 application context it would also be called when you pop a
1196 request context.
1198 When a teardown function was called because of an unhandled
1199 exception it will be passed an error object. If an
1200 :meth:`errorhandler` is registered, it will handle the exception
1201 and the teardown will not receive it.
1203 Teardown functions must avoid raising exceptions. If they
1204 execute code that might fail they must surround that code with a
1205 ``try``/``except`` block and log any errors.
1207 The return values of teardown functions are ignored.
1209 .. versionadded:: 0.9
1210 """
1211 self.teardown_appcontext_funcs.append(f)
1212 return f
1214 @setupmethod
1215 def shell_context_processor(
1216 self, f: T_shell_context_processor
1217 ) -> T_shell_context_processor:
1218 """Registers a shell context processor function.
1220 .. versionadded:: 0.11
1221 """
1222 self.shell_context_processors.append(f)
1223 return f
1225 def _find_error_handler(self, e: Exception) -> ft.ErrorHandlerCallable | None:
1226 """Return a registered error handler for an exception in this order:
1227 blueprint handler for a specific code, app handler for a specific code,
1228 blueprint handler for an exception class, app handler for an exception
1229 class, or ``None`` if a suitable handler is not found.
1230 """
1231 exc_class, code = self._get_exc_class_and_code(type(e))
1232 names = (*request.blueprints, None)
1234 for c in (code, None) if code is not None else (None,):
1235 for name in names:
1236 handler_map = self.error_handler_spec[name][c]
1238 if not handler_map:
1239 continue
1241 for cls in exc_class.__mro__:
1242 handler = handler_map.get(cls)
1244 if handler is not None:
1245 return handler
1246 return None
1248 def handle_http_exception(
1249 self, e: HTTPException
1250 ) -> HTTPException | ft.ResponseReturnValue:
1251 """Handles an HTTP exception. By default this will invoke the
1252 registered error handlers and fall back to returning the
1253 exception as response.
1255 .. versionchanged:: 1.0.3
1256 ``RoutingException``, used internally for actions such as
1257 slash redirects during routing, is not passed to error
1258 handlers.
1260 .. versionchanged:: 1.0
1261 Exceptions are looked up by code *and* by MRO, so
1262 ``HTTPException`` subclasses can be handled with a catch-all
1263 handler for the base ``HTTPException``.
1265 .. versionadded:: 0.3
1266 """
1267 # Proxy exceptions don't have error codes. We want to always return
1268 # those unchanged as errors
1269 if e.code is None:
1270 return e
1272 # RoutingExceptions are used internally to trigger routing
1273 # actions, such as slash redirects raising RequestRedirect. They
1274 # are not raised or handled in user code.
1275 if isinstance(e, RoutingException):
1276 return e
1278 handler = self._find_error_handler(e)
1279 if handler is None:
1280 return e
1281 return self.ensure_sync(handler)(e)
1283 def trap_http_exception(self, e: Exception) -> bool:
1284 """Checks if an HTTP exception should be trapped or not. By default
1285 this will return ``False`` for all exceptions except for a bad request
1286 key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It
1287 also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``.
1289 This is called for all HTTP exceptions raised by a view function.
1290 If it returns ``True`` for any exception the error handler for this
1291 exception is not called and it shows up as regular exception in the
1292 traceback. This is helpful for debugging implicitly raised HTTP
1293 exceptions.
1295 .. versionchanged:: 1.0
1296 Bad request errors are not trapped by default in debug mode.
1298 .. versionadded:: 0.8
1299 """
1300 if self.config["TRAP_HTTP_EXCEPTIONS"]:
1301 return True
1303 trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"]
1305 # if unset, trap key errors in debug mode
1306 if (
1307 trap_bad_request is None
1308 and self.debug
1309 and isinstance(e, BadRequestKeyError)
1310 ):
1311 return True
1313 if trap_bad_request:
1314 return isinstance(e, BadRequest)
1316 return False
1318 def handle_user_exception(
1319 self, e: Exception
1320 ) -> HTTPException | ft.ResponseReturnValue:
1321 """This method is called whenever an exception occurs that
1322 should be handled. A special case is :class:`~werkzeug
1323 .exceptions.HTTPException` which is forwarded to the
1324 :meth:`handle_http_exception` method. This function will either
1325 return a response value or reraise the exception with the same
1326 traceback.
1328 .. versionchanged:: 1.0
1329 Key errors raised from request data like ``form`` show the
1330 bad key in debug mode rather than a generic bad request
1331 message.
1333 .. versionadded:: 0.7
1334 """
1335 if isinstance(e, BadRequestKeyError) and (
1336 self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"]
1337 ):
1338 e.show_exception = True
1340 if isinstance(e, HTTPException) and not self.trap_http_exception(e):
1341 return self.handle_http_exception(e)
1343 handler = self._find_error_handler(e)
1345 if handler is None:
1346 raise
1348 return self.ensure_sync(handler)(e)
1350 def handle_exception(self, e: Exception) -> Response:
1351 """Handle an exception that did not have an error handler
1352 associated with it, or that was raised from an error handler.
1353 This always causes a 500 ``InternalServerError``.
1355 Always sends the :data:`got_request_exception` signal.
1357 If :data:`PROPAGATE_EXCEPTIONS` is ``True``, such as in debug
1358 mode, the error will be re-raised so that the debugger can
1359 display it. Otherwise, the original exception is logged, and
1360 an :exc:`~werkzeug.exceptions.InternalServerError` is returned.
1362 If an error handler is registered for ``InternalServerError`` or
1363 ``500``, it will be used. For consistency, the handler will
1364 always receive the ``InternalServerError``. The original
1365 unhandled exception is available as ``e.original_exception``.
1367 .. versionchanged:: 1.1.0
1368 Always passes the ``InternalServerError`` instance to the
1369 handler, setting ``original_exception`` to the unhandled
1370 error.
1372 .. versionchanged:: 1.1.0
1373 ``after_request`` functions and other finalization is done
1374 even for the default 500 response when there is no handler.
1376 .. versionadded:: 0.3
1377 """
1378 exc_info = sys.exc_info()
1379 got_request_exception.send(self, _async_wrapper=self.ensure_sync, exception=e)
1380 propagate = self.config["PROPAGATE_EXCEPTIONS"]
1382 if propagate is None:
1383 propagate = self.testing or self.debug
1385 if propagate:
1386 # Re-raise if called with an active exception, otherwise
1387 # raise the passed in exception.
1388 if exc_info[1] is e:
1389 raise
1391 raise e
1393 self.log_exception(exc_info)
1394 server_error: InternalServerError | ft.ResponseReturnValue
1395 server_error = InternalServerError(original_exception=e)
1396 handler = self._find_error_handler(server_error)
1398 if handler is not None:
1399 server_error = self.ensure_sync(handler)(server_error)
1401 return self.finalize_request(server_error, from_error_handler=True)
1403 def log_exception(
1404 self,
1405 exc_info: (tuple[type, BaseException, TracebackType] | tuple[None, None, None]),
1406 ) -> None:
1407 """Logs an exception. This is called by :meth:`handle_exception`
1408 if debugging is disabled and right before the handler is called.
1409 The default implementation logs the exception as error on the
1410 :attr:`logger`.
1412 .. versionadded:: 0.8
1413 """
1414 self.logger.error(
1415 f"Exception on {request.path} [{request.method}]", exc_info=exc_info
1416 )
1418 def raise_routing_exception(self, request: Request) -> t.NoReturn:
1419 """Intercept routing exceptions and possibly do something else.
1421 In debug mode, intercept a routing redirect and replace it with
1422 an error if the body will be discarded.
1424 With modern Werkzeug this shouldn't occur, since it now uses a
1425 308 status which tells the browser to resend the method and
1426 body.
1428 .. versionchanged:: 2.1
1429 Don't intercept 307 and 308 redirects.
1431 :meta private:
1432 :internal:
1433 """
1434 if (
1435 not self.debug
1436 or not isinstance(request.routing_exception, RequestRedirect)
1437 or request.routing_exception.code in {307, 308}
1438 or request.method in {"GET", "HEAD", "OPTIONS"}
1439 ):
1440 raise request.routing_exception # type: ignore
1442 from .debughelpers import FormDataRoutingRedirect
1444 raise FormDataRoutingRedirect(request)
1446 def dispatch_request(self) -> ft.ResponseReturnValue:
1447 """Does the request dispatching. Matches the URL and returns the
1448 return value of the view or error handler. This does not have to
1449 be a response object. In order to convert the return value to a
1450 proper response object, call :func:`make_response`.
1452 .. versionchanged:: 0.7
1453 This no longer does the exception handling, this code was
1454 moved to the new :meth:`full_dispatch_request`.
1455 """
1456 req = request_ctx.request
1457 if req.routing_exception is not None:
1458 self.raise_routing_exception(req)
1459 rule: Rule = req.url_rule # type: ignore[assignment]
1460 # if we provide automatic options for this URL and the
1461 # request came with the OPTIONS method, reply automatically
1462 if (
1463 getattr(rule, "provide_automatic_options", False)
1464 and req.method == "OPTIONS"
1465 ):
1466 return self.make_default_options_response()
1467 # otherwise dispatch to the handler for that endpoint
1468 view_args: dict[str, t.Any] = req.view_args # type: ignore[assignment]
1469 return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
1471 def full_dispatch_request(self) -> Response:
1472 """Dispatches the request and on top of that performs request
1473 pre and postprocessing as well as HTTP exception catching and
1474 error handling.
1476 .. versionadded:: 0.7
1477 """
1478 self._got_first_request = True
1480 try:
1481 request_started.send(self, _async_wrapper=self.ensure_sync)
1482 rv = self.preprocess_request()
1483 if rv is None:
1484 rv = self.dispatch_request()
1485 except Exception as e:
1486 rv = self.handle_user_exception(e)
1487 return self.finalize_request(rv)
1489 def finalize_request(
1490 self,
1491 rv: ft.ResponseReturnValue | HTTPException,
1492 from_error_handler: bool = False,
1493 ) -> Response:
1494 """Given the return value from a view function this finalizes
1495 the request by converting it into a response and invoking the
1496 postprocessing functions. This is invoked for both normal
1497 request dispatching as well as error handlers.
1499 Because this means that it might be called as a result of a
1500 failure a special safe mode is available which can be enabled
1501 with the `from_error_handler` flag. If enabled, failures in
1502 response processing will be logged and otherwise ignored.
1504 :internal:
1505 """
1506 response = self.make_response(rv)
1507 try:
1508 response = self.process_response(response)
1509 request_finished.send(
1510 self, _async_wrapper=self.ensure_sync, response=response
1511 )
1512 except Exception:
1513 if not from_error_handler:
1514 raise
1515 self.logger.exception(
1516 "Request finalizing failed with an error while handling an error"
1517 )
1518 return response
1520 def make_default_options_response(self) -> Response:
1521 """This method is called to create the default ``OPTIONS`` response.
1522 This can be changed through subclassing to change the default
1523 behavior of ``OPTIONS`` responses.
1525 .. versionadded:: 0.7
1526 """
1527 adapter = request_ctx.url_adapter
1528 methods = adapter.allowed_methods() # type: ignore[union-attr]
1529 rv = self.response_class()
1530 rv.allow.update(methods)
1531 return rv
1533 def should_ignore_error(self, error: BaseException | None) -> bool:
1534 """This is called to figure out if an error should be ignored
1535 or not as far as the teardown system is concerned. If this
1536 function returns ``True`` then the teardown handlers will not be
1537 passed the error.
1539 .. versionadded:: 0.10
1540 """
1541 return False
1543 def ensure_sync(self, func: t.Callable) -> t.Callable:
1544 """Ensure that the function is synchronous for WSGI workers.
1545 Plain ``def`` functions are returned as-is. ``async def``
1546 functions are wrapped to run and wait for the response.
1548 Override this method to change how the app runs async views.
1550 .. versionadded:: 2.0
1551 """
1552 if iscoroutinefunction(func):
1553 return self.async_to_sync(func)
1555 return func
1557 def async_to_sync(
1558 self, func: t.Callable[..., t.Coroutine]
1559 ) -> t.Callable[..., t.Any]:
1560 """Return a sync function that will run the coroutine function.
1562 .. code-block:: python
1564 result = app.async_to_sync(func)(*args, **kwargs)
1566 Override this method to change how the app converts async code
1567 to be synchronously callable.
1569 .. versionadded:: 2.0
1570 """
1571 try:
1572 from asgiref.sync import async_to_sync as asgiref_async_to_sync
1573 except ImportError:
1574 raise RuntimeError(
1575 "Install Flask with the 'async' extra in order to use async views."
1576 ) from None
1578 return asgiref_async_to_sync(func)
1580 def url_for(
1581 self,
1582 endpoint: str,
1583 *,
1584 _anchor: str | None = None,
1585 _method: str | None = None,
1586 _scheme: str | None = None,
1587 _external: bool | None = None,
1588 **values: t.Any,
1589 ) -> str:
1590 """Generate a URL to the given endpoint with the given values.
1592 This is called by :func:`flask.url_for`, and can be called
1593 directly as well.
1595 An *endpoint* is the name of a URL rule, usually added with
1596 :meth:`@app.route() <route>`, and usually the same name as the
1597 view function. A route defined in a :class:`~flask.Blueprint`
1598 will prepend the blueprint's name separated by a ``.`` to the
1599 endpoint.
1601 In some cases, such as email messages, you want URLs to include
1602 the scheme and domain, like ``https://example.com/hello``. When
1603 not in an active request, URLs will be external by default, but
1604 this requires setting :data:`SERVER_NAME` so Flask knows what
1605 domain to use. :data:`APPLICATION_ROOT` and
1606 :data:`PREFERRED_URL_SCHEME` should also be configured as
1607 needed. This config is only used when not in an active request.
1609 Functions can be decorated with :meth:`url_defaults` to modify
1610 keyword arguments before the URL is built.
1612 If building fails for some reason, such as an unknown endpoint
1613 or incorrect values, the app's :meth:`handle_url_build_error`
1614 method is called. If that returns a string, that is returned,
1615 otherwise a :exc:`~werkzeug.routing.BuildError` is raised.
1617 :param endpoint: The endpoint name associated with the URL to
1618 generate. If this starts with a ``.``, the current blueprint
1619 name (if any) will be used.
1620 :param _anchor: If given, append this as ``#anchor`` to the URL.
1621 :param _method: If given, generate the URL associated with this
1622 method for the endpoint.
1623 :param _scheme: If given, the URL will have this scheme if it
1624 is external.
1625 :param _external: If given, prefer the URL to be internal
1626 (False) or require it to be external (True). External URLs
1627 include the scheme and domain. When not in an active
1628 request, URLs are external by default.
1629 :param values: Values to use for the variable parts of the URL
1630 rule. Unknown keys are appended as query string arguments,
1631 like ``?a=b&c=d``.
1633 .. versionadded:: 2.2
1634 Moved from ``flask.url_for``, which calls this method.
1635 """
1636 req_ctx = _cv_request.get(None)
1638 if req_ctx is not None:
1639 url_adapter = req_ctx.url_adapter
1640 blueprint_name = req_ctx.request.blueprint
1642 # If the endpoint starts with "." and the request matches a
1643 # blueprint, the endpoint is relative to the blueprint.
1644 if endpoint[:1] == ".":
1645 if blueprint_name is not None:
1646 endpoint = f"{blueprint_name}{endpoint}"
1647 else:
1648 endpoint = endpoint[1:]
1650 # When in a request, generate a URL without scheme and
1651 # domain by default, unless a scheme is given.
1652 if _external is None:
1653 _external = _scheme is not None
1654 else:
1655 app_ctx = _cv_app.get(None)
1657 # If called by helpers.url_for, an app context is active,
1658 # use its url_adapter. Otherwise, app.url_for was called
1659 # directly, build an adapter.
1660 if app_ctx is not None:
1661 url_adapter = app_ctx.url_adapter
1662 else:
1663 url_adapter = self.create_url_adapter(None)
1665 if url_adapter is None:
1666 raise RuntimeError(
1667 "Unable to build URLs outside an active request"
1668 " without 'SERVER_NAME' configured. Also configure"
1669 " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as"
1670 " needed."
1671 )
1673 # When outside a request, generate a URL with scheme and
1674 # domain by default.
1675 if _external is None:
1676 _external = True
1678 # It is an error to set _scheme when _external=False, in order
1679 # to avoid accidental insecure URLs.
1680 if _scheme is not None and not _external:
1681 raise ValueError("When specifying '_scheme', '_external' must be True.")
1683 self.inject_url_defaults(endpoint, values)
1685 try:
1686 rv = url_adapter.build( # type: ignore[union-attr]
1687 endpoint,
1688 values,
1689 method=_method,
1690 url_scheme=_scheme,
1691 force_external=_external,
1692 )
1693 except BuildError as error:
1694 values.update(
1695 _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external
1696 )
1697 return self.handle_url_build_error(error, endpoint, values)
1699 if _anchor is not None:
1700 _anchor = _url_quote(_anchor, safe="%!#$&'()*+,/:;=?@")
1701 rv = f"{rv}#{_anchor}"
1703 return rv
1705 def redirect(self, location: str, code: int = 302) -> BaseResponse:
1706 """Create a redirect response object.
1708 This is called by :func:`flask.redirect`, and can be called
1709 directly as well.
1711 :param location: The URL to redirect to.
1712 :param code: The status code for the redirect.
1714 .. versionadded:: 2.2
1715 Moved from ``flask.redirect``, which calls this method.
1716 """
1717 return _wz_redirect(location, code=code, Response=self.response_class)
1719 def make_response(self, rv: ft.ResponseReturnValue) -> Response:
1720 """Convert the return value from a view function to an instance of
1721 :attr:`response_class`.
1723 :param rv: the return value from the view function. The view function
1724 must return a response. Returning ``None``, or the view ending
1725 without returning, is not allowed. The following types are allowed
1726 for ``view_rv``:
1728 ``str``
1729 A response object is created with the string encoded to UTF-8
1730 as the body.
1732 ``bytes``
1733 A response object is created with the bytes as the body.
1735 ``dict``
1736 A dictionary that will be jsonify'd before being returned.
1738 ``list``
1739 A list that will be jsonify'd before being returned.
1741 ``generator`` or ``iterator``
1742 A generator that returns ``str`` or ``bytes`` to be
1743 streamed as the response.
1745 ``tuple``
1746 Either ``(body, status, headers)``, ``(body, status)``, or
1747 ``(body, headers)``, where ``body`` is any of the other types
1748 allowed here, ``status`` is a string or an integer, and
1749 ``headers`` is a dictionary or a list of ``(key, value)``
1750 tuples. If ``body`` is a :attr:`response_class` instance,
1751 ``status`` overwrites the exiting value and ``headers`` are
1752 extended.
1754 :attr:`response_class`
1755 The object is returned unchanged.
1757 other :class:`~werkzeug.wrappers.Response` class
1758 The object is coerced to :attr:`response_class`.
1760 :func:`callable`
1761 The function is called as a WSGI application. The result is
1762 used to create a response object.
1764 .. versionchanged:: 2.2
1765 A generator will be converted to a streaming response.
1766 A list will be converted to a JSON response.
1768 .. versionchanged:: 1.1
1769 A dict will be converted to a JSON response.
1771 .. versionchanged:: 0.9
1772 Previously a tuple was interpreted as the arguments for the
1773 response object.
1774 """
1776 status = headers = None
1778 # unpack tuple returns
1779 if isinstance(rv, tuple):
1780 len_rv = len(rv)
1782 # a 3-tuple is unpacked directly
1783 if len_rv == 3:
1784 rv, status, headers = rv # type: ignore[misc]
1785 # decide if a 2-tuple has status or headers
1786 elif len_rv == 2:
1787 if isinstance(rv[1], (Headers, dict, tuple, list)):
1788 rv, headers = rv
1789 else:
1790 rv, status = rv # type: ignore[assignment,misc]
1791 # other sized tuples are not allowed
1792 else:
1793 raise TypeError(
1794 "The view function did not return a valid response tuple."
1795 " The tuple must have the form (body, status, headers),"
1796 " (body, status), or (body, headers)."
1797 )
1799 # the body must not be None
1800 if rv is None:
1801 raise TypeError(
1802 f"The view function for {request.endpoint!r} did not"
1803 " return a valid response. The function either returned"
1804 " None or ended without a return statement."
1805 )
1807 # make sure the body is an instance of the response class
1808 if not isinstance(rv, self.response_class):
1809 if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, _abc_Iterator):
1810 # let the response class set the status and headers instead of
1811 # waiting to do it manually, so that the class can handle any
1812 # special logic
1813 rv = self.response_class(
1814 rv,
1815 status=status,
1816 headers=headers, # type: ignore[arg-type]
1817 )
1818 status = headers = None
1819 elif isinstance(rv, (dict, list)):
1820 rv = self.json.response(rv)
1821 elif isinstance(rv, BaseResponse) or callable(rv):
1822 # evaluate a WSGI callable, or coerce a different response
1823 # class to the correct type
1824 try:
1825 rv = self.response_class.force_type(
1826 rv, request.environ # type: ignore[arg-type]
1827 )
1828 except TypeError as e:
1829 raise TypeError(
1830 f"{e}\nThe view function did not return a valid"
1831 " response. The return type must be a string,"
1832 " dict, list, tuple with headers or status,"
1833 " Response instance, or WSGI callable, but it"
1834 f" was a {type(rv).__name__}."
1835 ).with_traceback(sys.exc_info()[2]) from None
1836 else:
1837 raise TypeError(
1838 "The view function did not return a valid"
1839 " response. The return type must be a string,"
1840 " dict, list, tuple with headers or status,"
1841 " Response instance, or WSGI callable, but it was a"
1842 f" {type(rv).__name__}."
1843 )
1845 rv = t.cast(Response, rv)
1846 # prefer the status if it was provided
1847 if status is not None:
1848 if isinstance(status, (str, bytes, bytearray)):
1849 rv.status = status
1850 else:
1851 rv.status_code = status
1853 # extend existing headers with provided headers
1854 if headers:
1855 rv.headers.update(headers) # type: ignore[arg-type]
1857 return rv
1859 def create_url_adapter(self, request: Request | None) -> MapAdapter | None:
1860 """Creates a URL adapter for the given request. The URL adapter
1861 is created at a point where the request context is not yet set
1862 up so the request is passed explicitly.
1864 .. versionadded:: 0.6
1866 .. versionchanged:: 0.9
1867 This can now also be called without a request object when the
1868 URL adapter is created for the application context.
1870 .. versionchanged:: 1.0
1871 :data:`SERVER_NAME` no longer implicitly enables subdomain
1872 matching. Use :attr:`subdomain_matching` instead.
1873 """
1874 if request is not None:
1875 # If subdomain matching is disabled (the default), use the
1876 # default subdomain in all cases. This should be the default
1877 # in Werkzeug but it currently does not have that feature.
1878 if not self.subdomain_matching:
1879 subdomain = self.url_map.default_subdomain or None
1880 else:
1881 subdomain = None
1883 return self.url_map.bind_to_environ(
1884 request.environ,
1885 server_name=self.config["SERVER_NAME"],
1886 subdomain=subdomain,
1887 )
1888 # We need at the very least the server name to be set for this
1889 # to work.
1890 if self.config["SERVER_NAME"] is not None:
1891 return self.url_map.bind(
1892 self.config["SERVER_NAME"],
1893 script_name=self.config["APPLICATION_ROOT"],
1894 url_scheme=self.config["PREFERRED_URL_SCHEME"],
1895 )
1897 return None
1899 def inject_url_defaults(self, endpoint: str, values: dict) -> None:
1900 """Injects the URL defaults for the given endpoint directly into
1901 the values dictionary passed. This is used internally and
1902 automatically called on URL building.
1904 .. versionadded:: 0.7
1905 """
1906 names: t.Iterable[str | None] = (None,)
1908 # url_for may be called outside a request context, parse the
1909 # passed endpoint instead of using request.blueprints.
1910 if "." in endpoint:
1911 names = chain(
1912 names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0]))
1913 )
1915 for name in names:
1916 if name in self.url_default_functions:
1917 for func in self.url_default_functions[name]:
1918 func(endpoint, values)
1920 def handle_url_build_error(
1921 self, error: BuildError, endpoint: str, values: dict[str, t.Any]
1922 ) -> str:
1923 """Called by :meth:`.url_for` if a
1924 :exc:`~werkzeug.routing.BuildError` was raised. If this returns
1925 a value, it will be returned by ``url_for``, otherwise the error
1926 will be re-raised.
1928 Each function in :attr:`url_build_error_handlers` is called with
1929 ``error``, ``endpoint`` and ``values``. If a function returns
1930 ``None`` or raises a ``BuildError``, it is skipped. Otherwise,
1931 its return value is returned by ``url_for``.
1933 :param error: The active ``BuildError`` being handled.
1934 :param endpoint: The endpoint being built.
1935 :param values: The keyword arguments passed to ``url_for``.
1936 """
1937 for handler in self.url_build_error_handlers:
1938 try:
1939 rv = handler(error, endpoint, values)
1940 except BuildError as e:
1941 # make error available outside except block
1942 error = e
1943 else:
1944 if rv is not None:
1945 return rv
1947 # Re-raise if called with an active exception, otherwise raise
1948 # the passed in exception.
1949 if error is sys.exc_info()[1]:
1950 raise
1952 raise error
1954 def preprocess_request(self) -> ft.ResponseReturnValue | None:
1955 """Called before the request is dispatched. Calls
1956 :attr:`url_value_preprocessors` registered with the app and the
1957 current blueprint (if any). Then calls :attr:`before_request_funcs`
1958 registered with the app and the blueprint.
1960 If any :meth:`before_request` handler returns a non-None value, the
1961 value is handled as if it was the return value from the view, and
1962 further request handling is stopped.
1963 """
1964 names = (None, *reversed(request.blueprints))
1966 for name in names:
1967 if name in self.url_value_preprocessors:
1968 for url_func in self.url_value_preprocessors[name]:
1969 url_func(request.endpoint, request.view_args)
1971 for name in names:
1972 if name in self.before_request_funcs:
1973 for before_func in self.before_request_funcs[name]:
1974 rv = self.ensure_sync(before_func)()
1976 if rv is not None:
1977 return rv
1979 return None
1981 def process_response(self, response: Response) -> Response:
1982 """Can be overridden in order to modify the response object
1983 before it's sent to the WSGI server. By default this will
1984 call all the :meth:`after_request` decorated functions.
1986 .. versionchanged:: 0.5
1987 As of Flask 0.5 the functions registered for after request
1988 execution are called in reverse order of registration.
1990 :param response: a :attr:`response_class` object.
1991 :return: a new response object or the same, has to be an
1992 instance of :attr:`response_class`.
1993 """
1994 ctx = request_ctx._get_current_object() # type: ignore[attr-defined]
1996 for func in ctx._after_request_functions:
1997 response = self.ensure_sync(func)(response)
1999 for name in chain(request.blueprints, (None,)):
2000 if name in self.after_request_funcs:
2001 for func in reversed(self.after_request_funcs[name]):
2002 response = self.ensure_sync(func)(response)
2004 if not self.session_interface.is_null_session(ctx.session):
2005 self.session_interface.save_session(self, ctx.session, response)
2007 return response
2009 def do_teardown_request(
2010 self, exc: BaseException | None = _sentinel # type: ignore
2011 ) -> None:
2012 """Called after the request is dispatched and the response is
2013 returned, right before the request context is popped.
2015 This calls all functions decorated with
2016 :meth:`teardown_request`, and :meth:`Blueprint.teardown_request`
2017 if a blueprint handled the request. Finally, the
2018 :data:`request_tearing_down` signal is sent.
2020 This is called by
2021 :meth:`RequestContext.pop() <flask.ctx.RequestContext.pop>`,
2022 which may be delayed during testing to maintain access to
2023 resources.
2025 :param exc: An unhandled exception raised while dispatching the
2026 request. Detected from the current exception information if
2027 not passed. Passed to each teardown function.
2029 .. versionchanged:: 0.9
2030 Added the ``exc`` argument.
2031 """
2032 if exc is _sentinel:
2033 exc = sys.exc_info()[1]
2035 for name in chain(request.blueprints, (None,)):
2036 if name in self.teardown_request_funcs:
2037 for func in reversed(self.teardown_request_funcs[name]):
2038 self.ensure_sync(func)(exc)
2040 request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
2042 def do_teardown_appcontext(
2043 self, exc: BaseException | None = _sentinel # type: ignore
2044 ) -> None:
2045 """Called right before the application context is popped.
2047 When handling a request, the application context is popped
2048 after the request context. See :meth:`do_teardown_request`.
2050 This calls all functions decorated with
2051 :meth:`teardown_appcontext`. Then the
2052 :data:`appcontext_tearing_down` signal is sent.
2054 This is called by
2055 :meth:`AppContext.pop() <flask.ctx.AppContext.pop>`.
2057 .. versionadded:: 0.9
2058 """
2059 if exc is _sentinel:
2060 exc = sys.exc_info()[1]
2062 for func in reversed(self.teardown_appcontext_funcs):
2063 self.ensure_sync(func)(exc)
2065 appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc)
2067 def app_context(self) -> AppContext:
2068 """Create an :class:`~flask.ctx.AppContext`. Use as a ``with``
2069 block to push the context, which will make :data:`current_app`
2070 point at this application.
2072 An application context is automatically pushed by
2073 :meth:`RequestContext.push() <flask.ctx.RequestContext.push>`
2074 when handling a request, and when running a CLI command. Use
2075 this to manually create a context outside of these situations.
2077 ::
2079 with app.app_context():
2080 init_db()
2082 See :doc:`/appcontext`.
2084 .. versionadded:: 0.9
2085 """
2086 return AppContext(self)
2088 def request_context(self, environ: dict) -> RequestContext:
2089 """Create a :class:`~flask.ctx.RequestContext` representing a
2090 WSGI environment. Use a ``with`` block to push the context,
2091 which will make :data:`request` point at this request.
2093 See :doc:`/reqcontext`.
2095 Typically you should not call this from your own code. A request
2096 context is automatically pushed by the :meth:`wsgi_app` when
2097 handling a request. Use :meth:`test_request_context` to create
2098 an environment and context instead of this method.
2100 :param environ: a WSGI environment
2101 """
2102 return RequestContext(self, environ)
2104 def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext:
2105 """Create a :class:`~flask.ctx.RequestContext` for a WSGI
2106 environment created from the given values. This is mostly useful
2107 during testing, where you may want to run a function that uses
2108 request data without dispatching a full request.
2110 See :doc:`/reqcontext`.
2112 Use a ``with`` block to push the context, which will make
2113 :data:`request` point at the request for the created
2114 environment. ::
2116 with app.test_request_context(...):
2117 generate_report()
2119 When using the shell, it may be easier to push and pop the
2120 context manually to avoid indentation. ::
2122 ctx = app.test_request_context(...)
2123 ctx.push()
2124 ...
2125 ctx.pop()
2127 Takes the same arguments as Werkzeug's
2128 :class:`~werkzeug.test.EnvironBuilder`, with some defaults from
2129 the application. See the linked Werkzeug docs for most of the
2130 available arguments. Flask-specific behavior is listed here.
2132 :param path: URL path being requested.
2133 :param base_url: Base URL where the app is being served, which
2134 ``path`` is relative to. If not given, built from
2135 :data:`PREFERRED_URL_SCHEME`, ``subdomain``,
2136 :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`.
2137 :param subdomain: Subdomain name to append to
2138 :data:`SERVER_NAME`.
2139 :param url_scheme: Scheme to use instead of
2140 :data:`PREFERRED_URL_SCHEME`.
2141 :param data: The request body, either as a string or a dict of
2142 form keys and values.
2143 :param json: If given, this is serialized as JSON and passed as
2144 ``data``. Also defaults ``content_type`` to
2145 ``application/json``.
2146 :param args: other positional arguments passed to
2147 :class:`~werkzeug.test.EnvironBuilder`.
2148 :param kwargs: other keyword arguments passed to
2149 :class:`~werkzeug.test.EnvironBuilder`.
2150 """
2151 from .testing import EnvironBuilder
2153 builder = EnvironBuilder(self, *args, **kwargs)
2155 try:
2156 return self.request_context(builder.get_environ())
2157 finally:
2158 builder.close()
2160 def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any:
2161 """The actual WSGI application. This is not implemented in
2162 :meth:`__call__` so that middlewares can be applied without
2163 losing a reference to the app object. Instead of doing this::
2165 app = MyMiddleware(app)
2167 It's a better idea to do this instead::
2169 app.wsgi_app = MyMiddleware(app.wsgi_app)
2171 Then you still have the original application object around and
2172 can continue to call methods on it.
2174 .. versionchanged:: 0.7
2175 Teardown events for the request and app contexts are called
2176 even if an unhandled error occurs. Other events may not be
2177 called depending on when an error occurs during dispatch.
2178 See :ref:`callbacks-and-errors`.
2180 :param environ: A WSGI environment.
2181 :param start_response: A callable accepting a status code,
2182 a list of headers, and an optional exception context to
2183 start the response.
2184 """
2185 ctx = self.request_context(environ)
2186 error: BaseException | None = None
2187 try:
2188 try:
2189 ctx.push()
2190 response = self.full_dispatch_request()
2191 except Exception as e:
2192 error = e
2193 response = self.handle_exception(e)
2194 except: # noqa: B001
2195 error = sys.exc_info()[1]
2196 raise
2197 return response(environ, start_response)
2198 finally:
2199 if "werkzeug.debug.preserve_context" in environ:
2200 environ["werkzeug.debug.preserve_context"](_cv_app.get())
2201 environ["werkzeug.debug.preserve_context"](_cv_request.get())
2203 if error is not None and self.should_ignore_error(error):
2204 error = None
2206 ctx.pop(error)
2208 def __call__(self, environ: dict, start_response: t.Callable) -> t.Any:
2209 """The WSGI server calls the Flask application object as the
2210 WSGI application. This calls :meth:`wsgi_app`, which can be
2211 wrapped to apply middleware.
2212 """
2213 return self.wsgi_app(environ, start_response)