Skip to content

Commit 7b19cd5

Browse files
authored
Move utility functions from _utils.py to _client.py (#3389)
1 parent b47d94c commit 7b19cd5

File tree

4 files changed

+92
-100
lines changed

4 files changed

+92
-100
lines changed

httpx/_client.py

+35-8
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,7 @@
4545
TimeoutTypes,
4646
)
4747
from ._urls import URL, QueryParams
48-
from ._utils import (
49-
URLPattern,
50-
get_environment_proxies,
51-
is_https_redirect,
52-
same_origin,
53-
)
48+
from ._utils import URLPattern, get_environment_proxies
5449

5550
if typing.TYPE_CHECKING:
5651
import ssl # pragma: no cover
@@ -63,6 +58,38 @@
6358
U = typing.TypeVar("U", bound="AsyncClient")
6459

6560

61+
def _is_https_redirect(url: URL, location: URL) -> bool:
62+
"""
63+
Return 'True' if 'location' is a HTTPS upgrade of 'url'
64+
"""
65+
if url.host != location.host:
66+
return False
67+
68+
return (
69+
url.scheme == "http"
70+
and _port_or_default(url) == 80
71+
and location.scheme == "https"
72+
and _port_or_default(location) == 443
73+
)
74+
75+
76+
def _port_or_default(url: URL) -> int | None:
77+
if url.port is not None:
78+
return url.port
79+
return {"http": 80, "https": 443}.get(url.scheme)
80+
81+
82+
def _same_origin(url: URL, other: URL) -> bool:
83+
"""
84+
Return 'True' if the given URLs share the same origin.
85+
"""
86+
return (
87+
url.scheme == other.scheme
88+
and url.host == other.host
89+
and _port_or_default(url) == _port_or_default(other)
90+
)
91+
92+
6693
class UseClientDefault:
6794
"""
6895
For some parameters such as `auth=...` and `timeout=...` we need to be able
@@ -521,8 +548,8 @@ def _redirect_headers(self, request: Request, url: URL, method: str) -> Headers:
521548
"""
522549
headers = Headers(request.headers)
523550

524-
if not same_origin(url, request.url):
525-
if not is_https_redirect(request.url, url):
551+
if not _same_origin(url, request.url):
552+
if not _is_https_redirect(request.url, url):
526553
# Strip Authorization headers when responses are redirected
527554
# away from the origin. (Except for direct HTTP to HTTPS redirects.)
528555
headers.pop("Authorization", None)

httpx/_utils.py

-32
Original file line numberDiff line numberDiff line change
@@ -27,38 +27,6 @@ def primitive_value_to_str(value: PrimitiveData) -> str:
2727
return str(value)
2828

2929

30-
def port_or_default(url: URL) -> int | None:
31-
if url.port is not None:
32-
return url.port
33-
return {"http": 80, "https": 443}.get(url.scheme)
34-
35-
36-
def same_origin(url: URL, other: URL) -> bool:
37-
"""
38-
Return 'True' if the given URLs share the same origin.
39-
"""
40-
return (
41-
url.scheme == other.scheme
42-
and url.host == other.host
43-
and port_or_default(url) == port_or_default(other)
44-
)
45-
46-
47-
def is_https_redirect(url: URL, location: URL) -> bool:
48-
"""
49-
Return 'True' if 'location' is a HTTPS upgrade of 'url'
50-
"""
51-
if url.host != location.host:
52-
return False
53-
54-
return (
55-
url.scheme == "http"
56-
and port_or_default(url) == 80
57-
and location.scheme == "https"
58-
and port_or_default(location) == 443
59-
)
60-
61-
6230
def get_environment_proxies() -> dict[str, str | None]:
6331
"""Gets proxy information from the environment"""
6432

tests/client/test_headers.py

