Skip to content

Commit 46c22bf

Browse files
committed
Refactor of Headers, implemented _IFieldStorage interface
1 parent 9a79039 commit 46c22bf

File tree

3 files changed

+49
-40
lines changed

3 files changed

+49
-40
lines changed

adafruit_httpserver/headers.py

Lines changed: 35 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
"""
99

1010
try:
11-
from typing import Dict, Tuple, Union
11+
from typing import Dict, List, Union
1212
except ImportError:
1313
pass
1414

15+
from .interfaces import _IFieldStorage
1516

16-
class Headers:
17+
18+
class Headers(_IFieldStorage):
1719
"""
1820
A dict-like class for storing HTTP headers.
1921
@@ -47,23 +49,30 @@ class Headers:
4749
# True
4850
"""
4951

50-
_storage: Dict[str, Tuple[str, str]]
52+
_storage: Dict[str, List[str]]
5153

5254
def __init__(self, headers: Union[str, Dict[str, str]] = None) -> None:
55+
self._storage = {}
56+
5357
if isinstance(headers, str):
54-
headers = {
55-
name: value
56-
for header_line in headers.strip().splitlines()
57-
for name, value in [header_line.split(": ", 1)]
58-
}
58+
for header_line in headers.strip().splitlines():
59+
name, value = header_line.split(": ", 1)
60+
self.add(name, value)
5961
else:
60-
headers = headers or {}
62+
for key, value in (headers or {}).items():
63+
self.add(key, value)
6164

62-
self._storage = {key.lower(): [key, value] for key, value in headers.items()}
65+
def add(self, field_name: str, value: str):
66+
"""Adds a header with the given field name and value."""
67+
self._add_field_value(field_name.lower(), value)
6368

64-
def get(self, name: str, default: str = None) -> Union[str, None]:
69+
def get(self, field_name: str, default: str = None) -> Union[str, None]:
6570
"""Returns the value for the given header name, or default if not found."""
66-
return self._storage.get(name.lower(), [None, default])[1]
71+
return super().get(field_name.lower(), default)
72+
73+
def get_list(self, field_name: str) -> List[str]:
74+
"""Get the list of values of a field."""
75+
return super().get_list(field_name.lower())
6776

6877
def get_directive(self, name: str, default: str = None) -> Union[str, None]:
6978
"""
@@ -102,49 +111,36 @@ def get_parameter(
102111
return header_parameter.strip().split("=")[1].strip('" ')
103112
return default
104113

114+
def set(self, name: str, value: str):
115+
"""Sets the value for the given header name."""
116+
self._storage[name.lower()] = [value]
117+
105118
def setdefault(self, name: str, default: str = None):
106119
"""Sets the value for the given header name if it does not exist."""
107-
return self._storage.setdefault(name.lower(), [name, default])[1]
108-
109-
def items(self):
110-
"""Returns a list of (name, value) tuples."""
111-
return dict(self._storage.values()).items()
112-
113-
def keys(self):
114-
"""Returns a list of header names."""
115-
return list(dict(self._storage.values()).keys())
116-
117-
def values(self):
118-
"""Returns a list of header values."""
119-
return list(dict(self._storage.values()).values())
120+
return self._storage.setdefault(name.lower(), [default])
120121

121122
def update(self, headers: Dict[str, str]):
122123
"""Updates the headers with the given dict."""
123124
return self._storage.update(
124-
{key.lower(): [key, value] for key, value in headers.items()}
125+
{key.lower(): [value] for key, value in headers.items()}
125126
)
126127

127128
def copy(self):
128129
"""Returns a copy of the headers."""
129-
return Headers(dict(self._storage.values()))
130+
return Headers(
131+
"\r\n".join(
132+
f"{key}: {value}" for key in self.fields for value in self.get_list(key)
133+
)
134+
)
130135

131136
def __getitem__(self, name: str):
132-
return self._storage[name.lower()][1]
137+
return super().__getitem__(name.lower())
133138

134139
def __setitem__(self, name: str, value: str):
135-
self._storage[name.lower()] = [name, value]
140+
self._storage[name.lower()] = [value]
136141

137142
def __delitem__(self, name: str):
138143
del self._storage[name.lower()]
139144

140-
def __iter__(self):
141-
return iter(dict(self._storage.values()))
142-
143-
def __len__(self):
144-
return len(self._storage)
145-
146145
def __contains__(self, key: str):
147-
return key.lower() in self._storage.keys()
148-
149-
def __repr__(self):
150-
return f"{self.__class__.__name__}({dict(self._storage.values())})"
146+
return super().__contains__(key.lower())

adafruit_httpserver/interfaces.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515

1616
class _IFieldStorage:
17-
"""Interface with shared methods for QueryParams and FormData."""
17+
"""Interface with shared methods for QueryParams, FormData and Headers."""
1818

1919
_storage: Dict[str, List[Any]]
2020

@@ -37,6 +37,18 @@ def fields(self):
3737
"""Returns a list of field names."""
3838
return list(self._storage.keys())
3939

40+
def items(self):
41+
"""Returns a list of (name, value) tuples."""
42+
return [(key, value) for key in self.fields for value in self.get_list(key)]
43+
44+
def keys(self):
45+
"""Returns a list of header names."""
46+
return self.fields
47+
48+
def values(self):
49+
"""Returns a list of header values."""
50+
return [value for key in self.keys() for value in self.get_list(key)]
51+
4052
def __getitem__(self, field_name: str):
4153
return self._storage[field_name][0]
4254

docs/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
.. automodule:: adafruit_httpserver.headers
2121
:members:
22+
:inherited-members:
2223

2324
.. automodule:: adafruit_httpserver.status
2425
:members:

0 commit comments

Comments
 (0)