Skip to main content

rex-tls

rex-tls 是一个面向 Python 的原生移动端 TLS/HTTP 客户端。它提供接近 requests 的调用方式,并在 Rust 原生扩展中实现 TLS、HTTP/1.1、HTTP/2 以及 Chrome Android 的 HTTP/3 网络路径。

项目使用 vendored BoringSSL,不依赖 wreqreqwestcurl 或系统 OpenSSL。当前版本已经发布到 PyPI: rex-tls 0.1.1

适用范围:协议兼容测试、移动客户端互操作、经过授权的网络研究和普通 HTTP 客户端开发。本项目不包含验证码求解、WAF 绕过或站点专用规避逻辑。

支持的 profile

profile 协议 设备验证基线
chrome_android_149 TLS + HTTP/1.1 + HTTP/2 + HTTP/3 Pixel 4 / Android 11 / Chrome 149.0.7827.200
chrome_android_150 TLS + HTTP/1.1 + HTTP/2 + HTTP/3 Pixel 4 / Android 11 / Chrome 150.0.7871.63
okhttp_4.12 TLS + HTTP/1.1 + HTTP/2 Pixel 4 / Android 11 / OkHttp 4.12.0

三套 profile 均完成真实设备 L4 行为验证。OkHttp 4.12 不声明 HTTP/3 能力。

安装

python -m pip install rex-tls==0.1.1

要求 Python 3.9 或更高版本。0.1.1 提供以下预编译 wheel:

  • Windows x86-64
  • Linux manylinux 2.28 x86-64
  • macOS x86-64
  • macOS ARM64

首选导入名是 rex_tlsmobile_tls 仅作为兼容入口保留。

快速开始

import rex_tls

response = rex_tls.get(
    "https://example.com/",
    profile="chrome_android_149",
    params={"page": 1},
    timeout=30,
)

response.raise_for_status()
print(response.status_code)       # 200
print(response.http_version)      # HTTP/1.1、HTTP/2 或 HTTP/3
print(response.text)

发送 JSON:

import rex_tls

response = rex_tls.post(
    "https://api.example.com/items",
    profile="okhttp_4.12",
    json={"name": "测试", "enabled": True},
)
print(response.json())

推荐:复用 Session

Session 会复用连接、Cookie 和 TLS 会话,连续请求时应优先使用:

from rex_tls import Session

with Session(
    "chrome_android_150",
    timeout=20,
    follow_redirects=True,
    max_redirects=10,
) as session:
    session.headers.update({"x-client-id": "demo"})

    first = session.get("https://example.com/start")
    second = session.get("https://example.com/next")

    print(first.connection_reused)
    print(second.connection_reused)

请求参数与请求体

from rex_tls import Session

with Session("okhttp_4.12") as session:
    # 查询参数
    r1 = session.get(
        "https://api.example.com/search",
        params={"q": "中文", "page": 2},
    )

    # application/x-www-form-urlencoded
    r2 = session.post(
        "https://api.example.com/form",
        data={"username": "demo", "remember": "1"},
    )

    # application/json; charset=utf-8
    r3 = session.post(
        "https://api.example.com/json",
        json={"message": "你好"},
    )

    # 原始内容
    r4 = session.put(
        "https://api.example.com/raw",
        content=b"raw bytes",
        headers={"content-type": "application/octet-stream"},
    )

contentdatajson 三者互斥。支持 getoptionsheadpostputpatchdelete 以及通用 request

请求头顺序

底层会自动按选定 profile 的设备规则排列请求头:

  • 覆盖默认头时,头部保留在真实设备对应的槽位;
  • 新增的非默认头在 profile 默认头之后,按调用者传入顺序排列;
  • 需要重复同名头时,可传入元组列表;
  • Session 级请求头会先与单次请求头进行大小写不敏感合并;
  • Host、HTTP/2/HTTP/3 伪头及 Content-Length 由底层安全生成。
from rex_tls import Session

with Session("chrome_android_149") as session:
    session.headers.update({"accept-language": "zh-CN,zh;q=0.9"})
    response = session.get(
        "https://example.com/",
        headers=[
            ("user-agent", "My-Mobile-Client/1.0"),
            ("accept", "application/json"),
            ("x-trace-a", "1"),
            ("x-trace-b", "2"),
        ],
    )

不需要手工复制全部 Chrome/OkHttp 默认请求头。只传入需要覆盖或追加的头即可。

HTTP 代理

代理映射与 requests 风格相近:

from rex_tls import Session

proxies = {
    "http": "http://user:password@proxy.example:8080",
    "https": "http://user:password@proxy.example:8080",
    "no_proxy": ".internal.example,127.0.0.1",
}

with Session("okhttp_4.12", proxies=proxies) as session:
    response = session.get("https://example.com/")

也可在单次请求覆盖代理:

response = session.get(
    "https://example.com/",
    proxies={"https": "http://other-proxy.example:3128"},
)

# 显式为这一次请求禁用 HTTPS 代理
direct = session.get("https://example.com/", proxies={"https": None})

