wrappers.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. # -*- coding: utf-8 -*-
  2. """
  3. flask.wrappers
  4. ~~~~~~~~~~~~~~
  5. Implements the WSGI wrappers (request and response).
  6. :copyright: 2010 Pallets
  7. :license: BSD-3-Clause
  8. """
  9. from werkzeug.exceptions import BadRequest
  10. from werkzeug.wrappers import Request as RequestBase
  11. from werkzeug.wrappers import Response as ResponseBase
  12. from werkzeug.wrappers.json import JSONMixin as _JSONMixin
  13. from . import json
  14. from .globals import current_app
  15. class JSONMixin(_JSONMixin):
  16. json_module = json
  17. def on_json_loading_failed(self, e):
  18. if current_app and current_app.debug:
  19. raise BadRequest("Failed to decode JSON object: {0}".format(e))
  20. raise BadRequest()
  21. class Request(RequestBase, JSONMixin):
  22. """The request object used by default in Flask. Remembers the
  23. matched endpoint and view arguments.
  24. It is what ends up as :class:`~flask.request`. If you want to replace
  25. the request object used you can subclass this and set
  26. :attr:`~flask.Flask.request_class` to your subclass.
  27. The request object is a :class:`~werkzeug.wrappers.Request` subclass and
  28. provides all of the attributes Werkzeug defines plus a few Flask
  29. specific ones.
  30. """
  31. #: The internal URL rule that matched the request. This can be
  32. #: useful to inspect which methods are allowed for the URL from
  33. #: a before/after handler (``request.url_rule.methods``) etc.
  34. #: Though if the request's method was invalid for the URL rule,
  35. #: the valid list is available in ``routing_exception.valid_methods``
  36. #: instead (an attribute of the Werkzeug exception
  37. #: :exc:`~werkzeug.exceptions.MethodNotAllowed`)
  38. #: because the request was never internally bound.
  39. #:
  40. #: .. versionadded:: 0.6
  41. url_rule = None
  42. #: A dict of view arguments that matched the request. If an exception
  43. #: happened when matching, this will be ``None``.
  44. view_args = None
  45. #: If matching the URL failed, this is the exception that will be
  46. #: raised / was raised as part of the request handling. This is
  47. #: usually a :exc:`~werkzeug.exceptions.NotFound` exception or
  48. #: something similar.
  49. routing_exception = None
  50. @property
  51. def max_content_length(self):
  52. """Read-only view of the ``MAX_CONTENT_LENGTH`` config key."""
  53. if current_app:
  54. return current_app.config["MAX_CONTENT_LENGTH"]
  55. @property
  56. def endpoint(self):
  57. """The endpoint that matched the request. This in combination with
  58. :attr:`view_args` can be used to reconstruct the same or a
  59. modified URL. If an exception happened when matching, this will
  60. be ``None``.
  61. """
  62. if self.url_rule is not None:
  63. return self.url_rule.endpoint
  64. @property
  65. def blueprint(self):
  66. """The name of the current blueprint"""
  67. if self.url_rule and "." in self.url_rule.endpoint:
  68. return self.url_rule.endpoint.rsplit(".", 1)[0]
  69. def _load_form_data(self):
  70. RequestBase._load_form_data(self)
  71. # In debug mode we're replacing the files multidict with an ad-hoc
  72. # subclass that raises a different error for key errors.
  73. if (
  74. current_app
  75. and current_app.debug
  76. and self.mimetype != "multipart/form-data"
  77. and not self.files
  78. ):
  79. from .debughelpers import attach_enctype_error_multidict
  80. attach_enctype_error_multidict(self)
  81. class Response(ResponseBase, JSONMixin):
  82. """The response object that is used by default in Flask. Works like the
  83. response object from Werkzeug but is set to have an HTML mimetype by
  84. default. Quite often you don't have to create this object yourself because
  85. :meth:`~flask.Flask.make_response` will take care of that for you.
  86. If you want to replace the response object used you can subclass this and
  87. set :attr:`~flask.Flask.response_class` to your subclass.
  88. .. versionchanged:: 1.0
  89. JSON support is added to the response, like the request. This is useful
  90. when testing to get the test client response data as JSON.
  91. .. versionchanged:: 1.0
  92. Added :attr:`max_cookie_size`.
  93. """
  94. default_mimetype = "text/html"
  95. def _get_data_for_json(self, cache):
  96. return self.get_data()
  97. @property
  98. def max_cookie_size(self):
  99. """Read-only view of the :data:`MAX_COOKIE_SIZE` config key.
  100. See :attr:`~werkzeug.wrappers.BaseResponse.max_cookie_size` in
  101. Werkzeug's docs.
  102. """
  103. if current_app:
  104. return current_app.config["MAX_COOKIE_SIZE"]
  105. # return Werkzeug's default when not in an app context
  106. return super(Response, self).max_cookie_size