1from __future__ import annotations
2
3import collections.abc as cabc
4import json
5import typing as t
6import wsgiref.types as wt
7from http import HTTPStatus
8from types import TracebackType
9from urllib.parse import urljoin
10
11from ..datastructures.headers import Headers
12from ..http import _generate_etag
13from ..sansio.response import Response as _SansIOResponse
14from ..urls import iri_to_uri
15from ..utils import cached_property
16from ..wsgi import _RangeWrapper
17from ..wsgi import ClosingIterator
18
19if t.TYPE_CHECKING:
20 from .request import Request
21
22
23def _iter_encoded(iterable: cabc.Iterable[str | bytes]) -> cabc.Iterator[bytes]:
24 has_str = False
25 has_bytes = False
26 warned = False
27
28 for item in iterable:
29 if isinstance(item, str):
30 has_str = True
31 yield item.encode()
32 else:
33 has_bytes = True
34 yield item
35
36 if has_str and has_bytes and not warned:
37 import warnings
38
39 warned = True
40 warnings.warn(
41 "The response iterable must contain only bytes or only strings,"
42 " not both. Support for mixed types is deprecated and will be"
43 " removed in Werkzeug 4.0.",
44 DeprecationWarning,
45 stacklevel=2,
46 )
47
48
49class Response(_SansIOResponse):
50 """Represents an outgoing WSGI HTTP response with body, status, and
51 headers. Has properties and methods for using the functionality
52 defined by various HTTP specs.
53
54 The response body is flexible to support different use cases. The
55 simple form is passing bytes, or a string which will be encoded as
56 UTF-8. Passing an iterable of bytes or strings makes this a
57 streaming response. A generator is particularly useful for building
58 a CSV file in memory or using SSE (Server Sent Events). A file-like
59 object is also iterable, although the
60 :func:`~werkzeug.utils.send_file` helper should be used in that
61 case.
62
63 The response object is itself a WSGI application callable. When
64 called (:meth:`__call__`) with ``environ`` and ``start_response``,
65 it will pass its status and headers to ``start_response`` then
66 return its body as an iterable.
67
68 .. code-block:: python
69
70 from werkzeug.wrappers.response import Response
71
72 def index():
73 return Response("Hello, World!")
74
75 def application(environ, start_response):
76 path = environ.get("PATH_INFO") or "/"
77
78 if path == "/":
79 response = index()
80 else:
81 response = Response("Not Found", status=404)
82
83 return response(environ, start_response)
84
85 :param response: The data for the body of the response. A string or
86 bytes, or tuple or list of strings or bytes, for a fixed-length
87 response, or any other iterable of strings or bytes for a
88 streaming response. Defaults to an empty body.
89 :param status: The status code for the response. Either an int, in
90 which case the default status message is added, or a string in
91 the form ``{code} {message}``, like ``404 Not Found``. Defaults
92 to 200.
93 :param headers: A :class:`~werkzeug.datastructures.Headers` object,
94 or a list of ``(key, value)`` tuples that will be converted to a
95 ``Headers`` object.
96 :param mimetype: The mime type (content type without charset or
97 other parameters) of the response. If the value starts with
98 ``text/`` (or matches some other special cases), the charset
99 will be added to create the ``content_type``.
100 :param content_type: The full content type of the response.
101 Overrides building the value from ``mimetype``.
102 :param direct_passthrough: Pass the response body directly through
103 as the WSGI iterable. This can be used when the body is a binary
104 file or other iterator of bytes, to skip some unnecessary
105 checks. Use :func:`~werkzeug.utils.send_file` instead of setting
106 this manually.
107
108 .. versionchanged:: 2.1
109 Old ``BaseResponse`` and mixin classes were removed.
110
111 .. versionchanged:: 2.0
112 Combine ``BaseResponse`` and mixins into a single ``Response``
113 class.
114
115 .. versionchanged:: 0.5
116 The ``direct_passthrough`` parameter was added.
117 """
118
119 implicit_sequence_conversion = True
120 """Set to ``False`` to disable places where an arbitrary :attr:`response`
121 iterable would be automatically converted into a fixed-length sequence. In
122 that case, a ``RuntimeError`` will be raised unless ``response`` is already
123 a sequence.
124
125 .. versionchanged:: 0.6.2
126 Renamed from the typo ``implicit_seqence_conversion``.
127 """
128
129 #: If a redirect ``Location`` header is a relative URL, make it an
130 #: absolute URL, including scheme and domain.
131 #:
132 #: .. deprecated:: 3.2
133 #: Will be removed in Werkzeug 4.0. Set ``response.location`` directly
134 #: if a specific format is needed.
135 #:
136 #: .. versionchanged:: 2.1
137 #: This is disabled by default, so responses will send relative
138 #: redirects.
139 #:
140 #: .. versionadded:: 0.8
141 autocorrect_location_header: None = None
142
143 automatically_set_content_length = None
144 """Set to ``False`` to disable automatically calculating and setting
145 :attr:`content_length` in certain places. It can be set automatically when
146 the :attr:`response` iterable is a fixed-length sequence.
147
148 .. deprecated:: 3.2
149 Will be removed in Werkzeug 4.0. Set ``response`` to a non-sequence
150 iterable to indicate that the content length should not be set.
151
152 .. versionadded:: 0.8
153 """
154
155 @property
156 def _auto_length(self) -> bool:
157 if self.automatically_set_content_length is None:
158 return True
159
160 import warnings
161
162 warnings.warn(
163 "The 'automatically_set_content_length' attribute is deprecated and"
164 " will be removed in Werkzeug 4.0. Set 'response' to a non-sequence"
165 " iterable to indicate that the content length should not be set.",
166 DeprecationWarning,
167 stacklevel=2,
168 )
169 return self.automatically_set_content_length
170
171 response: t.Iterable[str] | t.Iterable[bytes]
172 """The response body to send as the WSGI iterable. A sequence with ``len``
173 is a fixed-length response, any other iterable is a streaming response.
174
175 This should contain bytes. For convenience, it can also be strings, which
176 will be encoded as UTF-8. If you know the body is bytes, set
177 :attr:`direct_passthrough` to avoid some overhead.
178
179 Use :meth:`set_data` rather than modifying this directly in most cases.
180
181 Do not set this to a plain string or bytes. That would be very inefficient,
182 as it would iterate one byte at a time.
183
184 .. versionchanged:: 3.2
185 An iterable that contains both bytes and strings is deprecated and will
186 not be supported in Werkzeug 4.0.
187 """
188
189 def __init__(
190 self,
191 response: str | bytes | cabc.Iterable[str] | cabc.Iterable[bytes] | None = None,
192 status: int | str | HTTPStatus | None = None,
193 headers: cabc.Mapping[str, str | cabc.Iterable[str]]
194 | cabc.Iterable[tuple[str, str]]
195 | None = None,
196 mimetype: str | None = None,
197 content_type: str | None = None,
198 direct_passthrough: bool = False,
199 ) -> None:
200 super().__init__(
201 status=status,
202 headers=headers,
203 mimetype=mimetype,
204 content_type=content_type,
205 )
206
207 self.direct_passthrough = direct_passthrough
208 """Use :attr:`response` directly as the WSGI iterable, rather than
209 passing it through :meth:`iter_encoded`. Should be enabled when
210 ``response`` is a binary file. It is enabled automatically when using
211 :func:`.send_file`.
212 """
213
214 self._on_close: list[t.Callable[[], t.Any]] = []
215
216 # Can't call set_data(response) for all types here, it may clear the
217 # content-type header.
218 if response is None:
219 self.response = []
220 elif isinstance(response, (str, bytes)):
221 self.set_data(response)
222 else:
223 self.response = response
224
225 def call_on_close(self, func: t.Callable[[], t.Any]) -> t.Callable[[], t.Any]:
226 """Adds a function to the internal list of functions that should
227 be called as part of closing down the response. Since 0.7 this
228 function also returns the function that was passed so that this
229 can be used as a decorator.
230
231 .. versionadded:: 0.6
232 """
233 self._on_close.append(func)
234 return func
235
236 def __repr__(self) -> str:
237 if self.is_sequence:
238 body_info = f"{self.calculate_content_length()} bytes"
239 else:
240 body_info = "streamed"
241
242 return f"<{type(self).__name__} {body_info} [{self.status}]>"
243
244 @classmethod
245 def force_type(
246 cls,
247 response: Response | wt.WSGIApplication,
248 environ: wt.WSGIEnvironment | None = None,
249 ) -> Response:
250 """Enforce that the WSGI response is a response object of the current
251 type. Werkzeug will use the :class:`Response` internally in many
252 situations like the exceptions. If you call :meth:`get_response` on an
253 exception you will get back a regular :class:`Response` object, even
254 if you are using a custom subclass.
255
256 This method can enforce a given response type, and it will also
257 convert arbitrary WSGI callables into response objects if an environ
258 is provided::
259
260 # convert a Werkzeug response object into an instance of the
261 # MyResponseClass subclass.
262 response = MyResponseClass.force_type(response)
263
264 # convert any WSGI application into a response object
265 response = MyResponseClass.force_type(response, environ)
266
267 This is especially useful if you want to post-process responses in
268 the main dispatcher and use functionality provided by your subclass.
269
270 Keep in mind that this will modify response objects in place if
271 possible!
272
273 :param response: a response object or wsgi application.
274 :param environ: a WSGI environment object.
275 :return: a response object.
276 """
277 if not isinstance(response, Response):
278 if environ is None:
279 raise TypeError(
280 "cannot convert WSGI application into response"
281 " objects without an environ"
282 )
283
284 from ..test import run_wsgi_app
285
286 response = Response(*run_wsgi_app(response, environ))
287
288 response.__class__ = cls
289 return response
290
291 @classmethod
292 def from_app(
293 cls,
294 app: wt.WSGIApplication,
295 environ: wt.WSGIEnvironment,
296 buffered: bool = False,
297 ) -> Response:
298 """Create a new response object from an application output. This
299 works best if you pass it an application that returns a generator all
300 the time. Sometimes applications may use the `write()` callable
301 returned by the `start_response` function. This tries to resolve such
302 edge cases automatically. But if you don't get the expected output
303 you should set `buffered` to `True` which enforces buffering.
304
305 :param app: the WSGI application to execute.
306 :param environ: the WSGI environment to execute against.
307 :param buffered: set to `True` to enforce buffering.
308 :return: a response object.
309 """
310 from ..test import run_wsgi_app
311
312 return cls(*run_wsgi_app(app, environ, buffered))
313
314 @t.overload
315 def get_data(self, as_text: t.Literal[False] = False) -> bytes: ...
316 @t.overload
317 def get_data(self, as_text: t.Literal[True]) -> str: ...
318 def get_data(self, as_text: bool = False) -> bytes | str:
319 """Read the :attr:`response` iterable into a single bytes value.
320
321 Typically, this should only be used in tests, to examine an expected
322 response. It causes ``response`` to be iterated and encoded immediately,
323 which will be a problem with large or infinite streamed data.
324
325 Set :attr:`implicit_sequence_conversion` to ``False`` to disable this
326 behavior for arbitrary iterables. In that case, this can only be
327 accessed if the body is already a fixed-length sequence. This cannot be
328 accessed if :attr:`direct_passthrough` is ``True``.
329
330 :param as_text: Decode the bytes as UTF-8 and return a string.
331
332 .. versionadded:: 0.9
333 """
334 self._ensure_sequence()
335 rv = b"".join(self.iter_encoded())
336
337 if as_text:
338 return rv.decode()
339
340 return rv
341
342 def set_data(self, value: str | bytes) -> None:
343 """Set the :attr:`response` iterable and :attr:`content_length`. A
344 string is encoded as UTF-8. The value is wrapped as a single-item
345 sequence.nse.
346
347 .. versionadded:: 0.9
348 """
349 if isinstance(value, str):
350 value = value.encode()
351
352 self.response = [value]
353
354 if self._auto_length:
355 self.content_length = len(value)
356
357 @property
358 def data(self) -> bytes:
359 """The data from the response body. See :meth:`get_data` and
360 :meth:`set_data`.
361 """
362 return self.get_data()
363
364 @data.setter
365 def data(self, value: str | bytes) -> None:
366 self.set_data(value)
367
368 def calculate_content_length(self) -> int | None:
369 """Calculate the total bytes returned by the :attr:`response` iterable.
370
371 This does not set :attr:`content_length`, it only calculates the value.
372 It does not read :attr:`content_length` either, it's only based on what
373 :attr:`response` contains.
374
375 This causes ``response`` to be iterated and encoded immediately, which
376 will be a problem with large or infinite streamed data.
377 Set :attr:`implicit_sequence_conversion` to ``False`` to disable this
378 behavior for arbitrary iterables. In that case, this can only be
379 accessed if the body is already a fixed-length sequence. This cannot be
380 accessed if :attr:`direct_passthrough` is ``True``.
381 """
382 try:
383 self._ensure_sequence()
384 except RuntimeError:
385 return None
386
387 return sum(map(len, self.iter_encoded()))
388
389 def _ensure_sequence(self, mutable: bool = False) -> None:
390 """Use before operations that need :attr:`response` to be a
391 fixed-length sequence, while obeying flags that disable this behavior.
392 Use :meth:`make_sequence` to override those flags.
393
394 This causes ``response`` to be iterated and encoded immediately, which
395 will be a problem with large or infinite streamed data.
396
397 :param mutable: Convert to a mutable sequence.
398 :raise RuntimeError: If it is not already a sequence and
399 :attr:direct_passthrough` is enabled or
400 :attr:`implicit_sequence_conversion` is disabled.
401
402 .. versionadded:: 0.6
403 """
404 if self.is_sequence:
405 if mutable and not isinstance(self.response, cabc.MutableSequence):
406 self.response = list(self.response) # type: ignore[assignment]
407
408 return
409
410 if self.direct_passthrough:
411 raise RuntimeError(
412 "Attempted implicit sequence conversion but the"
413 " response object is in direct passthrough mode."
414 )
415
416 if not self.implicit_sequence_conversion:
417 raise RuntimeError(
418 "The response object required the iterable to be a"
419 " sequence, but implicit conversion was disabled."
420 " Call 'make_sequence()' manually."
421 )
422
423 self.make_sequence()
424
425 def make_sequence(self) -> None:
426 """Convert the :attr:`response` iterator to a fixed-length sequence if
427 it is not already.
428
429 Sets :attr:`content_length` unless :attr:`automatically_set_content_length`
430 is disabled.
431
432 If the original ``response`` has a ``close`` method, it will be called
433 after iterating.
434
435 Some other methods automatically do this conversion, but will raise an
436 error instead if :attr:`direct_passthrough` is enabled or
437 :attr:`implicit_sequence_conversion` is disabled. Call this method to
438 override those checks. This causes ``response`` to be iterated and
439 encoded immediately, which will be a problem with large or infinite
440 streamed data.
441
442 .. versionchanged:: 3.2
443 ``close`` is called immediately instead of with the response.
444
445 .. versionadded:: 0.6
446 """
447 if not self.is_sequence:
448 close: t.Callable[[], None] | None = getattr(self.response, "close", None)
449 self.response = list(self.iter_encoded())
450
451 if close is not None:
452 close()
453
454 def iter_encoded(self) -> cabc.Iterator[bytes]:
455 """Iterate over the :attr:`response` iterable as bytes. If the iterable
456 is strings, they will be encoded as UTF-8.
457
458 This is used as the WSGI iterator unless :attr:`direct_passthrough` is
459 enabled. That signals that you know the ``response`` is bytes and the
460 check can be skipped, which will be more efficient.
461
462 .. versionchanged:: 3.2
463 An iterable that contains both bytes and strings is deprecated and
464 will not be supported in Werkzeug 4.0.
465 """
466 # Use a separate generator rather than yielding directly. Yielding here
467 # wouldn't access `response` until the first iteration was requested,
468 # meaning `r.response = process(r.iter_encoded())` would create a
469 # circular reference.
470 return _iter_encoded(self.response)
471
472 @property
473 def is_streamed(self) -> bool:
474 """``True`` if the :attr:`response` iterable is not a sequence with a
475 length, for example a generator. This means the number of iterations is
476 unknown, it may end or it may be infinite.
477
478 .. versionchanged:: 3.2
479 Rejects any non ``Sequence`` instead of anything without ``len``.
480 """
481 return not self.is_sequence
482
483 @property
484 def is_sequence(self) -> bool:
485 """``True`` if the :attr:`response` iterator is a sequence with a
486 length, for example a list. This means the number of iterations is
487 known, although it may change if you modify the body.
488
489 .. versionchanged:: 3.2
490 Accepts any ``Sequence`` instead of only ``list`` or ``tuple``.
491
492 .. versionadded:: 0.6
493 """
494 return isinstance(self.response, cabc.Sequence)
495
496 def close(self) -> None:
497 """Close the wrapped response if possible. You can also use the object
498 in a with statement which will automatically close it.
499
500 .. versionadded:: 0.9
501 Can now be used in a with statement.
502 """
503 if hasattr(self.response, "close"):
504 self.response.close()
505 for func in self._on_close:
506 func()
507
508 def __enter__(self) -> t.Self:
509 return self
510
511 def __exit__(
512 self,
513 exc_type: type[BaseException] | None,
514 exc_val: BaseException | None,
515 exc_tb: TracebackType | None,
516 ) -> None:
517 self.close()
518
519 def freeze(self) -> None:
520 """Make the response pickleable.
521
522 - Call :attr:`make_sequence` to buffer the response in memory,
523 ignoring :attr:`direct_passthrough` and
524 :attr:`implicit_sequence_conversion`.
525 - Set :attr:`content_length` to :meth:`calculate_content_length`, even
526 if it's already set.
527 - Call :attr:`add_etag` to generate an ``ETag`` header if it's not
528 already set.
529
530 .. versionchanged:: 2.1
531 Removed the ``no_etag`` parameter.
532
533 .. versionchanged:: 2.0
534 An ``ETag`` header is always added.
535
536 .. versionchanged:: 0.6
537 The ``Content-Length`` header is set.
538 """
539 self.make_sequence()
540 self.content_length = self.calculate_content_length()
541 self.add_etag()
542
543 def get_wsgi_headers(self, environ: wt.WSGIEnvironment) -> Headers:
544 """This is automatically called right before the response is started
545 and returns headers modified for the given environment. It returns a
546 copy of the headers from the response with some modifications applied
547 if necessary.
548
549 For example the location header (if present) is joined with the root
550 URL of the environment. Also the content length is automatically set
551 to zero here for certain status codes.
552
553 .. versionchanged:: 0.6
554 Previously that function was called `fix_headers` and modified
555 the response object in place. Also since 0.6, IRIs in location
556 and content-location headers are handled properly.
557
558 Also starting with 0.6, Werkzeug will attempt to set the content
559 length if it is able to figure it out on its own. This is the
560 case if all the strings in the response iterable are already
561 encoded and the iterable is buffered.
562
563 :param environ: the WSGI environment of the request.
564 :return: returns a new :class:`~werkzeug.datastructures.Headers`
565 object.
566 """
567 headers = Headers(self.headers)
568 location: str | None = None
569 content_location: str | None = None
570 content_length: str | None = None
571 status = self.status_code
572
573 # iterate over the headers to find all values in one go. Because
574 # get_wsgi_headers is used each response that gives us a tiny
575 # speedup.
576 for key, value in headers:
577 ikey = key.lower()
578 if ikey == "location":
579 location = value
580 elif ikey == "content-location":
581 content_location = value
582 elif ikey == "content-length":
583 content_length = value
584
585 if location is not None:
586 uri_location = iri_to_uri(location)
587
588 if location != uri_location:
589 import warnings
590
591 warnings.warn(
592 "The 'Location' header must be a URI, but it was an IRI. Set"
593 " 'response.location' to handle that. An invalid header will not be"
594 " automatically corrected in Werkzeug 4.0.",
595 DeprecationWarning,
596 stacklevel=2,
597 )
598
599 if self.autocorrect_location_header:
600 import warnings
601
602 from .request import Request
603
604 warnings.warn(
605 "Setting 'Response.autocorrect_location_header' is deprecated"
606 " and will be removed in Werkzeug 4.0. Set 'response.location'"
607 " directly if you need a specific format.",
608 DeprecationWarning,
609 stacklevel=2,
610 )
611 # Make the location header an absolute URL.
612 current_url = iri_to_uri(Request(environ).base_url)
613 uri_location = urljoin(current_url, uri_location)
614
615 headers["Location"] = uri_location
616
617 # make sure the content location is a URL
618 if content_location is not None:
619 uri_content_location = iri_to_uri(content_location)
620
621 if content_location != uri_content_location:
622 import warnings
623
624 warnings.warn(
625 "The 'Content-Location' header must be a URI, but it was an IRI."
626 " Set 'response.content_location' to handle that. An invalid header"
627 " will not be automatically corrected in Werkzeug 4.0.",
628 DeprecationWarning,
629 stacklevel=2,
630 )
631
632 headers["Content-Location"] = uri_content_location
633
634 if 100 <= status < 200 or status == 204:
635 # Per section 3.3.2 of RFC 7230, "a server MUST NOT send a
636 # Content-Length header field in any response with a status
637 # code of 1xx (Informational) or 204 (No Content)."
638 headers.remove("Content-Length")
639 elif status == 304:
640 # remove representation metadata
641 # https://httpwg.org/specs/rfc9110.html#status.304
642 # https://httpwg.org/specs/rfc9110.html#representation.metadata
643 for name in (
644 "content-type",
645 "content-encoding",
646 "content-language",
647 "content-length",
648 ):
649 headers.remove(name)
650 elif self._auto_length and content_length is None and self.is_sequence:
651 headers["Content-Length"] = str(self.calculate_content_length())
652
653 return headers
654
655 def get_app_iter(self, environ: wt.WSGIEnvironment) -> cabc.Iterable[bytes]:
656 """Returns the application iterator for the given environ. Depending
657 on the request method and the current status code the return value
658 might be an empty response rather than the one from the response.
659
660 If the request method is `HEAD` or the status code is in a range
661 where the HTTP specification requires an empty response, an empty
662 iterable is returned.
663
664 .. versionadded:: 0.6
665
666 :param environ: the WSGI environment of the request.
667 :return: a response iterable.
668 """
669 status = self.status_code
670 if (
671 environ["REQUEST_METHOD"] == "HEAD"
672 or 100 <= status < 200
673 or status in (204, 304)
674 ):
675 iterable: t.Iterable[bytes] = ()
676 elif self.direct_passthrough:
677 return self.response # type: ignore[return-value]
678 else:
679 iterable = self.iter_encoded()
680 return ClosingIterator(iterable, self.close)
681
682 def get_wsgi_response(
683 self, environ: wt.WSGIEnvironment
684 ) -> tuple[cabc.Iterable[bytes], str, list[tuple[str, str]]]:
685 """Returns the final WSGI response as tuple. The first item in
686 the tuple is the application iterator, the second the status and
687 the third the list of headers. The response returned is created
688 specially for the given environment. For example if the request
689 method in the WSGI environment is ``'HEAD'`` the response will
690 be empty and only the headers and status code will be present.
691
692 .. versionadded:: 0.6
693
694 :param environ: the WSGI environment of the request.
695 :return: an ``(app_iter, status, headers)`` tuple.
696 """
697 headers = self.get_wsgi_headers(environ)
698 app_iter = self.get_app_iter(environ)
699 return app_iter, self.status, headers.to_wsgi_list()
700
701 def __call__(
702 self, environ: wt.WSGIEnvironment, start_response: wt.StartResponse
703 ) -> cabc.Iterable[bytes]:
704 """Process this response as WSGI application.
705
706 :param environ: the WSGI environment.
707 :param start_response: the response callable provided by the WSGI
708 server.
709 :return: an application iterator
710 """
711 app_iter, status, headers = self.get_wsgi_response(environ)
712 start_response(status, headers)
713 return app_iter
714
715 # JSON
716
717 #: A module or other object that has ``dumps`` and ``loads``
718 #: functions that match the API of the built-in :mod:`json` module.
719 json_module = json
720
721 @property
722 def json(self) -> t.Any | None:
723 """The parsed JSON data if :attr:`mimetype` indicates JSON
724 (:mimetype:`application/json`, see :attr:`is_json`).
725
726 Calls :meth:`get_json` with default arguments.
727 """
728 return self.get_json()
729
730 @t.overload
731 def get_json(self, force: bool = ..., silent: t.Literal[False] = ...) -> t.Any: ...
732
733 @t.overload
734 def get_json(self, force: bool = ..., silent: bool = ...) -> t.Any | None: ...
735
736 def get_json(self, force: bool = False, silent: bool = False) -> t.Any | None:
737 """Parse :attr:`data` as JSON. Useful during testing.
738
739 If the mimetype does not indicate JSON
740 (:mimetype:`application/json`, see :attr:`is_json`), this
741 returns ``None``.
742
743 Unlike :meth:`Request.get_json`, the result is not cached.
744
745 :param force: Ignore the mimetype and always try to parse JSON.
746 :param silent: Silence parsing errors and return ``None``
747 instead.
748 """
749 if not (force or self.is_json):
750 return None
751
752 data = self.get_data()
753
754 try:
755 return self.json_module.loads(data)
756 except ValueError:
757 if not silent:
758 raise
759
760 return None
761
762 # Stream
763
764 @cached_property
765 def stream(self) -> ResponseStream:
766 """The response iterable as write-only stream.
767
768 .. deprecated:: 3.2
769 Will be removed in Werkzeug 4.0. Use a list comprehension or
770 generator instead.
771 """
772 import warnings
773
774 warnings.warn(
775 "The 'stream' attribute is deprecated and will be removed in"
776 " Werkzeug 4.0. Use a list comprehension or generator instead.",
777 DeprecationWarning,
778 stacklevel=2,
779 )
780 return ResponseStream(self)
781
782 # Preconditions and Range Requests
783
784 def apply_conditions(self, request: Request, *, exists: bool = True) -> None:
785 """Check preconditions from the request: :attr:`~.Request.if_match`,
786 :attr:`~.Request.if_unmodified_since`, :attr:`~.Request.if_none_match`,
787 and :attr:`~.Request.if_modified_since`. The response's :attr:`etag` and
788 :attr:`last_modified` must already be set.
789
790 Depending on the request details and the precondition, a failure will
791 either raise :exc:`.PreconditionFailed`, or :attr:`status_code` will be
792 set to 304. The response will handle clearing the data and content
793 length for 304 automatically.
794
795 Call :meth:`apply_range` after this, it will exit early if a condition
796 was not met.
797
798 :param request: The request to get the range from.
799 :param exists: Whether the resource currently exists. Used when
800 ``If-Match`` or ``If-None-Match`` are ``*``.
801 :raises .PreconditionFailed: If a precondition fails and results in a
802 412 instead of a 304.
803
804 .. versionadded:: 3.2
805 """
806 from ..exceptions import PreconditionFailed
807
808 etag = self.etag
809 last_modified = self.last_modified
810
811 # https://httpwg.org/specs/rfc9110.html#precedence
812 # first evaluate one of if-match or if-unmodified-since
813 if request.if_match:
814 if not (
815 exists
816 if request.if_match.star_tag
817 else request.if_match.contains_strong(etag)
818 ):
819 raise PreconditionFailed()
820 else:
821 if (
822 request.if_unmodified_since is not None
823 and last_modified is not None
824 and last_modified > request.if_unmodified_since
825 ):
826 raise PreconditionFailed()
827
828 # then evaluate one of if-none-match or if-modified-since
829 if request.if_none_match:
830 if (
831 exists
832 if request.if_none_match.star_tag
833 else request.if_none_match.contains_weak(etag)
834 ):
835 if request.method not in {"GET", "HEAD"}:
836 raise PreconditionFailed()
837
838 self.status_code = 304
839 else:
840 if (
841 request.method in {"GET", "HEAD"}
842 and last_modified is not None
843 and request.if_modified_since is not None
844 and last_modified <= request.if_modified_since
845 ):
846 self.status_code = 304
847
848 def apply_range(self, request: Request) -> None:
849 """Advertise range request support, check :attr:`.Request.if_range`, and
850 apply :attr:`.Request.range` if it is valid and satisfiable. The
851 response's :attr:`data`, :attr:`content_length`, :attr:`etag`, and
852 :attr:`last_modified` must already be set for the complete data.
853
854 Only the ``bytess`` unit is supported. If multiple ranges are given,
855 only the first is used. An unknown length is not supported.
856
857 Call :meth:`apply_conditions` before this, to exit early if a condition
858 was not met.
859
860 :param request: The request to get the range from.
861 :raises .RequestedRangeNotSatisfiable: If the range is valid but cannot
862 be satisfied for the content length.
863
864 .. versionadded:: 3.2
865 """
866 from ..exceptions import RequestedRangeNotSatisfiable
867
868 self.accept_ranges = "bytes"
869
870 if (
871 self.status_code != 200
872 or request.method != "GET"
873 or request.range is None
874 or request.range.units != "bytes"
875 or not (complete_length := self.content_length)
876 or (
877 request.if_range
878 and not request.if_range.check(self.etag, self.last_modified)
879 )
880 ):
881 return
882
883 if (content_range := request.range.make_content_range(complete_length)) is None:
884 raise RequestedRangeNotSatisfiable(complete_length)
885
886 content_length = content_range.stop - content_range.start # type: ignore[operator]
887 self.content_length = content_length
888 self.content_range = content_range
889 self.status_code = 206
890 self.response = _RangeWrapper(
891 self.response, # type: ignore[arg-type]
892 content_range.start, # type: ignore[arg-type]
893 content_length,
894 )
895
896 def make_conditional(
897 self,
898 request_or_environ: Request | wt.WSGIEnvironment,
899 accept_ranges: bool = False,
900 complete_length: int | None = None,
901 ) -> Response:
902 """Check preconditions from the request, advertise range support, and
903 apply a requested range. :attr:`data`, :attr:`content_length`,
904 :attr:`etag`, and :attr:`last_modified` must already be set.
905
906 :param request_or_environ: The request or WSGI environ to get the
907 preconditions and range from.
908 :param accept_ranges: If ``True``, after checking preconditions,
909 advertise range support and apply a requested range.
910 :param complete_length: Set :attr:`content_length` to this value. Better
911 to set it before calling instead.
912 :raises .PreconditionFailed: If a precondition fails and results in a
913 412 instead of a 304.
914 :raises .RequestedRangeNotSatisfiable: If the range is valid but cannot
915 be satisfied for the content length.
916
917 .. deprecated:: 3.2
918 Will be removed in Werkzeug 3.3. Use ``apply_conditions`` and
919 ``apply_range`` instead.
920
921 .. versionchanged:: 3.2
922 Applies to all request methods correctly.
923
924 Does not set ``Date``. Does not calculate ``Content-Length``
925 if not given.
926
927 Correct ordering of preconditions followed by range.
928
929 Only the ``bytes`` unit is allowed. Sets ``Accept-Ranges``
930 even if the range is not valid or satisfiable.
931
932 Raises ``PreconditionFailed`` instead of setting a ``412`` status.
933
934 .. versionchanged:: 2.0
935 Range processing is skipped if length is 0 instead of raising a 416.
936 """
937 import warnings
938
939 warnings.warn(
940 "'make_conditional' is deprecated and will be removed in Werkzeug 3.3."
941 " Use 'apply_conditions' and 'apply_range' instead.",
942 DeprecationWarning,
943 stacklevel=2,
944 )
945 from .request import Request
946
947 if isinstance(request_or_environ, Request):
948 request = request_or_environ
949 else:
950 request = Request(request_or_environ)
951
952 self.apply_conditions(request)
953
954 if accept_ranges:
955 if complete_length is not None:
956 self.content_length = complete_length
957
958 self.apply_range(request)
959
960 return self
961
962 def add_etag(self, overwrite: bool = False, weak: bool = False) -> None:
963 """Set the ``ETag`` header by hashing the response's data. This causes
964 the data to be read, don't call this on a streaming response.
965
966 :param overwrite: Overwrite an existing ``ETag`` header.
967 :param weak: Mark the ETag as weak. This is unlikely what you want, as
968 a hash of the data is typically considered strong.
969
970 .. versionchanged:: 3.2
971 Use SHA3-256.
972
973 .. versionchanged:: 2.0
974 Use SHA-1.
975 """
976 if overwrite or "ETag" not in self.headers:
977 self.etag = _generate_etag(self.get_data()), weak
978
979
980class ResponseStream:
981 """A file descriptor like object used by :meth:`Response.stream` to
982 represent the body of the stream. It directly pushes into the
983 response iterable of the response object.
984 """
985
986 mode = "wb+"
987
988 def __init__(self, response: Response):
989 self.response = response
990 self.closed = False
991
992 def write(self, value: bytes) -> int:
993 if self.closed:
994 raise ValueError("I/O operation on closed file")
995 self.response._ensure_sequence(mutable=True)
996 self.response.response.append(value) # type: ignore[union-attr]
997 self.response.content_length = None
998 return len(value)
999
1000 def writelines(self, seq: cabc.Iterable[bytes]) -> None:
1001 for item in seq:
1002 self.write(item)
1003
1004 def close(self) -> None:
1005 self.closed = True
1006
1007 def flush(self) -> None:
1008 if self.closed:
1009 raise ValueError("I/O operation on closed file")
1010
1011 def isatty(self) -> bool:
1012 if self.closed:
1013 raise ValueError("I/O operation on closed file")
1014 return False
1015
1016 def tell(self) -> int:
1017 self.response._ensure_sequence()
1018 return sum(map(len, self.response.response))
1019
1020 @property
1021 def encoding(self) -> str:
1022 return "utf-8"