Skip to content

Commit 2b0f99d

Browse files
authored
⚡ Lazy load the OCSP extension in order to improve the import performance (#124)
3.6.5 (2024-05-22) ------------------ **Fixed** - Support `localhost` as a valid domain for cookies. The standard library does not allow this special domain. Researches showed that a valid domain should have at least two dots (e.g. abc.com. and xyz.tld. but not com.). Public suffixes cannot be used as a cookie domain for security reasons, but as `localhost` isn't one we are explicitly allowing it. Reported in httpie/cli#602 `RequestsCookieJar` set a default policy that circumvent that limitation, if you specified a custom cookie policy then this fix won't be applied. **Changed** - Lazy load the OCSP extension in order to improve the import performance. **Removed** - Class variable `disable_thread` in `AsyncSession` that is no longer relevant since the native asyncio implementation. (PR #122)
1 parent 5fcfe0c commit 2b0f99d

File tree

6 files changed

+99
-65
lines changed

6 files changed

+99
-65
lines changed

HISTORY.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Release History
22
===============
33

4-
3.6.5 (2024-05-??)
4+
3.6.5 (2024-05-22)
55
------------------
66

77
**Fixed**
@@ -12,6 +12,12 @@ Release History
1212
`RequestsCookieJar` set a default policy that circumvent that limitation, if you specified a custom cookie policy then this
1313
fix won't be applied.
1414

15+
**Changed**
16+
- Lazy load the OCSP extension in order to improve the import performance.
17+
18+
**Removed**
19+
- Class variable `disable_thread` in `AsyncSession` that is no longer relevant since the native asyncio implementation. (PR #122)
20+
1521
3.6.4 (2024-05-16)
1622
------------------
1723

src/niquests/__init__.py

-4
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@
5454

5555
# urllib3's DependencyWarnings should be silenced.
5656
warnings.simplefilter("ignore", DependencyWarning)
57-
# Commonly happen on Windows due to some legacy root CA in
58-
# their trust store. They are aware of it, we silent the warning
59-
# yield by Cryptography to avoid producing undesired noise to end-users.
60-
warnings.filterwarnings("ignore", "Parsed a negative serial number")
6157

6258
# ruff: noqa: E402
6359
from . import utils

src/niquests/_async.py

+15-14
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
_swap_context,
7373
_deepcopy_ci,
7474
parse_scheme,
75+
is_ocsp_capable,
7576
)
7677
from .cookies import (
7778
RequestsCookieJar,
@@ -82,11 +83,6 @@
8283
from .structures import AsyncQuicSharedCache
8384
from .adapters import AsyncBaseAdapter, AsyncHTTPAdapter
8485

85-
try:
86-
from .extensions._async_ocsp import verify as ocsp_verify
87-
except ImportError:
88-
ocsp_verify = None # type: ignore[assignment]
89-
9086
# Preferred clock, based on which one is more accurate on a given system.
9187
if sys.platform == "win32":
9288
preferred_clock = time.perf_counter
@@ -323,21 +319,26 @@ async def on_post_connection(conn_info: ConnectionInfo) -> None:
323319
if (
324320
ptr_request.url
325321
and ptr_request.url.startswith("https://")
326-
and ocsp_verify is not None
327322
and kwargs["verify"]
323+
and is_ocsp_capable(conn_info)
328324
):
329325
strict_ocsp_enabled: bool = (
330326
os.environ.get("NIQUESTS_STRICT_OCSP", "0") != "0"
331327
)
332328

333-
await ocsp_verify(
334-
ptr_request,
335-
strict_ocsp_enabled,
336-
0.2 if not strict_ocsp_enabled else 1.0,
337-
kwargs["proxies"],
338-
resolver=self.resolver,
339-
happy_eyeballs=self._happy_eyeballs,
340-
)
329+
try:
330+
from .extensions._async_ocsp import verify as ocsp_verify
331+
except ImportError:
332+
pass
333+
else:
334+
await ocsp_verify(
335+
ptr_request,
336+
strict_ocsp_enabled,
337+
0.2 if not strict_ocsp_enabled else 1.0,
338+
kwargs["proxies"],
339+
resolver=self.resolver,
340+
happy_eyeballs=self._happy_eyeballs,
341+
)
341342

342343
# don't trigger pre_send for redirects
343344
if ptr_request == request:

src/niquests/adapters.py

+39-32
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,9 @@
152152
_swap_context,
153153
_deepcopy_ci,
154154
parse_scheme,
155+
is_ocsp_capable,
155156
)
156157

157-
try:
158-
from .extensions._ocsp import verify as ocsp_verify
159-
from .extensions._async_ocsp import verify as async_ocsp_verify
160-
except ImportError:
161-
ocsp_verify = None # type: ignore[assignment]
162-
163158
try:
164159
if HAS_LEGACY_URLLIB3 is False:
165160
from urllib3.contrib.socks import SOCKSProxyManager, AsyncSOCKSProxyManager
@@ -1041,23 +1036,28 @@ def on_post_connection(conn_info: ConnectionInfo) -> None:
10411036
if (
10421037
next_request.url
10431038
and next_request.url.startswith("https://")
1044-
and ocsp_verify is not None
10451039
and kwargs["verify"]
1040+
and is_ocsp_capable(conn_info)
10461041
):
10471042
strict_ocsp_enabled: bool = (
10481043
os.environ.get("NIQUESTS_STRICT_OCSP", "0") != "0"
10491044
)
10501045

1051-
ocsp_verify(
1052-
next_request,
1053-
strict_ocsp_enabled,
1054-
0.2 if not strict_ocsp_enabled else 1.0,
1055-
kwargs["proxies"],
1056-
self._resolver
1057-
if isinstance(self._resolver, BaseResolver)
1058-
else None,
1059-
self._happy_eyeballs,
1060-
)
1046+
try:
1047+
from .extensions._ocsp import verify as ocsp_verify
1048+
except ImportError:
1049+
pass
1050+
else:
1051+
ocsp_verify(
1052+
next_request,
1053+
strict_ocsp_enabled,
1054+
0.2 if not strict_ocsp_enabled else 1.0,
1055+
kwargs["proxies"],
1056+
self._resolver
1057+
if isinstance(self._resolver, BaseResolver)
1058+
else None,
1059+
self._happy_eyeballs,
1060+
)
10611061

10621062
kwargs["on_post_connection"] = on_post_connection
10631063

@@ -2015,23 +2015,30 @@ async def on_post_connection(conn_info: ConnectionInfo) -> None:
20152015
if (
20162016
next_request.url
20172017
and next_request.url.startswith("https://")
2018-
and ocsp_verify is not None
20192018
and kwargs["verify"]
2019+
and is_ocsp_capable(conn_info)
20202020
):
2021-
strict_ocsp_enabled: bool = (
2022-
os.environ.get("NIQUESTS_STRICT_OCSP", "0") != "0"
2023-
)
2024-
2025-
await async_ocsp_verify(
2026-
next_request,
2027-
strict_ocsp_enabled,
2028-
0.2 if not strict_ocsp_enabled else 1.0,
2029-
kwargs["proxies"],
2030-
self._resolver
2031-
if isinstance(self._resolver, AsyncBaseResolver)
2032-
else None,
2033-
self._happy_eyeballs,
2034-
)
2021+
try:
2022+
from .extensions._async_ocsp import (
2023+
verify as async_ocsp_verify,
2024+
)
2025+
except ImportError:
2026+
pass
2027+
else:
2028+
strict_ocsp_enabled: bool = (
2029+
os.environ.get("NIQUESTS_STRICT_OCSP", "0") != "0"
2030+
)
2031+
2032+
await async_ocsp_verify(
2033+
next_request,
2034+
strict_ocsp_enabled,
2035+
0.2 if not strict_ocsp_enabled else 1.0,
2036+
kwargs["proxies"],
2037+
self._resolver
2038+
if isinstance(self._resolver, AsyncBaseResolver)
2039+
else None,
2040+
self._happy_eyeballs,
2041+
)
20352042

20362043
kwargs["on_post_connection"] = on_post_connection
20372044

src/niquests/sessions.py

+15-14
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,6 @@
6868
)
6969
from .hooks import HOOKS, default_hooks, dispatch_hook
7070

71-
try:
72-
from .extensions._ocsp import verify as ocsp_verify
73-
except ImportError:
74-
ocsp_verify = None # type: ignore[assignment]
75-
7671
# formerly defined here, reexposed here for backward compatibility
7772
from .models import ( # noqa: F401
7873
DEFAULT_REDIRECT_LIMIT,
@@ -98,6 +93,7 @@
9893
create_resolver,
9994
_deepcopy_ci,
10095
parse_scheme,
96+
is_ocsp_capable,
10197
)
10298

10399
# Preferred clock, based on which one is more accurate on a given system.
@@ -1087,21 +1083,26 @@ def on_post_connection(conn_info: ConnectionInfo) -> None:
10871083
if (
10881084
ptr_request.url
10891085
and parse_scheme(ptr_request.url) == "https"
1090-
and ocsp_verify is not None
10911086
and kwargs["verify"]
1087+
and is_ocsp_capable(conn_info)
10921088
):
10931089
strict_ocsp_enabled: bool = (
10941090
os.environ.get("NIQUESTS_STRICT_OCSP", "0") != "0"
10951091
)
10961092

1097-
ocsp_verify(
1098-
ptr_request,
1099-
strict_ocsp_enabled,
1100-
0.2 if not strict_ocsp_enabled else 1.0,
1101-
kwargs["proxies"],
1102-
resolver=self.resolver,
1103-
happy_eyeballs=self._happy_eyeballs,
1104-
)
1093+
try:
1094+
from .extensions._ocsp import verify as ocsp_verify
1095+
except ImportError:
1096+
pass
1097+
else:
1098+
ocsp_verify(
1099+
ptr_request,
1100+
strict_ocsp_enabled,
1101+
0.2 if not strict_ocsp_enabled else 1.0,
1102+
kwargs["proxies"],
1103+
resolver=self.resolver,
1104+
happy_eyeballs=self._happy_eyeballs,
1105+
)
11051106

11061107
# don't trigger pre_send for redirects
11071108
if ptr_request == request:

src/niquests/utils.py

+23
Original file line numberDiff line numberDiff line change
@@ -1173,3 +1173,26 @@ def parse_scheme(url: str, default: str | None = None, max_length: int = 9) -> s
11731173
) from e
11741174

11751175
return scheme.lower()
1176+
1177+
1178+
def is_ocsp_capable(conn_info: ConnectionInfo | None) -> bool:
1179+
# we can't do anything in that case.
1180+
if (
1181+
conn_info is None
1182+
or conn_info.certificate_der is None
1183+
or conn_info.certificate_dict is None
1184+
):
1185+
return False
1186+
1187+
endpoints: list[str] = [ # type: ignore
1188+
# exclude non-HTTP endpoint. like ldap.
1189+
ep # type: ignore
1190+
for ep in list(conn_info.certificate_dict.get("OCSP", [])) # type: ignore
1191+
if ep.startswith("http://") # type: ignore
1192+
]
1193+
1194+
# well... not all issued certificate have a OCSP entry. e.g. mkcert.
1195+
if not endpoints:
1196+
return False
1197+
1198+
return True

0 commit comments

Comments
 (0)