http_client_request 0.0.3__tar.gz → 0.0.5__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.
- {http_client_request-0.0.3 → http_client_request-0.0.5}/PKG-INFO +1 -1
- {http_client_request-0.0.3 → http_client_request-0.0.5}/http_client_request/__init__.py +59 -27
- {http_client_request-0.0.3 → http_client_request-0.0.5}/pyproject.toml +1 -1
- {http_client_request-0.0.3 → http_client_request-0.0.5}/http_client_request/py.typed +0 -0
- {http_client_request-0.0.3 → http_client_request-0.0.5}/readme.md +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# coding: utf-8
|
|
3
3
|
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
5
|
-
__version__ = (0, 0,
|
|
5
|
+
__version__ = (0, 0, 5)
|
|
6
6
|
__all__ = ["ConnectionPool", "request"]
|
|
7
7
|
|
|
8
8
|
from collections import defaultdict, deque, UserString
|
|
@@ -12,16 +12,17 @@ from http.cookiejar import CookieJar
|
|
|
12
12
|
from http.cookies import SimpleCookie
|
|
13
13
|
from inspect import signature
|
|
14
14
|
from os import PathLike
|
|
15
|
-
from socket import socket
|
|
15
|
+
from socket import socket
|
|
16
16
|
from types import EllipsisType
|
|
17
17
|
from typing import cast, overload, Any, Final, Literal
|
|
18
18
|
from urllib.error import HTTPError
|
|
19
19
|
from urllib.parse import urljoin, urlsplit, urlunsplit, ParseResult, SplitResult
|
|
20
|
+
from warnings import warn
|
|
20
21
|
|
|
21
22
|
from argtools import argcount
|
|
22
23
|
from cookietools import cookies_to_str, extract_cookies
|
|
23
24
|
from dicttools import get_all_items
|
|
24
|
-
from filewrap import
|
|
25
|
+
from filewrap import SupportsRead
|
|
25
26
|
from http_request import normalize_request_args, SupportsGeturl
|
|
26
27
|
from http_response import decompress_response, parse_response
|
|
27
28
|
from undefined import undefined, Undefined
|
|
@@ -90,6 +91,10 @@ class ConnectionPool:
|
|
|
90
91
|
for con in dq:
|
|
91
92
|
con.close()
|
|
92
93
|
|
|
94
|
+
def __repr__(self, /) -> str:
|
|
95
|
+
cls = type(self)
|
|
96
|
+
return f"{cls.__module__}.{cls.__qualname__}({self.pool!r})"
|
|
97
|
+
|
|
93
98
|
def get_connection(
|
|
94
99
|
self,
|
|
95
100
|
/,
|
|
@@ -110,11 +115,18 @@ class ConnectionPool:
|
|
|
110
115
|
con = dq.popleft()
|
|
111
116
|
except IndexError:
|
|
112
117
|
break
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
sock = con.sock
|
|
119
|
+
if not sock or getattr(sock, "_closed"):
|
|
120
|
+
con.connect()
|
|
121
|
+
else:
|
|
122
|
+
sock.setblocking(False)
|
|
123
|
+
try:
|
|
124
|
+
if socket.recv(sock, 1):
|
|
125
|
+
con.connect()
|
|
126
|
+
except BlockingIOError:
|
|
127
|
+
pass
|
|
128
|
+
finally:
|
|
129
|
+
sock.setblocking(True)
|
|
118
130
|
con.timeout = timeout
|
|
119
131
|
return con
|
|
120
132
|
if url.scheme == "https":
|
|
@@ -248,23 +260,32 @@ def request[T](
|
|
|
248
260
|
https_proxy = get_host_pair(proxies.get("https"))
|
|
249
261
|
else:
|
|
250
262
|
http_proxy = https_proxy = None
|
|
263
|
+
body: Any
|
|
251
264
|
if isinstance(data, PathLike):
|
|
252
|
-
data =
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
265
|
+
data = open(data, "rb")
|
|
266
|
+
if isinstance(data, SupportsRead):
|
|
267
|
+
request_args = normalize_request_args(
|
|
268
|
+
method=method,
|
|
269
|
+
url=url,
|
|
270
|
+
params=params,
|
|
271
|
+
headers=headers,
|
|
272
|
+
)
|
|
273
|
+
body = data
|
|
274
|
+
else:
|
|
275
|
+
request_args = normalize_request_args(
|
|
276
|
+
method=method,
|
|
277
|
+
url=url,
|
|
278
|
+
params=params,
|
|
279
|
+
data=data,
|
|
280
|
+
files=files,
|
|
281
|
+
json=json,
|
|
282
|
+
headers=headers,
|
|
283
|
+
)
|
|
284
|
+
body = request_args["data"]
|
|
264
285
|
method = request_args["method"]
|
|
265
286
|
url = request_args["url"]
|
|
266
|
-
body = cast(None | Buffer | Iterable[Buffer], request_args["data"])
|
|
267
287
|
headers_ = request_args["headers"]
|
|
288
|
+
headers_.setdefault("connection", "keep-alive")
|
|
268
289
|
need_set_cookie = "cookie" not in headers_
|
|
269
290
|
response_cookies = CookieJar()
|
|
270
291
|
connection: HTTPConnection | HTTPSConnection
|
|
@@ -294,7 +315,7 @@ def request[T](
|
|
|
294
315
|
headers_,
|
|
295
316
|
)
|
|
296
317
|
response = connection.getresponse()
|
|
297
|
-
if pool:
|
|
318
|
+
if pool and headers_.get("connection") == "keep-alive":
|
|
298
319
|
setattr(response, "pool", pool)
|
|
299
320
|
setattr(response, "connection", connection)
|
|
300
321
|
setattr(response, "url", url)
|
|
@@ -304,11 +325,21 @@ def request[T](
|
|
|
304
325
|
extract_cookies(cookies, url, response) # type: ignore
|
|
305
326
|
status_code = response.status
|
|
306
327
|
if 300 <= status_code < 400 and follow_redirects:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
328
|
+
if location := response.headers.get("location"):
|
|
329
|
+
url = request_args["url"] = urljoin(url, location)
|
|
330
|
+
if body and status_code in (307, 308):
|
|
331
|
+
if isinstance(body, SupportsRead):
|
|
332
|
+
try:
|
|
333
|
+
body.seek(0) # type: ignore
|
|
334
|
+
except Exception:
|
|
335
|
+
warn(f"unseekable-stream: {body!r}")
|
|
336
|
+
elif not isinstance(body, Buffer):
|
|
337
|
+
warn(f"failed to resend request body: {body!r}, when {status_code} redirects")
|
|
338
|
+
else:
|
|
339
|
+
if status_code == 303:
|
|
340
|
+
method = "GET"
|
|
341
|
+
body = None
|
|
342
|
+
continue
|
|
312
343
|
elif status_code >= 400 and raise_for_status:
|
|
313
344
|
raise HTTPError(
|
|
314
345
|
url,
|
|
@@ -335,3 +366,4 @@ def request[T](
|
|
|
335
366
|
return cast(Callable[[HTTPResponse, bytes], T], parse)(
|
|
336
367
|
response, content)
|
|
337
368
|
|
|
369
|
+
# TODO: 实现异步请求,非阻塞模式(sock.setblocking(False)),对于响应体的数据加载,使用 select 模块进行通知
|
|
File without changes
|
|
File without changes
|