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

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

184 statements  

1from __future__ import annotations 

2 

3import collections.abc as cabc 

4import typing as t 

5from datetime import datetime 

6from datetime import timedelta 

7from http import HTTPStatus 

8 

9from .._header_property import header_property 

10from .._header_property import make_structure_on_update 

11from .._header_property import structure_property 

12from ..datastructures.auth import WWWAuthenticate 

13from ..datastructures.cache_control import ResponseCacheControl 

14from ..datastructures.csp import ContentSecurityPolicy 

15from ..datastructures.etag import ETag 

16from ..datastructures.headers import Headers 

17from ..datastructures.range import ContentRange 

18from ..datastructures.set import HeaderSet 

19from ..datastructures.structures import CallbackDict 

20from ..http import _dump_age 

21from ..http import _dump_retry_after 

22from ..http import _load_age 

23from ..http import _load_retry_after 

24from ..http import COEP 

25from ..http import COOP 

26from ..http import CORP 

27from ..http import dump_cookie 

28from ..http import dump_options_header 

29from ..http import http_date 

30from ..http import parse_date 

31from ..http import parse_options_header 

32from ..urls import iri_to_uri 

33from ..urls import uri_to_iri 

34from ..utils import _get_content_type 

35 

36 

37class Response: 

38 """Represents the non-IO parts of an HTTP response, specifically the 

39 status and headers but not the body. 

40 

41 This class is not meant for general use. It should only be used when 

42 implementing WSGI, ASGI, or another HTTP application spec. Werkzeug 

43 provides a WSGI implementation at :cls:`werkzeug.wrappers.Response`. 

44 

45 :param status: The status code for the response. Either an int, in 

46 which case the default status message is added, or a string in 

47 the form ``{code} {message}``, like ``404 Not Found``. Defaults 

48 to 200. 

49 :param headers: A :class:`~werkzeug.datastructures.Headers` object, 

50 or a list of ``(key, value)`` tuples that will be converted to a 

51 ``Headers`` object. 

52 :param mimetype: The mimetype (content type without charset or other 

53 parameters) of the response. If the value starts with ``text/`` (or 

54 matches some other special cases), the charset will be added to create 

55 the ``content_type``. Not used if ``content_type`` is passed. Replaces 

56 ``Content-Type`` in ``headers``. Defaults to :attr:`default_mimetype` 

57 unless ``Content-Type`` is in ``headers``. 

58 :param content_type: The full content type of the response. Overrides 

59 ``mimetype`` if both are passed. Replaces ``Content-Type`` if it's 

60 already in ``headers``. 

61 

62 .. versionchanged:: 3.0 

63 The ``charset`` attribute was removed. 

64 

65 .. versionadded:: 2.0 

66 """ 

67 

68 #: the default status if none is provided. 

69 default_status = 200 

70 

71 #: the default mimetype if none is provided. 

72 default_mimetype: str | None = "text/plain" 

73 """The default value for the ``mimetype`` argument to the constructor. Only 

74 used if ``mimetype`` and ``content_type`` are not passed, and 

75 ``Content-Type`` is not in ``headers``. 

76 """ 

77 

78 #: Warn if a cookie header exceeds this size. The default, 4093, should be 

79 #: safely `supported by most browsers <cookie_>`_. A cookie larger than 

80 #: this size will still be sent, but it may be ignored or handled 

81 #: incorrectly by some browsers. Set to 0 to disable this check. 

82 #: 

83 #: .. versionadded:: 0.13 

84 #: 

85 #: .. _`cookie`: http://browsercookielimits.squawky.net/ 

86 max_cookie_size = 4093 

87 

88 # A :class:`Headers` object representing the response headers. 

89 headers: Headers 

90 

91 def __init__( 

92 self, 

93 status: int | str | HTTPStatus | None = None, 

94 headers: t.Mapping[str, str | t.Iterable[str]] 

95 | t.Iterable[tuple[str, str]] 

96 | None = None, 

97 mimetype: str | None = None, 

98 content_type: str | None = None, 

99 ) -> None: 

100 if isinstance(headers, Headers): 

101 self.headers = headers 

102 elif not headers: 

103 self.headers = Headers() 

104 else: 

105 self.headers = Headers(headers) 

106 

107 if content_type is None: 

