tlsreq 0.1.0__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.
- tlsreq-0.1.0/LICENSE +21 -0
- tlsreq-0.1.0/PKG-INFO +82 -0
- tlsreq-0.1.0/README.md +45 -0
- tlsreq-0.1.0/pyproject.toml +54 -0
- tlsreq-0.1.0/setup.cfg +4 -0
- tlsreq-0.1.0/src/tlsreq/__init__.py +18 -0
- tlsreq-0.1.0/src/tlsreq/backends/__init__.py +61 -0
- tlsreq-0.1.0/src/tlsreq/backends/_httpx_patch.py +122 -0
- tlsreq-0.1.0/src/tlsreq/backends/_niquests_patch.py +327 -0
- tlsreq-0.1.0/src/tlsreq/backends/base.py +58 -0
- tlsreq-0.1.0/src/tlsreq/backends/curl_cffi.py +149 -0
- tlsreq-0.1.0/src/tlsreq/backends/httpx.py +262 -0
- tlsreq-0.1.0/src/tlsreq/backends/niquests.py +209 -0
- tlsreq-0.1.0/src/tlsreq/backends/wreq.py +241 -0
- tlsreq-0.1.0/src/tlsreq/chrome_h2.py +40 -0
- tlsreq-0.1.0/src/tlsreq/errors.py +14 -0
- tlsreq-0.1.0/src/tlsreq/fingerprints.py +131 -0
- tlsreq-0.1.0/src/tlsreq/install_utls.py +19 -0
- tlsreq-0.1.0/src/tlsreq/py.typed +0 -0
- tlsreq-0.1.0/src/tlsreq/response.py +119 -0
- tlsreq-0.1.0/src/tlsreq/session.py +203 -0
- tlsreq-0.1.0/src/tlsreq/utls_release.py +98 -0
- tlsreq-0.1.0/src/tlsreq.egg-info/PKG-INFO +82 -0
- tlsreq-0.1.0/src/tlsreq.egg-info/SOURCES.txt +30 -0
- tlsreq-0.1.0/src/tlsreq.egg-info/dependency_links.txt +1 -0
- tlsreq-0.1.0/src/tlsreq.egg-info/entry_points.txt +2 -0
- tlsreq-0.1.0/src/tlsreq.egg-info/requires.txt +20 -0
- tlsreq-0.1.0/src/tlsreq.egg-info/top_level.txt +1 -0
- tlsreq-0.1.0/tests/test_api.py +74 -0
- tlsreq-0.1.0/tests/test_fingerprints.py +28 -0
- tlsreq-0.1.0/tests/test_httpx_h2.py +66 -0
- tlsreq-0.1.0/tests/test_live_peet.py +91 -0
tlsreq-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 xiaoweigege
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
tlsreq-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tlsreq
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified async/sync HTTP client over curl_cffi, wreq, niquests+utls, and httpx+utls
|
|
5
|
+
Author: xiaoweigege
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/xiaoweigege/tlsreq
|
|
8
|
+
Project-URL: Repository, https://github.com/xiaoweigege/tlsreq
|
|
9
|
+
Project-URL: Issues, https://github.com/xiaoweigege/tlsreq/issues
|
|
10
|
+
Project-URL: utls (Chrome 152), https://github.com/xiaoweigege/utls/releases/tag/2026.9.4
|
|
11
|
+
Keywords: tls,http2,fingerprint,ja4,utls,curl_cffi,wreq
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Provides-Extra: curl-cffi
|
|
22
|
+
Requires-Dist: curl_cffi>=0.13; extra == "curl-cffi"
|
|
23
|
+
Provides-Extra: wreq
|
|
24
|
+
Requires-Dist: wreq>=0.12; extra == "wreq"
|
|
25
|
+
Provides-Extra: niquests
|
|
26
|
+
Requires-Dist: niquests>=3.0; extra == "niquests"
|
|
27
|
+
Provides-Extra: httpx
|
|
28
|
+
Requires-Dist: httpx>=0.27; extra == "httpx"
|
|
29
|
+
Requires-Dist: httpcore>=1.0; extra == "httpx"
|
|
30
|
+
Requires-Dist: h2>=4.1; extra == "httpx"
|
|
31
|
+
Provides-Extra: all
|
|
32
|
+
Requires-Dist: tlsreq[curl_cffi]; extra == "all"
|
|
33
|
+
Requires-Dist: tlsreq[wreq]; extra == "all"
|
|
34
|
+
Requires-Dist: tlsreq[niquests]; extra == "all"
|
|
35
|
+
Requires-Dist: tlsreq[httpx]; extra == "all"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# tlsreq
|
|
39
|
+
|
|
40
|
+
把 `curl_cffi`、`wreq`、`niquests+utls`、`httpx+utls` 收成同一套 Session API。换库只改 `backend` 和 `impersonate`。
|
|
41
|
+
|
|
42
|
+
GitHub: https://github.com/xiaoweigege/tlsreq
|
|
43
|
+
|
|
44
|
+
## 安装
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install tlsreq
|
|
48
|
+
pip install "tlsreq[httpx]" # 或 niquests / wreq / curl_cffi / all
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Chrome 152 不在 PyPI 的 `utls` 里。httpx / niquests 需要再装 GitHub 2026.9.4:
|
|
52
|
+
|
|
53
|
+
https://github.com/xiaoweigege/utls/releases/tag/2026.9.4
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python -m tlsreq.install_utls
|
|
57
|
+
# 或 tlsreq-install-utls
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## 用法
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from tlsreq import AsyncSession, Session
|
|
64
|
+
|
|
65
|
+
async with AsyncSession(
|
|
66
|
+
backend="niquests", # curl_cffi / wreq / niquests / httpx
|
|
67
|
+
impersonate="chrome152",
|
|
68
|
+
proxy="http://user:pass@host:port",
|
|
69
|
+
timeout=30,
|
|
70
|
+
extra={"pool_maxsize": 1}, # 只传给当前库
|
|
71
|
+
) as s:
|
|
72
|
+
r = await s.get(url, headers=headers)
|
|
73
|
+
print(r.status_code, r.text, r.cookies, r.http_version)
|
|
74
|
+
r = await s.post(url, data=body, headers=headers, header_order=["user-agent", "accept"])
|
|
75
|
+
|
|
76
|
+
s = Session(backend="wreq", impersonate="chrome149", proxy=proxy)
|
|
77
|
+
r = s.get(url, headers=headers)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
`extra=` 会合并进底层构造函数或单次请求,后写覆盖统一层映射。底层 client 在 `s.raw`。
|
|
81
|
+
|
|
82
|
+
niquests / httpx 默认带 Chrome 152 的 HTTP/2 SETTINGS、窗口和 HEADERS Priority,JA4 / peetprint / akamai_fingerprint 对齐真机。
|
tlsreq-0.1.0/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# tlsreq
|
|
2
|
+
|
|
3
|
+
把 `curl_cffi`、`wreq`、`niquests+utls`、`httpx+utls` 收成同一套 Session API。换库只改 `backend` 和 `impersonate`。
|
|
4
|
+
|
|
5
|
+
GitHub: https://github.com/xiaoweigege/tlsreq
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install tlsreq
|
|
11
|
+
pip install "tlsreq[httpx]" # 或 niquests / wreq / curl_cffi / all
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Chrome 152 不在 PyPI 的 `utls` 里。httpx / niquests 需要再装 GitHub 2026.9.4:
|
|
15
|
+
|
|
16
|
+
https://github.com/xiaoweigege/utls/releases/tag/2026.9.4
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
python -m tlsreq.install_utls
|
|
20
|
+
# 或 tlsreq-install-utls
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 用法
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from tlsreq import AsyncSession, Session
|
|
27
|
+
|
|
28
|
+
async with AsyncSession(
|
|
29
|
+
backend="niquests", # curl_cffi / wreq / niquests / httpx
|
|
30
|
+
impersonate="chrome152",
|
|
31
|
+
proxy="http://user:pass@host:port",
|
|
32
|
+
timeout=30,
|
|
33
|
+
extra={"pool_maxsize": 1}, # 只传给当前库
|
|
34
|
+
) as s:
|
|
35
|
+
r = await s.get(url, headers=headers)
|
|
36
|
+
print(r.status_code, r.text, r.cookies, r.http_version)
|
|
37
|
+
r = await s.post(url, data=body, headers=headers, header_order=["user-agent", "accept"])
|
|
38
|
+
|
|
39
|
+
s = Session(backend="wreq", impersonate="chrome149", proxy=proxy)
|
|
40
|
+
r = s.get(url, headers=headers)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`extra=` 会合并进底层构造函数或单次请求,后写覆盖统一层映射。底层 client 在 `s.raw`。
|
|
44
|
+
|
|
45
|
+
niquests / httpx 默认带 Chrome 152 的 HTTP/2 SETTINGS、窗口和 HEADERS Priority,JA4 / peetprint / akamai_fingerprint 对齐真机。
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "tlsreq"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Unified async/sync HTTP client over curl_cffi, wreq, niquests+utls, and httpx+utls"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{name = "xiaoweigege"}]
|
|
13
|
+
keywords = ["tls", "http2", "fingerprint", "ja4", "utls", "curl_cffi", "wreq"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3.9",
|
|
17
|
+
"Programming Language :: Python :: 3.10",
|
|
18
|
+
"Programming Language :: Python :: 3.11",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Typing :: Typed",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
# Chrome 152 不在 PyPI utls。装完 extras 后执行: python -m tlsreq.install_utls
|
|
25
|
+
curl_cffi = ["curl_cffi>=0.13"]
|
|
26
|
+
wreq = ["wreq>=0.12"]
|
|
27
|
+
niquests = ["niquests>=3.0"]
|
|
28
|
+
httpx = ["httpx>=0.27", "httpcore>=1.0", "h2>=4.1"]
|
|
29
|
+
all = [
|
|
30
|
+
"tlsreq[curl_cffi]",
|
|
31
|
+
"tlsreq[wreq]",
|
|
32
|
+
"tlsreq[niquests]",
|
|
33
|
+
"tlsreq[httpx]",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
tlsreq-install-utls = "tlsreq.install_utls:main"
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/xiaoweigege/tlsreq"
|
|
41
|
+
Repository = "https://github.com/xiaoweigege/tlsreq"
|
|
42
|
+
Issues = "https://github.com/xiaoweigege/tlsreq/issues"
|
|
43
|
+
"utls (Chrome 152)" = "https://github.com/xiaoweigege/utls/releases/tag/2026.9.4"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools]
|
|
46
|
+
package-dir = {"" = "src"}
|
|
47
|
+
license-files = ["LICENSE"]
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.packages.find]
|
|
50
|
+
where = ["src"]
|
|
51
|
+
include = ["tlsreq*"]
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.package-data]
|
|
54
|
+
tlsreq = ["py.typed"]
|
tlsreq-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .errors import BackendNotInstalled, TlsReqError, UnknownBackend, UnknownFingerprint
|
|
2
|
+
from .response import Response
|
|
3
|
+
from .session import AsyncSession, Session
|
|
4
|
+
from .utls_release import UTLS_RELEASE, UTLS_RELEASE_PAGE
|
|
5
|
+
|
|
6
|
+
__version__ = "0.1.0"
|
|
7
|
+
__all__ = [
|
|
8
|
+
"AsyncSession",
|
|
9
|
+
"Session",
|
|
10
|
+
"Response",
|
|
11
|
+
"TlsReqError",
|
|
12
|
+
"UnknownBackend",
|
|
13
|
+
"BackendNotInstalled",
|
|
14
|
+
"UnknownFingerprint",
|
|
15
|
+
"UTLS_RELEASE",
|
|
16
|
+
"UTLS_RELEASE_PAGE",
|
|
17
|
+
"__version__",
|
|
18
|
+
]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
from ..errors import UnknownBackend
|
|
6
|
+
from .base import AsyncBackend, SyncBackend
|
|
7
|
+
|
|
8
|
+
_ALIASES = {
|
|
9
|
+
"curl": "curl_cffi",
|
|
10
|
+
"cffi": "curl_cffi",
|
|
11
|
+
"nirequest": "niquests",
|
|
12
|
+
"nirequests": "niquests",
|
|
13
|
+
"nio": "niquests",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _normalize_backend(name: str) -> str:
|
|
18
|
+
key = name.strip().lower().replace("-", "_")
|
|
19
|
+
return _ALIASES.get(key, key)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def create_sync_backend(
|
|
23
|
+
backend: str,
|
|
24
|
+
impersonate: Optional[str] = None,
|
|
25
|
+
**kwargs: Any,
|
|
26
|
+
) -> SyncBackend:
|
|
27
|
+
name = _normalize_backend(backend)
|
|
28
|
+
if name == "curl_cffi":
|
|
29
|
+
from .curl_cffi import CurlCffiSync
|
|
30
|
+
return CurlCffiSync(impersonate=impersonate, **kwargs)
|
|
31
|
+
if name == "wreq":
|
|
32
|
+
from .wreq import WreqSync
|
|
33
|
+
return WreqSync(impersonate=impersonate, **kwargs)
|
|
34
|
+
if name == "niquests":
|
|
35
|
+
from .niquests import NiquestsSync
|
|
36
|
+
return NiquestsSync(impersonate=impersonate, **kwargs)
|
|
37
|
+
if name == "httpx":
|
|
38
|
+
from .httpx import HttpxSync
|
|
39
|
+
return HttpxSync(impersonate=impersonate, **kwargs)
|
|
40
|
+
raise UnknownBackend(f"未知 backend {backend!r}。可选: curl_cffi, wreq, niquests, httpx")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def create_async_backend(
|
|
44
|
+
backend: str,
|
|
45
|
+
impersonate: Optional[str] = None,
|
|
46
|
+
**kwargs: Any,
|
|
47
|
+
) -> AsyncBackend:
|
|
48
|
+
name = _normalize_backend(backend)
|
|
49
|
+
if name == "curl_cffi":
|
|
50
|
+
from .curl_cffi import CurlCffiAsync
|
|
51
|
+
return CurlCffiAsync(impersonate=impersonate, **kwargs)
|
|
52
|
+
if name == "wreq":
|
|
53
|
+
from .wreq import WreqAsync
|
|
54
|
+
return WreqAsync(impersonate=impersonate, **kwargs)
|
|
55
|
+
if name == "niquests":
|
|
56
|
+
from .niquests import NiquestsAsync
|
|
57
|
+
return NiquestsAsync(impersonate=impersonate, **kwargs)
|
|
58
|
+
if name == "httpx":
|
|
59
|
+
from .httpx import HttpxAsync
|
|
60
|
+
return HttpxAsync(impersonate=impersonate, **kwargs)
|
|
61
|
+
raise UnknownBackend(f"未知 backend {backend!r}。可选: curl_cffi, wreq, niquests, httpx")
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""httpcore/h2:Chrome 152 SETTINGS、连接窗口、HEADERS Priority。"""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import collections
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import h2.settings
|
|
8
|
+
|
|
9
|
+
from ..chrome_h2 import (
|
|
10
|
+
CONNECTION_WINDOW_INCREMENT,
|
|
11
|
+
ENABLE_PUSH,
|
|
12
|
+
H2_HOP_BY_HOP,
|
|
13
|
+
HEADER_TABLE_SIZE,
|
|
14
|
+
INITIAL_WINDOW_SIZE,
|
|
15
|
+
MAX_HEADER_LIST_SIZE,
|
|
16
|
+
PRIORITY_DEPENDS_ON,
|
|
17
|
+
PRIORITY_EXCLUSIVE,
|
|
18
|
+
PRIORITY_WEIGHT,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
_PATCHED = False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _chrome_local_settings() -> h2.settings.Settings:
|
|
25
|
+
settings = h2.settings.Settings(
|
|
26
|
+
client=True,
|
|
27
|
+
initial_values={
|
|
28
|
+
h2.settings.SettingCodes.HEADER_TABLE_SIZE: HEADER_TABLE_SIZE,
|
|
29
|
+
h2.settings.SettingCodes.ENABLE_PUSH: ENABLE_PUSH,
|
|
30
|
+
h2.settings.SettingCodes.INITIAL_WINDOW_SIZE: INITIAL_WINDOW_SIZE,
|
|
31
|
+
h2.settings.SettingCodes.MAX_HEADER_LIST_SIZE: MAX_HEADER_LIST_SIZE,
|
|
32
|
+
h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: 100,
|
|
33
|
+
},
|
|
34
|
+
)
|
|
35
|
+
del settings[h2.settings.SettingCodes.MAX_FRAME_SIZE]
|
|
36
|
+
del settings[h2.settings.SettingCodes.ENABLE_CONNECT_PROTOCOL]
|
|
37
|
+
del settings[h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS]
|
|
38
|
+
return settings
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _restore_local_only(settings: h2.settings.Settings) -> None:
|
|
42
|
+
"""SETTINGS 帧发出后再补回 h2/httpcore 内部会读的项,避免再发一帧。"""
|
|
43
|
+
codes = h2.settings.SettingCodes
|
|
44
|
+
settings._settings.setdefault(codes.MAX_CONCURRENT_STREAMS, collections.deque([100]))
|
|
45
|
+
settings._settings.setdefault(codes.MAX_FRAME_SIZE, collections.deque([16384]))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def patch_httpcore_chrome_h2() -> None:
|
|
49
|
+
global _PATCHED
|
|
50
|
+
if _PATCHED:
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
from httpcore._async.http2 import AsyncHTTP2Connection
|
|
54
|
+
from httpcore._async.http2 import has_body_headers as async_has_body_headers
|
|
55
|
+
from httpcore._sync.http2 import HTTP2Connection
|
|
56
|
+
from httpcore._sync.http2 import has_body_headers as sync_has_body_headers
|
|
57
|
+
|
|
58
|
+
async def async_send_connection_init(self: Any, request: Any) -> None:
|
|
59
|
+
self._h2_state.local_settings = _chrome_local_settings()
|
|
60
|
+
self._h2_state.initiate_connection()
|
|
61
|
+
_restore_local_only(self._h2_state.local_settings)
|
|
62
|
+
self._h2_state.increment_flow_control_window(CONNECTION_WINDOW_INCREMENT)
|
|
63
|
+
await self._write_outgoing_data(request)
|
|
64
|
+
|
|
65
|
+
def sync_send_connection_init(self: Any, request: Any) -> None:
|
|
66
|
+
self._h2_state.local_settings = _chrome_local_settings()
|
|
67
|
+
self._h2_state.initiate_connection()
|
|
68
|
+
_restore_local_only(self._h2_state.local_settings)
|
|
69
|
+
self._h2_state.increment_flow_control_window(CONNECTION_WINDOW_INCREMENT)
|
|
70
|
+
self._write_outgoing_data(request)
|
|
71
|
+
|
|
72
|
+
async def async_send_request_headers(self: Any, request: Any, stream_id: int) -> None:
|
|
73
|
+
end_stream = not async_has_body_headers(request)
|
|
74
|
+
authority = [value for key, value in request.headers if key.lower() == b"host"][0]
|
|
75
|
+
headers = [
|
|
76
|
+
(b":method", request.method),
|
|
77
|
+
(b":authority", authority),
|
|
78
|
+
(b":scheme", request.url.scheme),
|
|
79
|
+
(b":path", request.url.target),
|
|
80
|
+
] + [
|
|
81
|
+
(key.lower(), value)
|
|
82
|
+
for key, value in request.headers
|
|
83
|
+
if key.lower() not in H2_HOP_BY_HOP
|
|
84
|
+
]
|
|
85
|
+
self._h2_state.send_headers(
|
|
86
|
+
stream_id,
|
|
87
|
+
headers,
|
|
88
|
+
end_stream=end_stream,
|
|
89
|
+
priority_weight=PRIORITY_WEIGHT,
|
|
90
|
+
priority_depends_on=PRIORITY_DEPENDS_ON,
|
|
91
|
+
priority_exclusive=PRIORITY_EXCLUSIVE,
|
|
92
|
+
)
|
|
93
|
+
await self._write_outgoing_data(request)
|
|
94
|
+
|
|
95
|
+
def sync_send_request_headers(self: Any, request: Any, stream_id: int) -> None:
|
|
96
|
+
end_stream = not sync_has_body_headers(request)
|
|
97
|
+
authority = [value for key, value in request.headers if key.lower() == b"host"][0]
|
|
98
|
+
headers = [
|
|
99
|
+
(b":method", request.method),
|
|
100
|
+
(b":authority", authority),
|
|
101
|
+
(b":scheme", request.url.scheme),
|
|
102
|
+
(b":path", request.url.target),
|
|
103
|
+
] + [
|
|
104
|
+
(key.lower(), value)
|
|
105
|
+
for key, value in request.headers
|
|
106
|
+
if key.lower() not in H2_HOP_BY_HOP
|
|
107
|
+
]
|
|
108
|
+
self._h2_state.send_headers(
|
|
109
|
+
stream_id,
|
|
110
|
+
headers,
|
|
111
|
+
end_stream=end_stream,
|
|
112
|
+
priority_weight=PRIORITY_WEIGHT,
|
|
113
|
+
priority_depends_on=PRIORITY_DEPENDS_ON,
|
|
114
|
+
priority_exclusive=PRIORITY_EXCLUSIVE,
|
|
115
|
+
)
|
|
116
|
+
self._write_outgoing_data(request)
|
|
117
|
+
|
|
118
|
+
AsyncHTTP2Connection._send_connection_init = async_send_connection_init
|
|
119
|
+
AsyncHTTP2Connection._send_request_headers = async_send_request_headers
|
|
120
|
+
HTTP2Connection._send_connection_init = sync_send_connection_init
|
|
121
|
+
HTTP2Connection._send_request_headers = sync_send_request_headers
|
|
122
|
+
_PATCHED = True
|