A dictionary that maintains ``Http-Header-Case`` for all keys. Supports multiple values per key via a pair of new methods, `add()` and `get_list()`. The regular dictionary interface returns a single value per key, with multiple values joined by a comma. >>> h = HTTPHeaders({"c
| 143 | |
| 144 | |
| 145 | class HTTPHeaders(StrMutableMapping): |
| 146 | """A dictionary that maintains ``Http-Header-Case`` for all keys. |
| 147 | |
| 148 | Supports multiple values per key via a pair of new methods, |
| 149 | `add()` and `get_list()`. The regular dictionary interface |
| 150 | returns a single value per key, with multiple values joined by a |
| 151 | comma. |
| 152 | |
| 153 | >>> h = HTTPHeaders({"content-type": "text/html"}) |
| 154 | >>> list(h.keys()) |
| 155 | ['Content-Type'] |
| 156 | >>> h["Content-Type"] |
| 157 | 'text/html' |
| 158 | |
| 159 | >>> h.add("Set-Cookie", "A=B") |
| 160 | >>> h.add("Set-Cookie", "C=D") |
| 161 | >>> h["set-cookie"] |
| 162 | 'A=B,C=D' |
| 163 | >>> h.get_list("set-cookie") |
| 164 | ['A=B', 'C=D'] |
| 165 | |
| 166 | >>> for (k,v) in sorted(h.get_all()): |
| 167 | ... print('%s: %s' % (k,v)) |
| 168 | ... |
| 169 | Content-Type: text/html |
| 170 | Set-Cookie: A=B |
| 171 | Set-Cookie: C=D |
| 172 | """ |
| 173 | |
| 174 | @typing.overload |
| 175 | def __init__(self, __arg: Mapping[str, List[str]]) -> None: |
| 176 | pass |
| 177 | |
| 178 | @typing.overload # noqa: F811 |
| 179 | def __init__(self, __arg: Mapping[str, str]) -> None: |
| 180 | pass |
| 181 | |
| 182 | @typing.overload # noqa: F811 |
| 183 | def __init__(self, *args: Tuple[str, str]) -> None: |
| 184 | pass |
| 185 | |
| 186 | @typing.overload # noqa: F811 |
| 187 | def __init__(self, **kwargs: str) -> None: |
| 188 | pass |
| 189 | |
| 190 | def __init__(self, *args: typing.Any, **kwargs: str) -> None: # noqa: F811 |
| 191 | # Formally, HTTP headers are a mapping from a field name to a "combined field value", |
| 192 | # which may be constructed from multiple field lines by joining them with commas. |
| 193 | # In practice, however, some headers (notably Set-Cookie) do not follow this convention, |
| 194 | # so we maintain a mapping from field name to a list of field lines in self._as_list. |
| 195 | # self._combined_cache is a cache of the combined field values derived from self._as_list |
| 196 | # on demand (and cleared whenever the list is modified). |
| 197 | self._as_list: dict[str, list[str]] = {} |
| 198 | self._combined_cache: dict[str, str] = {} |
| 199 | self._last_key = None # type: Optional[str] |
| 200 | if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], HTTPHeaders): |
| 201 | # Copy constructor |
| 202 | for k, v in args[0].get_all(): |
no outgoing calls