108 if mimetype is None: 

109 if "Content-Type" not in self.headers: 

110 self.mimetype = self.default_mimetype 

111 else: 

112 self.mimetype = mimetype 

113 else: 

114 self.content_type = content_type 

115 

116 if status is None: 

117 status = self.default_status 

118 

119 self.status = status 

120 

121 def __repr__(self) -> str: 

122 return f"<{type(self).__name__} [{self.status}]>" 

123 

124 @property 

125 def status_code(self) -> int: 

126 """The HTTP status code as a number.""" 

127 return self._status_code 

128 

129 @status_code.setter 

130 def status_code(self, code: int) -> None: 

131 self.status = code 

132 

133 @property 

134 def status(self) -> str: 

135 """The HTTP status code as a string.""" 

136 return self._status 

137 

138 @status.setter 

139 def status(self, value: str | int | HTTPStatus) -> None: 

140 self._status, self._status_code = self._clean_status(value) 

141 

142 def _clean_status(self, value: str | int | HTTPStatus) -> tuple[str, int]: 

143 if isinstance(value, (int, HTTPStatus)): 

144 status_code = int(value) 

145 else: 

146 value = value.strip() 

147 

148 if not value: 

149 raise ValueError("Empty status argument") 

150 

151 code_str, sep, _ = value.partition(" ") 

152 

153 try: 

154 status_code = int(code_str) 

155 except ValueError: 

156 # only message 

157 return f"0 {value}", 0 

158 

159 if sep: 

160 # code and message 

161 return value, status_code 

162 

163 # only code, look up message 

164 try: 

165 status = f"{status_code} {HTTPStatus(status_code).phrase}" 

166 except ValueError: 

167 status = f"{status_code} Unknown" 

168 

169 return status, status_code 

170 

171 def set_cookie( 

172 self, 

173 key: str, 

174 value: str = "", 

175 max_age: timedelta | int | None = None, 

176 expires: str | datetime | int | float | None = None, 

177 path: str | None = "/", 

178 domain: str | None = None, 

179 secure: bool = False, 

180 httponly: bool = False, 

181 samesite: str | None = None, 

182 partitioned: bool = False, 

183 ) -> None: 

184 """Sets a cookie. 

185 

186 A warning is raised if the size of the cookie header exceeds 

187 :attr:`max_cookie_size`, but the header will still be set. 

188 

189 :param key: the key (name) of the cookie to be set. 

190 :param value: the value of the cookie. 

191 :param max_age: should be a number of seconds, or `None` (default) if 

192 the cookie should last only as long as the client's 

193 browser session. 

194 :param expires: should be a `datetime` object or UNIX timestamp. 

195 :param path: limits the cookie to a given path, per default it will 

196 span the whole domain. 

197 :param domain: if you want to set a cross-domain cookie. For example, 

198 ``domain="example.com"`` will set a cookie that is 

199 readable by the domain ``www.example.com``, 

200 ``foo.example.com`` etc. Otherwise, a cookie will only 

201 be readable by the domain that set it. 

202 :param secure: If ``True``, the cookie will only be available 

203 via HTTPS. 

204 :param httponly: Disallow JavaScript access to the cookie. 

205 :param samesite: Limit the scope of the cookie to only be 

206 attached to requests that are "same-site". 

207 :param partitioned: If ``True``, the cookie will be partitioned. 

208 

209 .. versionchanged:: 3.1 

210 The ``partitioned`` parameter was added. 

211 """ 

212 self.headers.add( 

213 "Set-Cookie", 

214 dump_cookie( 

215 key, 

216 value=value, 

217 max_age=max_age, 

218 expires=expires, 

219 path=path, 

220 domain=domain, 

221 secure=secure, 

222 httponly=httponly, 

223 max_size=self.max_cookie_size, 

224 samesite=samesite, 

225 partitioned=partitioned, 

226 ), 

227 ) 

228 

229 def delete_cookie( 

230 self, 

231 key: str, 

232 path: str | None = "/", 

233 domain: str | None = None, 

234 secure: bool = False, 

235 httponly: bool = False, 

236 samesite: str | None = None, 

237 partitioned: bool = False, 

238 ) -> None: 

