Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/werkzeug/wrappers/response.py: 29%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

295 statements  

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"