Read only version of the headers from a WSGI environment. This provides the same interface as `Headers` and is constructed from a WSGI environment. From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a subclass of the :exc:`~exceptions.BadRequest` HTTP exception a
| 603 | |
| 604 | |
| 605 | class EnvironHeaders(ImmutableHeadersMixin, Headers): # type: ignore[misc] |
| 606 | """Read only version of the headers from a WSGI environment. This |
| 607 | provides the same interface as `Headers` and is constructed from |
| 608 | a WSGI environment. |
| 609 | From Werkzeug 0.3 onwards, the `KeyError` raised by this class is also a |
| 610 | subclass of the :exc:`~exceptions.BadRequest` HTTP exception and will |
| 611 | render a page for a ``400 BAD REQUEST`` if caught in a catch-all for |
| 612 | HTTP exceptions. |
| 613 | """ |
| 614 | |
| 615 | def __init__(self, environ: WSGIEnvironment) -> None: |
| 616 | super().__init__() |
| 617 | self.environ = environ |
| 618 | |
| 619 | def __eq__(self, other: object) -> bool: |
| 620 | if not isinstance(other, EnvironHeaders): |
| 621 | return NotImplemented |
| 622 | |
| 623 | return self.environ is other.environ |
| 624 | |
| 625 | __hash__ = None |
| 626 | |
| 627 | def __getitem__(self, key: str) -> str: # type: ignore[override] |
| 628 | return self._get_key(key) |
| 629 | |
| 630 | def _get_key(self, key: str) -> str: |
| 631 | if not isinstance(key, str): |
| 632 | raise BadRequestKeyError(key) |
| 633 | |
| 634 | key = key.upper().replace("-", "_") |
| 635 | |
| 636 | if key in {"CONTENT_TYPE", "CONTENT_LENGTH"}: |
| 637 | return self.environ[key] # type: ignore[no-any-return] |
| 638 | |
| 639 | return self.environ[f"HTTP_{key}"] # type: ignore[no-any-return] |
| 640 | |
| 641 | def __len__(self) -> int: |
| 642 | return sum(1 for _ in self) |
| 643 | |
| 644 | def __iter__(self) -> cabc.Iterator[tuple[str, str]]: |
| 645 | for key, value in self.environ.items(): |
| 646 | if key.startswith("HTTP_") and key not in { |
| 647 | "HTTP_CONTENT_TYPE", |
| 648 | "HTTP_CONTENT_LENGTH", |
| 649 | }: |
| 650 | yield key[5:].replace("_", "-").title(), value |
| 651 | elif key in {"CONTENT_TYPE", "CONTENT_LENGTH"} and value: |
| 652 | yield key.replace("_", "-").title(), value |
| 653 | |
| 654 | def copy(self) -> t.NoReturn: |
| 655 | raise TypeError(f"cannot create {type(self).__name__!r} copies") |
| 656 | |
| 657 | def __or__(self, other: t.Any) -> t.NoReturn: |
| 658 | raise TypeError(f"cannot create {type(self).__name__!r} copies") |
| 659 | |
| 660 | |
| 661 | # circular dependencies |
no outgoing calls