239 """Delete a cookie. Fails silently if key doesn't exist. 

240 

241 :param key: the key (name) of the cookie to be deleted. 

242 :param path: if the cookie that should be deleted was limited to a 

243 path, the path has to be defined here. 

244 :param domain: if the cookie that should be deleted was limited to a 

245 domain, that domain has to be defined here. 

246 :param secure: If ``True``, the cookie will only be available 

247 via HTTPS. 

248 :param httponly: Disallow JavaScript access to the cookie. 

249 :param samesite: Limit the scope of the cookie to only be 

250 attached to requests that are "same-site". 

251 :param partitioned: If ``True``, the cookie will be partitioned. 

252 """ 

253 self.set_cookie( 

254 key, 

255 expires=0, 

256 max_age=0, 

257 path=path, 

258 domain=domain, 

259 secure=secure, 

260 httponly=httponly, 

261 samesite=samesite, 

262 partitioned=partitioned, 

263 ) 

264 

265 @property 

266 def is_json(self) -> bool: 

267 """Check if the mimetype indicates JSON data, either 

268 :mimetype:`application/json` or :mimetype:`application/*+json`. 

269 """ 

270 mt = self.mimetype 

271 return mt is not None and ( 

272 mt == "application/json" 

273 or mt.startswith("application/") 

274 and mt.endswith("+json") 

275 ) 

276 

277 # Common Descriptors 

278 

279 @property 

280 def mimetype(self) -> str | None: 

281 """The value from :attr:`content_type`. For example, 

282 ``text/html; charset=utf-8`` becomes``text/html``. 

283 

284 Unlike :attr:`.Request.mimetype`, this will be ``None`` if not set, and 

285 will be the exact value rather than lowercase. 

286 

287 Setting this will clear :attr:`mimetype_params`. Set to ``None`` or use 

288 ``del`` to unset the header. 

289 """ 

290 if ct := self.headers.get("Content-Type"): 

291 return ct.partition(";")[0].strip() 

292 

293 return None 

294 

295 @mimetype.setter 

296 def mimetype(self, value: str | None) -> None: 

297 if not value: 

298 del self.headers["Content-Type"] 

299 else: 

300 self.headers["Content-Type"] = _get_content_type(value, "utf-8") 

301 

302 @mimetype.deleter 

303 def mimetype(self) -> None: 

304 del self.headers["Content-Type"] 

305 

306 @property 

307 def mimetype_params(self) -> dict[str, str]: 

308 """The parameters from :attr:`content_type``. For example, 

309 ``text/html; charset=utf-8`` becomes ``{"charset": "utf-8"}``. 

310 

311 Modifying the dict will update the header if it is set. 

312 

313 .. versionchanged:: 3.2 

314 When the header is not set, modifying does nothing instead of 

315 producing an invalid value. 

316 

317 .. versionadded:: 0.5 

318 """ 

319 

320 def on_update(value: CallbackDict[str, str]) -> None: 

321 if not (mt := self.mimetype): 

322 return 

323 

324 self.headers["Content-Type"] = dump_options_header(mt, value) 

325 

326 d = parse_options_header(self.headers.get("Content-Type"))[1] 

327 return CallbackDict(d, on_update) 

328 

329 location = header_property[str | None]( 

330 "Location", 

331 load_func=uri_to_iri, 

332 dump_func=iri_to_uri, # type: ignore[arg-type] 

333 doc="""The ``Location`` header. The URL the client should redirect to 

334 after this response. Used with ``3xx`` redirects and ``201 Created``. 

335 

336 A ``str``, or ``None`` if not set. Set to ``None`` or use ``del`` to 

337 unset the header. 

338 """, 

339 ) 

340 

341 age = header_property[timedelta | None]( 

342 "Age", 

343 load_func=_load_age, 

344 dump_func=_dump_age, # type: ignore[arg-type] 

345 doc="""The ``Age`` header. The time in seconds since the response data 

346 was generated. Implies that the data was returned by a cache rather than 

347 generated or validated by its origin. 

348 

349 A :class:`~datetime.timedelta`, or ``None`` if not set. Set to a 

350 ``timedelta`` or ``int`` number of seconds. Set to ``None`` or use 

351 ``del`` to unset the header. 

352 """, 

353 ) 

354 

