Skip to content

Commit a3e58ca

Browse files
authored
Release 3.18.2 (#350)
3.18.2 (2026-03-12) ------------------- **Fixed** - Unprepared URLs when scheme don't contain `http`. - Edge case false positive scheme detection in url. (#349) - Netrc don't work when base_url is set. (#348)
2 parents 72434a5 + 986a018 commit a3e58ca

File tree

6 files changed

+52
-11
lines changed

6 files changed

+52
-11
lines changed

HISTORY.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
Release History
22
===============
33

4+
3.18.2 (2026-03-12)
5+
-------------------
6+
7+
**Fixed**
8+
- Unprepared URLs when scheme don't contain `http`.
9+
- Edge case false positive scheme detection in url. (#349)
10+
- Netrc don't work when base_url is set. (#348)
11+
412
3.18.1 (2026-03-09)
513
-------------------
614

src/niquests/__version__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99
__url__: str = "https://niquests.readthedocs.io"
1010

1111
__version__: str
12-
__version__ = "3.18.1"
12+
__version__ = "3.18.2"
1313

14-
__build__: int = 0x031801
14+
__build__: int = 0x031802
1515
__author__: str = "Kenneth Reitz"
1616
__author_email__: str = "me@kennethreitz.org"
1717
__license__: str = "Apache-2.0"

src/niquests/models.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
get_auth_from_url,
108108
guess_filename,
109109
iter_slices,
110+
merge_base_url,
110111
parse_header_links,
111112
parse_scheme,
112113
requote_uri,
@@ -382,13 +383,7 @@ def prepare_url(
382383
"""Prepares the given HTTP URL."""
383384
assert url is not None, "Missing URL in PreparedRequest"
384385

385-
if base_url is not None:
386-
if parse_scheme(url, default="") == "":
387-
if base_url.endswith("/"):
388-
base_url = base_url[:-1]
389-
if url and not url.startswith("/"):
390-
url = f"/{url}"
391-
url = base_url + url
386+
url = merge_base_url(base_url, url)
392387

393388
#: Accept objects that have string representations.
394389
#: We're unable to blindly call unicode/str functions
@@ -410,6 +405,12 @@ def prepare_url(
410405
if "http" not in parsed_scheme and parsed_scheme not in {
411406
"asgi",
412407
"wsgi",
408+
"ws",
409+
"wss",
410+
"see",
411+
"psse",
412+
"psse+unix",
413+
"ws+unix",
413414
}:
414415
self.url = url
415416
return

src/niquests/sessions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
get_auth_from_url,
101101
get_environ_proxies,
102102
get_netrc_auth,
103+
merge_base_url,
103104
parse_scheme,
104105
requote_uri,
105106
resolve_proxies,
@@ -543,7 +544,7 @@ def prepare_request(self, request: Request) -> PreparedRequest:
543544
has_authorization_set = "authorization" in self.headers or "authorization" in CaseInsensitiveDict(request.headers)
544545

545546
if self.trust_env and not auth and not self.auth and not has_authorization_set:
546-
auth = get_netrc_auth(request.url)
547+
auth = get_netrc_auth(merge_base_url(self.base_url, request.url))
547548

548549
p = PreparedRequest()
549550
p.prepare(

src/niquests/utils.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1148,10 +1148,18 @@ def parse_scheme(url: str, default: str | None = None, max_length: int = 11) ->
11481148
enough to use urlparse for it...! We were wasting precious CPU cycles.
11491149
Return used scheme url, lowercased."""
11501150
try:
1151-
scheme = url[: url.index(":", 1, max_length + 1)]
1151+
scheme = url[: url.index("://", 1, max_length + 1)]
11521152
except ValueError as e:
11531153
if default is not None:
11541154
return default
1155+
1156+
try:
1157+
outsider_scheme = url[: url.index(":", 1, max_length + 1)]
1158+
1159+
return outsider_scheme.lower()
1160+
except ValueError:
1161+
pass
1162+
11551163
raise MissingSchema(f"Invalid URL {url!r}: No scheme supplied. Perhaps you meant https://{url}?") from e
11561164

11571165
return scheme.lower()
@@ -1443,3 +1451,25 @@ def guess_json_utf(data: bytes) -> str | None:
14431451
return encoding_guess.encoding.replace("_", "-")
14441452

14451453
return None
1454+
1455+
1456+
@typing.overload
1457+
def merge_base_url(base_url: str | None, url: None) -> None: ...
1458+
1459+
1460+
@typing.overload
1461+
def merge_base_url(base_url: str | None, url: str) -> str: ...
1462+
1463+
1464+
def merge_base_url(base_url: str | None, url: str | None) -> str | None:
1465+
if base_url is None or url is None:
1466+
return url
1467+
1468+
if parse_scheme(url, default="") == "":
1469+
if base_url.endswith("/"):
1470+
base_url = base_url[:-1]
1471+
if url and not url.startswith("/"):
1472+
url = f"/{url}"
1473+
return base_url + url
1474+
1475+
return url

tests/test_requests.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2799,6 +2799,7 @@ def test_preparing_bad_url(self, url):
27992799
("http://httpbingo.org", "get", "http://httpbingo.org/get"),
28002800
("http://api.example.com", "/v1/users", "http://api.example.com/v1/users"),
28012801
("http://api.example.com", "v1/users", "http://api.example.com/v1/users"),
2802+
("https://example.com", "123456789/k:v", "https://example.com/123456789/k:v"),
28022803
],
28032804
)
28042805
def test_base_url_prepare(self, base_url, url, join_expected):

0 commit comments

Comments
 (0)