http_client_request 0.0.8__tar.gz → 0.0.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: http_client_request
3
- Version: 0.0.8
4
- Summary: ttp.client request extension.
3
+ Version: 0.0.9
4
+ Summary: http.client request extension.
5
5
  Home-page: https://github.com/ChenyangGao/python-modules/tree/main/http_client_request
6
6
  License: MIT
7
7
  Keywords: http.client,request
@@ -22,10 +22,10 @@ Classifier: Topic :: Software Development :: Libraries
22
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
23
  Requires-Dist: http_response (>=0.0.9)
24
24
  Requires-Dist: python-argtools (>=0.0.2)
25
- Requires-Dist: python-cookietools (>=0.1.3)
25
+ Requires-Dist: python-cookietools (>=0.1.4)
26
26
  Requires-Dist: python-dicttools (>=0.0.4)
27
- Requires-Dist: python-filewrap (>=0.2.8)
28
- Requires-Dist: python-http_request (>=0.1.4)
27
+ Requires-Dist: python-filewrap (>=0.2.9)
28
+ Requires-Dist: python-http_request (>=0.1.6)
29
29
  Requires-Dist: python-property (>=0.0.3)
30
30
  Requires-Dist: python-undefined (>=0.0.3)
31
31
  Requires-Dist: urllib3
@@ -4,7 +4,7 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
7
- __version__ = (0, 0, 8)
7
+ __version__ = (0, 0, 9)
8
8
  __all__ = [
9
9
  "CONNECTION_POOL", "HTTPConnection", "HTTPSConnection", "HTTPResponse",
10
10
  "ConnectionPool", "request",
@@ -24,6 +24,7 @@ from http.cookies import BaseCookie
24
24
  from io import BufferedReader
25
25
  from inspect import signature
26
26
  from os import PathLike
27
+ from platform import system
27
28
  from select import select
28
29
  from socket import socket as Socket
29
30
  from ssl import SSLWantReadError
@@ -74,6 +75,68 @@ def sock_buf_readable(sock: Socket, /) -> bool:
74
75
  return bool(rlist)
75
76
 
76
77
 
78
+ def set_keepalive_linux(
79
+ sock: Socket,
80
+ after_idle_sec: int = 1,
81
+ interval_sec: int = 5,
82
+ max_fails: int = 5,
83
+ ):
84
+ """Set TCP keepalive on an open socket on Linux.
85
+ """
86
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
87
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec) # type: ignore
88
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
89
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)
90
+
91
+
92
+ def set_keepalive_osx(
93
+ sock: Socket,
94
+ after_idle_sec: int = 1,
95
+ interval_sec: int = 5,
96
+ max_fails: int = 5,
97
+ ):
98
+ """Set TCP keepalive on an open socket on MaxOSX.
99
+ """
100
+ sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
101
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPALIVE, after_idle_sec) # type: ignore
102
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)
103
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)
104
+
105
+
106
+ def set_keepalive_win(
107
+ sock: Socket,
108
+ after_idle_sec: int = 1,
109
+ interval_sec: int = 5,
110
+ max_fails: int = 5,
111
+ ):
112
+ """Set TCP keepalive on an open socket on Windows.
113
+ """
114
+ sock.ioctl(socket.SIO_KEEPALIVE_VALS, (1, after_idle_sec * 1000, interval_sec * 1000)) # type: ignore
115
+
116
+
117
+ def set_keepalive(
118
+ sock: Socket,
119
+ after_idle_sec: int = 1,
120
+ interval_sec: int = 3,
121
+ max_fails: int = 5,
122
+ ):
123
+ """Set TCP keepalive on an open socket on multiple platforms.
124
+
125
+ It activates after `after_idle_sec` second of idleness,
126
+ then sends a keepalive ping once every `interval_sec` seconds,
127
+ and closes the connection after `max_fails` failed ping (max_fails), or 15 seconds.
128
+ """
129
+ platform = system()
130
+ match platform:
131
+ case "Darwin":
132
+ return set_keepalive_osx(sock, after_idle_sec, interval_sec, max_fails)
133
+ case "Windows":
134
+ return set_keepalive_win(sock, after_idle_sec, interval_sec, max_fails)
135
+ case "Linux":
136
+ return set_keepalive_linux(sock, after_idle_sec, interval_sec, max_fails)
137
+ raise RuntimeError(f"unsupport platform {platform!r}")
138
+
139
+
77
140
  try:
78
141
  from fcntl import ioctl
79
142
  from termios import FIONREAD
@@ -220,6 +283,10 @@ class HTTPConnection(BaseHTTPConnection):
220
283
  def response(self, /) -> None | HTTPResponse:
221
284
  return self._HTTPConnection__response # type: ignore
222
285
 
286
+ def connect(self, /):
287
+ super().connect()
288
+ set_keepalive(self.sock)
289
+
223
290
  def getresponse(self, /) -> HTTPResponse:
224
291
  return cast(HTTPResponse, super().getresponse())
225
292
 
@@ -241,6 +308,10 @@ class HTTPSConnection(BaseHTTPSConnection):
241
308
  def response(self, /) -> None | HTTPResponse:
242
309
  return self._HTTPConnection__response # type: ignore
243
310
 
311
+ def connect(self, /):
312
+ super().connect()
313
+ set_keepalive(self.sock)
314
+
244
315
  def getresponse(self, /) -> HTTPResponse:
245
316
  return cast(HTTPResponse, super().getresponse())
246
317
 
@@ -1,7 +1,7 @@
1
1
  [tool.poetry]
2
2
  name = "http_client_request"
3
- version = "0.0.8"
4
- description = "ttp.client request extension."
3
+ version = "0.0.9"
4
+ description = "http.client request extension."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"
7
7
  readme = "readme.md"
@@ -29,10 +29,10 @@ include = [
29
29
  python = "^3.12"
30
30
  http_response = ">=0.0.9"
31
31
  python-argtools = ">=0.0.2"
32
- python-cookietools = ">=0.1.3"
32
+ python-cookietools = ">=0.1.4"
33
33
  python-dicttools = ">=0.0.4"
34
- python-filewrap = ">=0.2.8"
35
- python-http_request = ">=0.1.4"
34
+ python-filewrap = ">=0.2.9"
35
+ python-http_request = ">=0.1.6"
36
36
  python-property = ">=0.0.3"
37
37
  python-undefined = ">=0.0.3"
38
38
  urllib3 = "*"