从环境变量读取 HTTP_PROXYHTTPS_PROXYALL_PROXYNO_PROXY

with Session("chrome_android_149", trust_env=True) as session:
    response = session.get("https://example.com/")

当前代理能力边界:

  • 支持 http:// forward proxy 和 HTTPS 目标的 HTTP CONNECT;
  • 支持代理 URL 中的 Basic 用户名/密码;
  • 不支持 https:// proxy、SOCKS、PAC、NTLM/Digest 或 MASQUE;
  • 代理失败不会静默改成直连;
  • 不要把 Proxy-Authorization 放入源站请求头,凭据应写在代理 URL 中;
  • 传统 HTTP CONNECT 不能承载 QUIC,因此代理场景不使用 HTTP/3。

HTTP/3

HTTP/3 只适用于两个显式 Chrome profile,并且只支持 HTTPS URL:

from rex_tls import Session

# 优先尝试 HTTP/3,并允许按协议策略回退到 H2/H1
with Session("chrome_android_149", http3="auto") as session:
    response = session.get("https://example.com/")

# 只允许 HTTP/3;无法建立 H3 时直接报错
with Session("chrome_android_150", http3="only") as session:
    response = session.get("https://example.com/")

http3 可取 "off""auto""only",默认是 "off"。使用 H3 时必须写完整的 chrome_android_149chrome_android_150,不要使用别名。 okhttp_4.12 不支持 H3。

异步接口

import asyncio
from rex_tls import AsyncSession

async def main() -> None:
    async with AsyncSession("okhttp_4.12") as session:
        response = await session.get("https://example.com/", timeout=15)
        response.raise_for_status()
        print(response.status_code, response.http_version)

asyncio.run(main())

取消 asyncio Task 时,客户端会尝试取消对应的原生请求。

内置并发池

SessionPool 面向多线程,AsyncSessionPool 面向 asyncio。每个池成员拥有独立的 TLS/HTTP 连接状态,因此最多可以同时运行 max_connections 个请求;超过上限的请求会 排队。当前并发来自多条连接,不表示在单条 HTTP/2 或 HTTP/3 连接内多路复用。

import asyncio
from rex_tls import AsyncSessionPool

async def main() -> None:
    async with AsyncSessionPool(
        "chrome_android_150",
        max_connections=16,
        session_mode="shared",
        proxy="http://user:password@proxy.example:8080",
    ) as pool:
        pool.headers["x-client"] = "pool-demo"
        responses = await asyncio.gather(
            *(pool.get(f"https://example.com/?id={index}") for index in range(100))
        )
        print([response.status_code for response in responses])

asyncio.run(main())

池的可变会话状态有两种模式:

  • session_mode="shared"(默认):所有连接共享默认 Header、代理配置和线程安全 CookieJar,整个池表现为一个登录会话;
  • session_mode="isolated":每个连接的 Header、代理配置和 Cookie 均完全独立,适合 多账号或任务隔离。需要连续使用同一身份时,用 async with pool.acquire() as session: 固定租用一个成员。
async with AsyncSessionPool(
    "okhttp_4.12", max_connections=8, session_mode="isolated"
) as pool:
    async with pool.acquire() as session:
        session.headers["authorization"] = "Bearer account-one"
        session.proxies["https"] = "http://account-one.proxy:8080"
        session.cookies.set("account", "one")
        first = await session.get("https://example.com/first")
        second = await session.get("https://example.com/second")

同步代码可以在线程中共享一个池:

from concurrent.futures import ThreadPoolExecutor
from rex_tls import SessionPool

with SessionPool("okhttp_4.12", max_connections=8) as pool:
    with ThreadPoolExecutor(max_workers=32) as executor:
        responses = list(executor.map(pool.get, urls))

pool_timeout= 只控制等待空闲池成员的时间;timeout= 仍控制网络请求。池级 headersproxiestrust_env 会应用到所有成员。

Response 对象

常用属性和方法:

response.status_code       # int
response.reason            # str
response.url               # 最终 URL
response.http_version      # HTTP/1.1、HTTP/2 或 HTTP/3
response.headers           # 大小写不敏感的响应头映射
response.headers.raw       # 保留顺序及重复项的 tuple
response.headers.get_all("set-cookie")
response.content           # bytes
response.text              # 按 charset 解码后的 str
response.json()            # JSON 解码
response.ok                # status_code < 400
response.elapsed_seconds
response.local_address
response.remote_address
response.connection_reused
response.tls_session_reused
response.raise_for_status()

TLS 证书验证

默认使用 certifi CA 包并验证证书与主机名:

from rex_tls import Session

# 默认验证
session = Session("chrome_android_149", verify=True)

# 使用自定义 CA bundle
session = Session("chrome_android_149", verify="/path/to/ca-bundle.pem")

# 仅用于受控测试环境
session = Session("chrome_android_149", verify=False)

异常处理

import rex_tls

try:
    response = rex_tls.get(
        "https://example.com/",
        profile="chrome_android_149",
        timeout=10,
    )
    response.raise_for_status()
except rex_tls.RequestError as exc:
    print(f"请求失败: {exc}")