355 content_type = header_property[str | None]( 

356 "Content-Type", 

357 doc="""The ``Content-Type`` header. The type of data in the response 

358 body, with optional parameters for additional detail. 

359 

360 :attr:`mimetype` and :attr:`mimetype_params` allow working with the two 

361 parts of the value separately. 

362 

363 :attr:`.Request.accept_mimetypes` can be used to check the client's 

364 preferences. 

365 """, 

366 ) 

367 

368 content_length = header_property[int | None]( 

369 "Content-Length", 

370 load_func=int, 

371 doc="""The ``Content-Length`` header. The size of the body in bytes. 

372 

373 An ``int``, or ``None`` if not set. Set to ``None`` or use ``del`` to 

374 unset the header. 

375 """, 

376 ) 

377 

378 content_location = header_property[str | None]( 

379 "Content-Location", 

380 load_func=uri_to_iri, 

381 dump_func=iri_to_uri, # type: ignore[arg-type] 

382 doc="""The ``Content-Location`` header. A more specific URL for the same 

383 negotiated resource. 

384 

385 A ``str``, or ``None`` if not set. Set to ``None`` or use ``del`` to 

386 unset the header. 

387 """, 

388 ) 

389 

390 content_encoding = header_property[str | None]( 

391 "Content-Encoding", 

392 doc="""The ``Content-Encoding`` header. An additional encoding applied 

393 to the body beyond the ``Content-Type``. 

394 

395 A ``str``, or ``None`` if not set. Set to ``None`` or use ``del`` to 

396 unset the header. 

397 

398 :attr:`.Request.accept_encodings`` can be used to check the client's 

399 preferences. 

400 """, 

401 ) 

402 

403 @property 

404 def content_md5(self) -> str | None: 

405 """The ``Content-MD5`` header. An MD5 digest of the response body. 

406 

407 A ``str``, or ``None`` if not set. Set to ``None`` or use ``del`` to 

408 unset the header. 

409 

410 .. deprecated:: 3.2 

411 The header has not been used for a long time. Will be removed 

412 in Werkzeug 4.0. 

413 """ 

414 import warnings 

415 

416 warnings.warn( 

417 "The 'content_md5' attribute is deprecated and will be removed in" 

418 " Werkzeug 4.0. The header has not been used for a long time.", 

419 DeprecationWarning, 

420 stacklevel=2, 

421 ) 

422 return self.headers.get("Content-MD5") 

423 

424 @content_md5.setter 

425 def content_md5(self, value: str | None) -> None: 

426 import warnings 

427 

428 warnings.warn( 

429 "The 'content_md5' attribute is deprecated and will be removed in" 

430 " Werkzeug 4.0. The header has not been used for a long time.", 

431 DeprecationWarning, 

432 stacklevel=2, 

433 ) 

434 

435 if value is None: 

436 del self.headers["Content-MD5"] 

437 else: 

438 self.headers["Content-MD5"] = value 

439 

440 @content_md5.deleter 

441 def content_md5(self) -> None: 

442 import warnings 

443 

444 warnings.warn( 

445 "The 'content_md5' attribute is deprecated and will be removed in" 

446 " Werkzeug 4.0. The header has not been used for a long time.", 

447 DeprecationWarning, 

448 stacklevel=2, 

449 ) 

450 del self.headers["Content-MD5"] 

451 

452 date = header_property[datetime | None]( 

453 "Date", 

454 load_func=parse_date, 

455 dump_func=http_date, 

456 doc="""The ``Date`` header. When the application generated the response. 

457 

458 A :class:`~datetime.datetime`, or ``None`` if not set. Set to a 

459 ``datetime`` or an ``int``/``float`` timestamp. Set to ``None`` or use 

460 ``del`` to unset the header. 

461 

462 .. versionchanged:: 2.0 

463 The datetime object is timezone-aware. 

464 """, 

465 ) 

466 

467 expires = header_property[datetime | None]( 

468 "Expires", 

469 load_func=parse_date, 

470 dump_func=http_date, 

471 doc="""The ``Expires`` header. The time after which a cache of this 

472 response is considered stale. 

473 

474 :attr:`.CacheControl.max_age`` is preferred over this. 

475 

476 A :class:`~datetime.datetime`, or ``None`` if not set. Set to a 

477 ``datetime`` or an ``int``/``float`` timestamp. Set to ``None`` or use 

478 ``del`` to unset the header. 

479 

480 .. versionchanged:: 2.0 

481 The datetime object is timezone-aware. 

482 """, 

483 ) 

