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 )