Skip to content

Commit 266bfa1

Browse files
committed
Merge branch 'master' into content-parameters-on-response
2 parents 8e7b8d1 + 19b863a commit 266bfa1

File tree

4 files changed

+60
-36
lines changed

4 files changed

+60
-36
lines changed

httpx/_client.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import httpcore
77

8+
from .__version__ import __version__
89
from ._auth import Auth, BasicAuth, FunctionAuth
910
from ._config import (
1011
DEFAULT_LIMITS,
@@ -18,6 +19,7 @@
1819
create_ssl_context,
1920
)
2021
from ._content_streams import ContentStream
22+
from ._decoders import SUPPORTED_DECODERS
2123
from ._exceptions import (
2224
HTTPCORE_EXC_MAP,
2325
InvalidURL,
@@ -55,6 +57,10 @@
5557
logger = get_logger(__name__)
5658

5759
KEEPALIVE_EXPIRY = 5.0
60+
USER_AGENT = f"python-httpx/{__version__}"
61+
ACCEPT_ENCODING = ", ".join(
62+
[key for key in SUPPORTED_DECODERS.keys() if key != "identity"]
63+
)
5864

5965

6066
class BaseClient:
@@ -74,7 +80,7 @@ def __init__(
7480

7581
self._auth = self._build_auth(auth)
7682
self._params = QueryParams(params)
77-
self._headers = Headers(headers)
83+
self.headers = Headers(headers)
7884
self._cookies = Cookies(cookies)
7985
self._timeout = Timeout(timeout)
8086
self.max_redirects = max_redirects
@@ -161,7 +167,16 @@ def headers(self) -> Headers:
161167

162168
@headers.setter
163169
def headers(self, headers: HeaderTypes) -> None:
164-
self._headers = Headers(headers)
170+
client_headers = Headers(
171+
{
172+
b"Accept": b"*/*",
173+
b"Accept-Encoding": ACCEPT_ENCODING.encode("ascii"),
174+
b"Connection": b"keep-alive",
175+
b"User-Agent": USER_AGENT.encode("ascii"),
176+
}
177+
)
178+
client_headers.update(headers)
179+
self._headers = client_headers
165180

166181
@property
167182
def cookies(self) -> Cookies:
@@ -299,11 +314,9 @@ def _merge_headers(
299314
Merge a headers argument together with any headers on the client,
300315
to create the headers used for the outgoing request.
301316
"""
302-
if headers or self.headers:
303-
merged_headers = Headers(self.headers)
304-
merged_headers.update(headers)
305-
return merged_headers
306-
return headers
317+
merged_headers = Headers(self.headers)
318+
merged_headers.update(headers)
319+
return merged_headers
307320

308321
def _merge_queryparams(
309322
self, params: QueryParamTypes = None

httpx/_models.py

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import rfc3986
1515
import rfc3986.exceptions
1616

17-
from .__version__ import __version__
1817
from ._content_streams import (
1918
ByteStream,
2019
ContentStream,
@@ -109,13 +108,11 @@ def userinfo(self) -> str:
109108

110109
@property
111110
def username(self) -> str:
112-
userinfo = self._uri_reference.userinfo or ""
113-
return unquote(userinfo.partition(":")[0])
111+
return unquote(self.userinfo.partition(":")[0])
114112

115113
@property
116114
def password(self) -> str:
117-
userinfo = self._uri_reference.userinfo or ""
118-
return unquote(userinfo.partition(":")[2])
115+
return unquote(self.userinfo.partition(":")[2])
119116

120117
@property
121118
def host(self) -> str:
@@ -586,12 +583,6 @@ def getlist(self, key: str, split_commas: bool = False) -> typing.List[str]:
586583
return self.get_list(key, split_commas=split_commas)
587584

588585

589-
USER_AGENT = f"python-httpx/{__version__}"
590-
ACCEPT_ENCODING = ", ".join(
591-
[key for key in SUPPORTED_DECODERS.keys() if key != "identity"]
592-
)
593-
594-
595586
class Request:
596587
def __init__(
597588
self,
@@ -633,26 +624,12 @@ def prepare(self) -> None:
633624
has_content_length = (
634625
"content-length" in self.headers or "transfer-encoding" in self.headers
635626
)
636-
has_user_agent = "user-agent" in self.headers
637-
has_accept = "accept" in self.headers
638-
has_accept_encoding = "accept-encoding" in self.headers
639-
has_connection = "connection" in self.headers
640-
641-
if not has_host:
642-
url = self.url
643-
if url.userinfo:
644-
url = url.copy_with(username=None, password=None)
645-
auto_headers.append((b"host", url.authority.encode("ascii")))
627+
628+
if not has_host and self.url.authority:
629+
host = self.url.copy_with(username=None, password=None).authority
630+
auto_headers.append((b"host", host.encode("ascii")))
646631
if not has_content_length and self.method in ("POST", "PUT", "PATCH"):
647632
auto_headers.append((b"content-length", b"0"))
648-
if not has_user_agent:
649-
auto_headers.append((b"user-agent", USER_AGENT.encode("ascii")))
650-
if not has_accept:
651-
auto_headers.append((b"accept", b"*/*"))
652-
if not has_accept_encoding:
653-
auto_headers.append((b"accept-encoding", ACCEPT_ENCODING.encode()))
654-
if not has_connection:
655-
auto_headers.append((b"connection", b"keep-alive"))
656633

657634
self.headers = Headers(auto_headers + self.headers.raw)
658635

tests/client/test_headers.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,28 @@ def test_header_update():
124124
}
125125

126126

127+
def test_remove_default_header():
128+
"""
129+
Remove a default header from the Client.
130+
"""
131+
url = "http://example.org/echo_headers"
132+
133+
client = httpx.Client(transport=MockTransport())
134+
del client.headers["User-Agent"]
135+
136+
response = client.get(url)
137+
138+
assert response.status_code == 200
139+
assert response.json() == {
140+
"headers": {
141+
"accept": "*/*",
142+
"accept-encoding": "gzip, deflate, br",
143+
"connection": "keep-alive",
144+
"host": "example.org",
145+
}
146+
}
147+
148+
127149
def test_header_does_not_exist():
128150
headers = httpx.Headers({"foo": "bar"})
129151
with pytest.raises(KeyError):

tests/models/test_requests.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ def test_json_encoded_data():
3434
assert request.content == b'{"test": 123}'
3535

3636

37+
def test_headers():
38+
request = httpx.Request("POST", "http://example.org", json={"test": 123})
39+
40+
assert request.headers == httpx.Headers(
41+
{
42+
"Host": "example.org",
43+
"Content-Type": "application/json",
44+
"Content-Length": "13",
45+
}
46+
)
47+
48+
3749
def test_read_and_stream_data():
3850
# Ensure a request may still be streamed if it has been read.
3951
# Needed for cases such as authentication classes that read the request body.

0 commit comments

Comments
 (0)