484 

485 last_modified = header_property[datetime | None]( 

486 "Last-Modified", 

487 load_func=parse_date, 

488 dump_func=http_date, 

489 doc="""The ``Last-Modified`` header. When the resource was last 

490 modified. The client uses this to make conditional requests with 

491 ``If-Modified-Since``, ``If-Unmodified-Since``, and ``If-Range``. 

492 

493 A :class:`~datetime.datetime`, or ``None`` if not set. Set to a 

494 ``datetime`` or an ``int``/``float`` timestamp. Set to ``None`` or use 

495 ``del`` to unset the header. 

496 

497 .. versionchanged:: 2.0 

498 The datetime object is timezone-aware. 

499 """, 

500 ) 

501 

502 retry_after = header_property[datetime | None]( 

503 "Retry-After", 

504 load_func=_load_retry_after, 

505 dump_func=_dump_retry_after, # type: ignore[arg-type] 

506 doc="""The ``Retry-After`` header. The client should wait until after this 

507 time to make a follow-up request. 

508 

509 A :class:`~datetime.datetime`, or ``None`` if not set. Set to a 

510 ``datetime`` to send a date string, or an ``int`` to send a number of 

511 seconds. Set to ``None`` or use ``del`` to unset the header. 

512 

513 .. versionchanged:: 2.0 

514 The datetime object is timezone-aware. 

515 """, 

516 ) 

517 

518 vary = structure_property[HeaderSet]( 

519 "Vary", 

520 HeaderSet, 

521 doc="""The ``Vary`` header. The set of request headers that affected the 

522 response. Caches will not send a cached response if another request 

523 doesn't have the same header values. 

524 

525 A :class:`.HeaderSet`, empty if not set. Modifying the instance updates 

526 the header, but it is more efficient to set a new instance. Set to a 

527 ``HeaderSet``, or a basic collection like ``set``, ``list``, or 

528 ``tuple``. Set to ``None`` or use ``del`` to unset the header. 

529 

530 .. versionchanged:: 3.2 

531 Setting to a ``str`` is deprecated and will be removed in Werkzeug 4.0. 

532 Set ``headers`` directly instead. 

533 """, 

534 deprecate_str=True, 

535 ) 

536 

537 content_language = structure_property[HeaderSet]( 

538 "Content-Language", 

539 HeaderSet, 

540 doc="""The ``Content-Language`` header. The natural languages of the 

541 response body. 

542 

543 A :class:`.HeaderSet`, empty if not set. Modifying the instance updates 

544 the header, but it is more efficient to set a new instance. Set to a 

545 ``HeaderSet``, or a basic collection like ``set``, ``list``, or 

546 ``tuple``. Set to ``None`` or use ``del`` to unset the header. 

547 

548 :attr:`.Request.accept_languages` can be used to check the client's 

549 preferences. 

550 

551 .. versionchanged:: 3.2 

552 Setting to a ``str`` is deprecated and will be removed in Werkzeug 4.0. 

553 Set ``headers`` directly instead. 

554 """, 

555 deprecate_str=True, 

556 ) 

557 

558 allow = structure_property[HeaderSet]( 

559 "Allow", 

560 HeaderSet, 

561 doc="""The ``Allow`` header. The set of methods supported for the URL. 

562 Sent for ``OPTIONS`` and ``405`` responses. 

563 

564 A :class:`.HeaderSet`, empty if not set. Modifying the instance updates 

565 the header, but it is more efficient to set a new instance. Set to a 

566 ``HeaderSet``, or a basic collection like ``set``, ``list``, or 

567 ``tuple``. Set to ``None`` or use ``del`` to unset the header. 

568 

569 .. versionchanged:: 3.2 

570 Setting to a ``str`` is deprecated and will be removed in Werkzeug 4.0. 

571 Set ``headers`` directly instead. 

572 """, 

573 deprecate_str=True, 

574 ) 

575 

576 # ETag 

577 

