Metadata-Version: 2.4
Name: dartio-tls
Version: 0.1.1
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Summary: Python HTTP client (sync + async) that speaks TLS like Flutter dart:io (BoringSSL), with a Rust core
Keywords: http-client,tls,boringssl,dart,flutter,rust
Author: you-just
License: MIT
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Homepage, https://github.com/you-just/dartio-tls
Project-URL: Issues, https://github.com/you-just/dartio-tls/issues
Project-URL: Repository, https://github.com/you-just/dartio-tls

# dartio-tls

[English](#english) | [中文](#中文)

---

## English

A Python HTTP client that speaks TLS the way Flutter's `dart:io` does —
same embedded BoringSSL, same handshake shape (cipher suites and order,
extensions, signature algorithms, curves, ALPN) — with a Rust core and
both synchronous and asyncio interfaces.

`dart:io` (the networking library inside every Flutter app) produces a
TLS ClientHello that is distinct from browser or `requests`/`httpx`
stacks. This library uses the **same TLS library** (`BoringSSL`, via the
`boring` crate) configured the same way, so the bytes on the wire match
what a real Flutter `dart:io` client sends.

### Features

- **Flutter `dart:io` TLS shape** out of the box (`impersonate="dartio_3_33_0"`,
  matching the Dart SDK shipped with Flutter 3.33)
- **Sync + Async clients**: blocking `Client` and asyncio-native
  `AsyncClient` (Rust tokio runtime underneath)
- **Ordered headers**: request headers are serialized in the exact order
  you provide (pass `list[tuple]`; plain `dict` also accepted)
- **HTTP/1.1** with strict framing: content-length / chunked / close
  response bodies, HEAD/204/304 handling
- **Proxy support** per client or per request (`http://user:pass@host:port`,
  CONNECT tunneling for https targets)
- **Cookie jar**, automatic redirects (301/302/303 → GET, 307/308 keep
  method), per-request timeout
- **Embedded CA store** (Mozilla bundle) — no dependence on the system
  certificate store
- Prebuilt wheels for macOS (Apple Silicon), Linux (x86_64, manylinux),
  and Windows (x86_64); one wheel per platform covers Python ≥ 3.8 (abi3)

### Install

```bash
pip install dartio-tls
```

### Usage

Synchronous:

```python
import dartio_tls

client = dartio_tls.Client(impersonate="dartio_3_33_0", timeout=20.0)
resp = client.post(
    "https://example.com/api",
    headers=[("user-agent", "Dart/3.9"), ("content-type", "application/json")],
    json={"q": "x"},
)
print(resp.status_code, resp.json())
```

Asynchronous:

```python
import asyncio
import dartio_tls

async def main():
    client = dartio_tls.AsyncClient(impersonate="dartio_3_33_0")
    r1, r2 = await asyncio.gather(
        client.get("https://example.com/a"),
        client.post("https://example.com/b", json={"k": 1}),
    )

asyncio.run(main())
```

Per-request proxy override:

```python
resp = client.get(url, proxy="http://user:pass@host:port")
```

### API

- Constructors (`Client` / `AsyncClient`):
  `impersonate`, `proxy`, `cookie_store`, `timeout`,
  `follow_redirects`, `max_redirects`, `verify`
- Methods: `get / post / put / delete / patch / head / options /
  request(method, ...)`, each accepting `headers`, `content` (bytes),
  `json` (auto-serialized, sets content-type), `proxy`
- Response: `status_code`, `headers` (ordered list), `content` (bytes),
  `text`, `json()`, `url` (final URL after redirects)

Available `impersonate` profiles: `dartio_3_33_0` (default).

### License

MIT

---

## 中文

以 Flutter `dart:io` 的 TLS 形态发包的 Python HTTP 客户端——同一个内嵌
BoringSSL、同样的握手形态（cipher 套件与顺序、扩展、签名算法、曲线、
ALPN）——Rust 内核，同步 + asyncio 双面。

`dart:io`（每个 Flutter App 内嵌的网络库）产生的 TLS ClientHello 与浏览器
或 `requests`/`httpx` 栈都不同。本库与 `dart:io` 使用**同一个 TLS 库**
（BoringSSL，经 `boring` crate）按同样方式配置，线上字节与真实 Flutter
`dart:io` 客户端一致。

### 特性

- **Flutter `dart:io` TLS 形态**开箱即用（`impersonate="dartio_3_33_0"`，
  对齐 Flutter 3.33 搭载的 Dart SDK）
- **同步 + 异步双面**：阻塞式 `Client` 与 asyncio 原生 `AsyncClient`
  （底层为 Rust tokio runtime）
- **请求头保序**：头按你给的顺序原样上线（传 `list[tuple]`；普通
  `dict` 也收）
- **HTTP/1.1** 严格帧形：content-length / chunked / close 三种响应体、
  HEAD/204/304 处理
- **代理支持**：per-client 或 per-request（`http://user:pass@host:port`，
  https 目标走 CONNECT 隧道）
- **cookie jar**、自动重定向（301/302/303 转 GET，307/308 保方法）、
  请求级超时
- **内嵌 CA store**（Mozilla bundle），不依赖系统证书库
- 预编译 wheel：macOS（Apple Silicon）、Linux（x86_64，manylinux）、
  Windows（x86_64）；每平台一个 wheel 通吃 Python ≥ 3.8（abi3）

### 安装

```bash
pip install dartio-tls
```

### 用法

同步：

```python
import dartio_tls

client = dartio_tls.Client(impersonate="dartio_3_33_0", timeout=20.0)
resp = client.post(
    "https://example.com/api",
    headers=[("user-agent", "Dart/3.9"), ("content-type", "application/json")],
    json={"q": "x"},
)
print(resp.status_code, resp.json())
```

异步：

```python
import asyncio
import dartio_tls

async def main():
    client = dartio_tls.AsyncClient(impersonate="dartio_3_33_0")
    r1, r2 = await asyncio.gather(
        client.get("https://example.com/a"),
        client.post("https://example.com/b", json={"k": 1}),
    )

asyncio.run(main())
```

per-request 代理覆盖：

```python
resp = client.get(url, proxy="http://user:pass@host:port")
```

### API

- 构造（`Client` / `AsyncClient`）：`impersonate`、`proxy`、
  `cookie_store`、`timeout`、`follow_redirects`、`max_redirects`、`verify`
- 方法：`get / post / put / delete / patch / head / options /
  request(任意方法)`，均收 `headers`、`content`（bytes）、`json`
  （自动序列化并补 content-type）、`proxy`
- Response：`status_code`、`headers`（保序 list）、`content`（bytes）、
  `text`、`json()`、`url`（跳转后最终 URL）

可用 `impersonate` 档：`dartio_3_33_0`（默认）。

### 许可证

MIT