except rex_tls.MobileTLSError as exc:
    print(f"原生客户端错误: {exc}")

查询运行时能力

import rex_tls

print(rex_tls.profiles())
print(rex_tls.profile_info("chrome_android_149"))
print(dict(rex_tls.native_versions()))

与 requests 的差异

rex-tls 对齐的是常用调用方式,不是 requests 的完全兼容替代:

  • 当前没有公开的 authhooksadaptersmount
  • Session.cookies 提供常用的 RequestsCookieJar 风格 set/get/get_dict/update/clear 接口,并支持 domain、path、Secure 和 expires;单次请求也支持 cookies=, 显式 Cookie 请求头优先;
  • Session.headersSession.proxies 是可修改字典;
  • Cookie、重定向、连接池与 TLS 会话由原生 Session 管理;
  • verify、代理类型和 HTTP/3 有更严格的安全约束;
  • 请求头最终顺序由 profile 决定,而不是简单照搬 Python 字典顺序。

完整中文手册见 中文使用指南

开发与验证

python -m pip install -e ".[dev]"
python -m pytest -m "not network" -q

架构和证据说明位于 docs/;发布工作流见 docs/32-github-ci-and-publishing.md,本机四库性能 基准见 docs/34-performance.md

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rex_tls-0.1.1.tar.gz (5.7 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rex_tls-0.1.1-cp39-abi3-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.9+Windows x86-64

rex_tls-0.1.1-cp39-abi3-manylinux_2_28_x86_64.whl (2.0 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ x86-64

rex_tls-0.1.1-cp39-abi3-macosx_11_0_arm64.whl (1.8 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

rex_tls-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file rex_tls-0.1.1.tar.gz.

File metadata

  • Download URL: rex_tls-0.1.1.tar.gz
  • Upload date:
  • Size: 5.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for rex_tls-0.1.1.tar.gz
Algorithm Hash digest
SHA256 85085f243e75eefd0a6783b71f5efe5111c0ae0863311c1bae3c2e607fa7c022
MD5 d059488c08506dd3af3da70bd668ea01
BLAKE2b-256 efd7e6ac59efd1d43c7a3fd46ee84116ecc6c35433ea3c361ccbf512f6db27e3

See more details on using hashes here.

File details

Details for the file rex_tls-0.1.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: rex_tls-0.1.1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.9

File hashes

Hashes for rex_tls-0.1.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a69172bad2d50aa72a050996264da06ee51ef59a3922619f478db30aca60c1ce
MD5 3ab9cfa3834debdc36d4881914a37a31
BLAKE2b-256 430bfa86b35db04170ef71de8e84d2223d1d60a7ebf4e6f94f0059b84898fbd9

See more details on using hashes here.

File details

Details for the file rex_tls-0.1.1-cp39-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rex_tls-0.1.1-cp39-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 07d0f85cb6cfa9112fc78eaec3f00078dd12aa2b9c79ec54ceb820557449d8db
MD5 1229ec416837bd0e552ba8241d8d9b3b
BLAKE2b-256 c472272d82ceeb93cba50383bf17af99d634d59ae7ca9666f2a92980a3cd4e64

See more details on using hashes here.

File details

Details for the file rex_tls-0.1.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rex_tls-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9f898ba11ee6f039aba21c1d0f21a0e1e4012b7c2376dcc17022f72b9126f89f
MD5 61086e5b64a7a559dbee8633ff8182fd
BLAKE2b-256 94d5b042961bf8f9c129979ebb240a08d080c90e5b4378c0f4e42186630f0c71

See more details on using hashes here.

File details

Details for the file rex_tls-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for rex_tls-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c6ce3bb2a7ef9b3d4be3135ea6b9467692ceffc3507d511b5cfdeda6ea0695e5
MD5 a50886d84417bf1a902b905a25986b40
BLAKE2b-256 9f805e9e6e8d9c5341ea4881174da134de69b160b7f251a676e7f0d136fbd5e2

See more details on using hashes here.

Release history Release notifications | RSS feed

2.24.1

2 files

2.24.0

2 files

2.23.0

2 files

2.22.0

2 files

2.21.0

2 files

2.20.2

2 files

2.20.1

2 files

2.20.0

2 files

2.19.2

2 files

2.19.1

2 files

2.19.0

4 files

2.18.1

4 files

2.18.0

2 files

2.17.0

2 files

2.16.3

2 files

2.16.2

2 files

2.16.1

2 files

2.16.0

2 files

2.15.2

2 files

2.15.1

2 files

2.15.0

2 files

2.14.0

2 files

2.13.0

2 files

2.12.0

2 files

2.11.0

2 files

2.10.1

2 files

2.10.0

2 files

2.9.0

2 files

2.8.0

2 files

2.7.0

2 files

2.6.0

2 files

2.5.0

2 files

2.4.0

2 files

2.3.2

2 files

2.3.1

2 files

2.3.0

2 files

2.2.1

2 files

2.2.0

2 files

2.1.0

2 files

2.0.0

2 files

This release

0.1.1 This release

5 files

0.1.0

5 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page