578 cache_control = structure_property[ResponseCacheControl]( 

579 "Cache-Control", 

580 ResponseCacheControl, 

581 doc="""The ``Cache-Control`` header. Directives that control how the 

582 client should cache the response. 

583 

584 A :class:`.ResponseCacheControl`, or empty if the header is not set. 

585 Modifying the instance updates the header, but it is more efficient 

586 to set a new instance. Set to ``None`` or use ``del`` to unset the 

587 header. 

588 

589 .. versionchanged:: 3.2 

590 Can be set to an instance or ``None``, and can use ``del``. 

591 """, 

592 ) 

593 

594 etag = structure_property[ETag]( 

595 "ETag", 

596 ETag, 

597 doc="""The ``ETag`` header. A hash that identifies the state of the 

598 resource for use in conditional requests. 

599 

600 A :class:`.ETag`, or ``None`` if not set. Modifying the instance updates 

601 the header, but it is more efficient to set a new instance. Set to an 

602 ``ETag``, or a ``(value, weak)`` tuple, or a ``str`` meaning 

603 ``(value, False)``. Set to ``None`` or use ``del`` to unset the header. 

604 

605 .. versionadded:: 3.2 

606 """, 

607 ) 

608 

609 @etag.register_setter 

610 def _set_etag(self, value: ETag | tuple[str, bool] | str) -> None: 

611 if isinstance(value, str): 

612 value = ETag(value) 

613 elif isinstance(value, tuple): 

614 value = ETag(*value) 

615 

616 self.headers["ETag"] = value.to_header() 

617 value._on_update = make_structure_on_update(self, "ETag", ETag) 

618 

619 def set_etag(self, etag: str, weak: bool = False) -> None: 

620 """Set the ``ETag`` header. 

621 

622 .. deprecated:: 3.2 

623 Will be removed in Werkzeug 4.0. Use ``etag`` instead. 

624 """ 

625 import warnings 

626 

627 warnings.warn( 

628 "'set_etag' is deprecated and will be removed in Werkzeug 4.0." 

629 " Use 'etag' instead.", 

630 DeprecationWarning, 

631 stacklevel=2, 

632 ) 

633 self.etag = ETag(etag, weak) 

634 

635 def get_etag(self) -> tuple[str, bool] | tuple[None, None]: 

636 """The ``ETag`` header as ``(value, weak)``, or ``(None, None)`` if not 

637 set. 

638 

639 .. deprecated:: 3.2 

640 Will be removed in Werkzeug 4.0. Use ``etag`` instead. 

641 """ 

642 import warnings 

643 

644 warnings.warn( 

645 "'get_etag' is deprecated and will be removed in Werkzeug 4.0." 

646 " Use 'etag' instead.", 

647 DeprecationWarning, 

648 stacklevel=2, 

649 ) 

650 

651 if (result := self.etag) is None: 

652 return None, None 

653 

654 return result.value, result.weak 

655 

656 accept_ranges = header_property[str | None]( 

657 "Accept-Ranges", 

658 doc="""The ``Accept-Ranges`` header. Indicates that a request could 

659 include the ``Range`` header. The value is the unit that will be 

660 accepted, a single value despite the plural name. The only specified 

661 value is ``bytes``. 

662 

663 A ``str``, or ``None`` if not set. Set to ``None`` or use ``del`` to 

664 unset the header. 

665 

666 .. versionadded:: 0.7""", 

667 ) 

668 

669 content_range = structure_property[ContentRange]( 

670 "Content-Range", 

671 ContentRange, 

672 doc="""The ``Content-Range`` header. The partial range being returned in 

673 response to a ``Range`` request. 

674 

675 A :class:`.ContentRange`, empty if not set. Modifying the instance 

676 updates the header, but it is more effiecient to set a new instance. Set 

677 to ``None`` or use ``del`` to unset the header. 

678 

679 .. versionchanged:: 3.2 

680 Setting to a ``str`` is deprecated and will be removed in Werkzeug 4.0. 

681 Set ``headers`` directly instead. 

682 

683 .. versionadded:: 0.7 

684 """, 

685 deprecate_str=True, 

686 ) 

687 

688 # Authorization 

689 