+56
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,59 @@ def test_host_with_non_default_port_in_url():
235235
def test_request_auto_headers():
236236
request = httpx.Request("GET", "https://www.example.org/")
237237
assert "host" in request.headers
238+
239+
240+
def test_same_origin():
241+
origin = httpx.URL("https://example.com")
242+
request = httpx.Request("GET", "HTTPS://EXAMPLE.COM:443")
243+
244+
client = httpx.Client()
245+
headers = client._redirect_headers(request, origin, "GET")
246+
247+
assert headers["Host"] == request.url.netloc.decode("ascii")
248+
249+
250+
def test_not_same_origin():
251+
origin = httpx.URL("https://example.com")
252+
request = httpx.Request("GET", "HTTP://EXAMPLE.COM:80")
253+
254+
client = httpx.Client()
255+
headers = client._redirect_headers(request, origin, "GET")
256+
257+
assert headers["Host"] == origin.netloc.decode("ascii")
258+
259+
260+
def test_is_https_redirect():
261+
url = httpx.URL("https://example.com")
262+
request = httpx.Request(
263+
"GET", "http://example.com", headers={"Authorization": "empty"}
264+
)
265+
266+
client = httpx.Client()
267+
headers = client._redirect_headers(request, url, "GET")
268+
269+
assert "Authorization" in headers
270+
271+
272+
def test_is_not_https_redirect():
273+
url = httpx.URL("https://www.example.com")
274+
request = httpx.Request(
275+
"GET", "http://example.com", headers={"Authorization": "empty"}
276+
)
277+
278+
client = httpx.Client()
279+
headers = client._redirect_headers(request, url, "GET")
280+
281+
assert "Authorization" not in headers
282+
283+
284+
def test_is_not_https_redirect_if_not_default_ports():
285+
url = httpx.URL("https://example.com:1337")
286+
request = httpx.Request(
287+
"GET", "http://example.com:9999", headers={"Authorization": "empty"}
288+
)
289+
290+
client = httpx.Client()
291+
headers = client._redirect_headers(request, url, "GET")
292+
293+
assert "Authorization" not in headers

tests/test_utils.py

+1-60
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
import pytest
77

88
import httpx
9-
from httpx._utils import (
10-
URLPattern,
11-
get_environment_proxies,
12-
)
9+
from httpx._utils import URLPattern, get_environment_proxies
1310

1411

1512
@pytest.mark.parametrize(
@@ -115,62 +112,6 @@ def test_get_environment_proxies(environment, proxies):
115112
assert get_environment_proxies() == proxies
116113

117114

118-
def test_same_origin():
119-
origin = httpx.URL("https://example.com")
120-
request = httpx.Request("GET", "HTTPS://EXAMPLE.COM:443")
121-
122-
client = httpx.Client()
123-
headers = client._redirect_headers(request, origin, "GET")
124-
125-
assert headers["Host"] == request.url.netloc.decode("ascii")
126-
127-
128-
def test_not_same_origin():
129-
origin = httpx.URL("https://example.com")
130-
request = httpx.Request("GET", "HTTP://EXAMPLE.COM:80")
131-
132-
client = httpx.Client()
133-
headers = client._redirect_headers(request, origin, "GET")
134-
135-
assert headers["Host"] == origin.netloc.decode("ascii")
136-
137-
138-
def test_is_https_redirect():
139-
url = httpx.URL("https://example.com")
140-
request = httpx.Request(
141-
"GET", "http://example.com", headers={"Authorization": "empty"}
142-
)
143-
144-
client = httpx.Client()
145-
headers = client._redirect_headers(request, url, "GET")
146-
147-
assert "Authorization" in headers
148-
149-
150-
def test_is_not_https_redirect():
151-
url = httpx.URL("https://www.example.com")
152-
request = httpx.Request(
153-
"GET", "http://example.com", headers={"Authorization": "empty"}
154-
)
155-
156-
client = httpx.Client()
157-
headers = client._redirect_headers(request, url, "GET")
158-
159-
assert "Authorization" not in headers
160-
161-
162-
def test_is_not_https_redirect_if_not_default_ports():
163-
url = httpx.URL("https://example.com:1337")
164-
request = httpx.Request(
165-
"GET", "http://example.com:9999", headers={"Authorization": "empty"}
166-
)
167-
168-
client = httpx.Client()
169-
headers = client._redirect_headers(request, url, "GET")
170-
171-
assert "Authorization" not in headers
172-
173-
174115
@pytest.mark.parametrize(
175116
["pattern", "url", "expected"],
176117
[

0 commit comments

Comments
 (0)