690 www_authenticate = structure_property[WWWAuthenticate]( 

691 "WWW-Authenticate", 

692 WWWAuthenticate, 

693 doc="""The ``WWW-Authenticate`` header. The authentication method needed 

694 to access this resource. Sent with ``401`` errors. 

695 

696 A :class:`.WWWAuthenticate`, empty if not set. Modifying the instance 

697 updates the header, but it is more efficient to set a new instance. Set 

698 to ``None`` or use ``del`` to unset the header. 

699 

700 Set to a ``list[WWWAuthenticate]`` to set multiple values. Modifying the 

701 values in the list does not update the header. Accessing will only 

702 return the first value. 

703 

704 .. versionchanged:: 3.2 

705 :attr:`WWWAuthenticate.type` is empty if the header is not set. 

706 Setting to a ``str`` is deprecated and will be removed in Werkzeug 

707 4.0. Set ``headers`` directly instead. 

708 

709 .. versionchanged:: 2.3 

710 Can be assigned to set the header. A list will set multiple header 

711 values. Set ``None`` or use ``del`` to unset the header. 

712 

713 .. versionchanged:: 2.3 

714 :class:`WWWAuthenticate` is no longer a ``dict``. The ``token`` 

715 attribute was added for auth challenges that use a token instead of 

716 parameters. 

717 """, 

718 deprecate_str=True, 

719 ) 

720 

721 @www_authenticate.register_setter 

722 def _set_www_authenticate( 

723 self, value: WWWAuthenticate | cabc.Sequence[WWWAuthenticate] 

724 ) -> None: 

725 if isinstance(value, cabc.Sequence): 

726 self.headers.setlist("WWW-Authenticate", (v.to_header() for v in value)) 

727 else: 

728 self.headers["WWW-Authenticate"] = value.to_header() 

729 value._on_update = make_structure_on_update( 

730 self, "WWW-Authenticate", WWWAuthenticate 

731 ) 

732 

733 # CSP 

734 

735 content_security_policy = structure_property[ContentSecurityPolicy]( 

736 "Content-Security-Policy", 

737 ContentSecurityPolicy, 

738 doc="""The ``Content-Security-Policy`` header. Controls how the client 

739 loads resources for the returned page. 

740 

741 A :class:`.ContentSecurityPolicy`, empty if not set. Modifying the 

742 instance updates the header, but it it more efficient to set a new 

743 instance. Set to ``None`` or use ``del`` to unset the header. 

744 

745 .. versionchanged:: 3.2 

746 Setting to a ``str`` is deprecated and will be removed in Werkzeug 4.0. 

747 Set ``headers`` directly instead. 

748 """, 

749 deprecate_str=True, 

750 ) 

751 

752 content_security_policy_report_only = structure_property[ContentSecurityPolicy]( 

753 "Content-Security-Policy-Report-Only", 

754 ContentSecurityPolicy, 

755 doc="""The ``Content-Security-Policy-Report-Only`` header. Controls how 

756 the client loads resources for the returned page. Violations are only 

757 reported and do not cause the client to stop. 

758 

759 A :class:`.ContentSecurityPolicy`, empty if not set. Modifying the 

760 instance updates the header, but it it more efficient to set a new 

761 instance. Set to ``None`` or use ``del`` to unset the header. 

762 

763 .. versionchanged:: 3.2 

764 Setting to a ``str`` is deprecated and will be removed in Werkzeug 4.0. 

765 Set ``headers`` directly instead. 

766 """, 

767 deprecate_str=True, 

768 ) 

769 

770 # CORS 

771 

772 access_control_allow_credentials = header_property[bool]( 

773 "Access-Control-Allow-Credentials", 

774 default=False, 

775 load_func=lambda value: value == "true", 

776 dump_func=lambda value: "true" if value is True else None, 

777 doc="""The ``Access-Control-Allow-Credentials`` header. Whether 

778 credentials are allowed in a cross-origin request. 

779 

780 A ``bool``, ``False`` if not set. Set to ``False`` or use ``del`` to 

781 unset the header. 

782 """, 

783 ) 

784 

785 access_control_allow_headers = structure_property[HeaderSet]( 

786 "Access-Control-Allow-Headers", 

787 HeaderSet, 

788 doc="""The ``Access-Control-Allow-Headers`` header. Which headers are 

789 allowed in a cross-origin request. 

790 

791 A :class:`.HeaderSet`, empty if not set. Modifying the instance updates 

792 the header, but it is more efficient to set a new instance. Set to a 

793 ``HeaderSet``, or a basic collection like ``set``, ``list``, or 

794 ``tuple``. Set to ``None`` or use ``del`` to unset the header. 

795 """, 

796 ) 

797 

798 access_control_allow_methods = structure_property[HeaderSet]( 

799 "Access-Control-Allow-Methods", 

800 HeaderSet, 

801 doc="""The ``Access-Control-Allow-Methods`` header. Which methods are 

802 allowed in a cross-origin request. 

803 

804 A :class:`.HeaderSet`, empty if not set. Modifying the instance updates 

805 the header, but it is more efficient to set a new instance. Set to a 

806 ``HeaderSet``, or a basic collection like ``set``, ``list``, or 

807 ``tuple``. Set to ``None`` or use ``del`` to unset the header. 

808 """, 

809 ) 

810 

811 access_control_allow_origin = header_property[str | None]( 

812 "Access-Control-Allow-Origin", 

813 doc="""The ``Access-Control-Allow-Origin`` header. Whether the origin of 

814 the request is allowed to make cross-origin requests. 

815 

816 A ``str``, or ``None`` if not set. Set to ``*`` to allow any origin, 

817 or set to the request's ``Origin`` to allow that origin. Set to ``None`` 

818 or use ``del`` to unset the header. 

819 """, 

820 ) 

821 

822 access_control_expose_headers = structure_property[HeaderSet]( 

823 "Access-Control-Expose-Headers", 

824 HeaderSet, 

825 doc="""The ``Access-Control-Allow-Origin`` header. Which response 

826 headers are allowed to be accessed by scripts. 

827 

828 A :class:`.HeaderSet`, empty if not set. Modifying the instance updates 

829 the header, but it is more efficient to set a new instance. Set to a 

830 ``HeaderSet``, or a basic collection like ``set``, ``list``, or 

831 ``tuple``. Set to ``None`` or use ``del`` to unset the header. 

832 """, 

833 ) 

834 

835 access_control_max_age = header_property[int | None]( 

836 "Access-Control-Max-Age", 

837 load_func=int, 

838 doc="""The ``Access-Control-Max-Age`` header. How long in seconds the 

839 access control headers in a response are valid. 

840 

841 An ``int``, or ``None`` if not set. Set to ``None`` or use ``del`` to 

842 unset the header. 

843 """, 

844 ) 

845 

846 cross_origin_opener_policy = header_property[COOP]( 

847 "Cross-Origin-Opener-Policy", 

848 default=COOP.UNSAFE_NONE, 

849 load_func=COOP, 

850 dump_func=lambda value: value.value, 

851 doc="""The ``Cross-Origin-Opener-Policy`` header. How additional windows 

852 opened from the page are allowed to communicate with the page. 

853 

854 A member of :class:`.COOP`, ``UNSAFE_NONE`` if not set. Set to ``None`` 

855 or use ``del`` to unset the header. 

856 

857 .. versionadded:: 2.0 

858 """, 

859 ) 

860 

861 cross_origin_embedder_policy = header_property[COEP]( 

862 "Cross-Origin-Embedder-Policy", 

863 default=COEP.UNSAFE_NONE, 

864 load_func=COEP, 

865 dump_func=lambda value: value.value, 

866 doc="""The ``Cross-Origin-Embedder-Policy`` header. How cross-origin 

867 resources are allowed to be loaded in ``no-cors`` mode. 

868 

869 A member of :class:`.COEP`, ``UNSAFE_NONE`` if not set. Set to ``None`` 

870 or use ``del`` to unset the header. 

871 

872 .. versionadded:: 2.0 

873 """, 

874 ) 

875 

876 cross_origin_resource_policy = header_property[CORP | None]( 

877 "Cross-Origin-Resource-Policy", 

878 load_func=CORP, 

879 dump_func=lambda value: value.value, # type: ignore[union-attr] 

880 doc="""The ``Cross-Origin-Resource-Policy`` header. Whether cross-origin 

881 requests can load this resource. 

882 

883 A member of :class:`.CORP`, or ``None`` if not set. Set to ``None`` or 

884 use ``del`` to unset the header. 

885 

886 .. versionadded:: 3.2 

887 """, 

888 )