http.client
HTTP/1.1 客户端 + 传输门面(P4-C) ═══ use 图与模块形态(本波实测,登记面)═══ 加载器事实(divergences (g) E5020 的加码实测):栈式查环无 pop ⇒ 任一文件 的传递 use 树中【每个模块至多出现一次】——同父双子共享任一叶子(如两个 std 模块各自 use net.bind)与跨模块菱形同样 E5020;且合并取全量 decl ⇒ 同名 decl 二次合并 E5030。⇒ http 的消费方 use 图必须是严格互斥树: client.ct(本文件)= 唯一触 net.bind 的模块(传输 IO 面) sse.ct / ws.ct = 纯叶子(ws → crypto 单子依赖,与 client 树互斥) 消费方夹具同批 use 三树 + std.rand 即全量面,不再 use std.net(否则与 bind.ct 汇合即 E5020)。StdNet 面未用:本文件自出 HttpNet 空 struct 作 能力显形参(与 net: StdNet 同构的命名面,不 import std.net)。 ═══ 面 ═══ ① 传输面 client_*(listen/sockname/accept/connect/read_t/write/write_str /close):net 门面 rc 口径的透传薄壳(0 成/<0 败;读 >0 n/0 eof/<0 败)——夹具服务端与服务端 SSE/WS 全走此面。 ② HttpSock = Drop RAII 句柄(fd < 0 跳过;显式 client_close 后置 -1, net.ct ④ 同款纪律)。 ③ 客户端面 client_request:连接(缓存复用)→ 发送(parse/message 树组 装)→ 响应读取(CL/chunked 分框,parse.ct 增量解析)→ 重定向跟随 (301/302/303 → GET 且弃体;307/308 保方法保体;上限 5 跳;Location 支持 绝对路径 与 http://host[:port]/path 全 URL 两形)→ 101 直通 (WS upgrade:连接经缓存槽交予调用方,键位失效防误用)。 ④ keep-alive 缓存(④ 面登记:发射面 struct 值语义 + 跨模块可变状态 通道受限 —— TupleE 出口径、Box 字段 StructLit 出口径(本波探针实证), 唯 Box[Box64] 标量胞 = 已证好形)⇒ 缓存态 = 调用方持有四枚标量胞 (bfd 连接 / bhh 主机哈希 / bpt 端口 / bru 复用计数),单槽 v1,键 = hash(host)+port;复用失败(对端已关)重连一次 = 重试一次语义(仅 复用面失败重试:发送失败或零字节读败;已有部分响应字节不重发)。 复用计数 bru 在【成功走复用连接】时自增(测试可见)。 ⑤ 上限 = parse.ct HttpLimits 缺省档(响应体 1 MiB 强制界,head 之上 cap 参数为硬界);超时 = net_read_t 读截止,每次读同参(v1 无整请求 deadline,登记)。 ⑥ 发射面纪律:无闭包、无方法调用、无 Tuple;(h) 缺口绕行 = getter 面 (成员访问不出模块);while 体无 Drop 局部(HttpSock 仅在夹具裸块内 生灭;本文件一律裸 fd + 显式 close)。
pub struct
struct HttpNet
| Field | Type |
|---|---|
struct HttpSock
RAII 句柄:作用域出口关 fd(显式 client_close 后须 sock.fd = -1)。
| Field | Type |
|---|---|
var fd |
I64 |
struct HttpLoc
| Field | Type |
|---|---|
ok |
I64 |
host |
Str |
port |
I64 |
path |
Str |
struct HttpResp
| Field | Type |
|---|---|
var rc |
I64 |
var err |
I64 |
var status |
I64 |
var ver |
I64 |
var keep |
I64 |
var nredir |
I64 |
var reuses |
I64 |
var head_end |
I64 |
var body_off |
I64 |
var body_len |
I64 |
struct Box64
| Field | Type |
|---|---|
var v |
I64 |
impl
impl Drop for HttpSock
fn drop(var self)
pub fn
| Signature | Returns | Description |
|---|---|---|
http_net() |
HttpNet |
— |
client_listen(host: Str, port: I64, out_fd: Box[Box64]) |
I64 |
— |
client_sockname(fd: I64, out_port: Box[Box64]) |
I64 |
— |
client_accept(lfd: I64, out_fd: Box[Box64]) |
I64 |
— |
client_connect(host: Str, port: I64, out_fd: Box[Box64]) |
I64 |
— |
client_read_t(fd: I64, buf: &[I64], cap: I64, timeout_ms: I64) |
I64 |
读:>0 n / 0 eof / <0 败(超时亦 <0);单次至多搬运 min(cap, 4096)。 |
client_write(fd: I64, buf: &[I64], n: I64) |
I64 |
— |
client_write_str(fd: I64, s: Str) |
I64 |
— |
client_close(fd: I64) |
I64 |
— |
client_sleep_ms(ms: I64) |
I64 |
时钟/睡眠透传(夹具服务端节奏控制与耗时测量;std.net 不可入的 use 图约束下 的同口径面) |
client_now_ns() |
I64 |
— |
client_hash_host(host: Str) |
I64 |
— |
loc_ok(l: HttpLoc) |
I64 |
— |
loc_host(l: HttpLoc) |
Str |
— |
loc_port(l: HttpLoc) |
I64 |
— |
loc_path(l: HttpLoc) |
Str |
— |
client_loc_resolve(loc: Str, base_host: Str, base_port: I64) |
HttpLoc |
Location 头解析:v1 两形 —— 绝对路径("/...")与全 URL("http://host[:port]/..."); 其余(协议相对 //、相对路径、https)→ ok = 0。host 空(全 URL 无端口)→ 继承 base。 |
rr_rc(r: HttpResp) |
I64 |
— |
rr_err(r: HttpResp) |
I64 |
— |
rr_status(r: HttpResp) |
I64 |
— |
rr_ver(r: HttpResp) |
I64 |
— |
rr_keep(r: HttpResp) |
I64 |
— |
rr_nredir(r: HttpResp) |
I64 |
— |
rr_reuses(r: HttpResp) |
I64 |
— |
rr_head_end(r: HttpResp) |
I64 |
— |
rr_body_off(r: HttpResp) |
I64 |
— |
rr_body_len(r: HttpResp) |
I64 |
— |
client_request(io: HttpNet, method: Str, host: Str, port: I64, path: Str, extra: Str, body: &[I64], blen: I64, buf: &[I64], cap: I64, scr: &[I64], timeout_ms: I64, bfd: Box[Box64], bhh: Box[Box64], bpt: Box[Box64], bru: Box[Box64]) |
HttpResp |
请求执行(重定向跟随 + 单槽 keep-alive 缓存 + 复用失败重试一次)。 err 码:1 连接败 / 2 发送败 / 3 接收败(干净)/ 4 接收败(有字节或帧坏)/ 5 解析 / 6 Location 坏 / 7 重定向超限。重试一次仅限【复用连接】上的发送 败或零字节读败(对端已关语义);有部分响应字节绝不重发。 |
http_limits_default() |
HttpLimits |
— |
http_err_line() |
I64 |
— |
http_err_line_long() |
I64 |
— |
http_err_version() |
I64 |
— |
http_err_token() |
I64 |
— |
http_err_target() |
I64 |
— |
http_err_hdr() |
I64 |
— |
http_err_fold() |
I64 |
— |
http_err_hdr_long() |
I64 |
— |
http_err_hdr_many() |
I64 |
— |
http_err_head_long() |
I64 |
— |
http_err_smuggle() |
I64 |
— |
http_err_cl() |
I64 |
— |
http_err_te() |
I64 |
— |
http_err_bodycap() |
I64 |
— |
http_parse_head(buf: &[I64], n: I64, lim: HttpLimits) |
HttpHead |
— |
http_header_at(buf: &[I64], h: HttpHead, idx: I64) |
HttpSlice |
— |
http_header_find(buf: &[I64], h: HttpHead, name: Str) |
I64 |
— |
http_header_value(buf: &[I64], h: HttpHead, name: Str) |
HttpSlice |
— |
http_keep_alive(buf: &[I64], h: HttpHead) |
I64 |
— |
http_rc(h: HttpHead) |
I64 |
— |
http_err_of(h: HttpHead) |
I64 |
— |
http_is_resp(h: HttpHead) |
I64 |
— |
http_ver(h: HttpHead) |
I64 |
— |
http_status_of(h: HttpHead) |
I64 |
— |
http_head_end(h: HttpHead) |
I64 |
— |
http_nheaders(h: HttpHead) |
I64 |
— |
http_body_kind(h: HttpHead) |
I64 |
— |
http_clen(h: HttpHead) |
I64 |
— |
http_method_len(h: HttpHead) |
I64 |
— |
http_target_len(h: HttpHead) |
I64 |
— |
sl_rc(s: HttpSlice) |
I64 |
— |
sl_vs(s: HttpSlice) |
I64 |
— |
sl_vl(s: HttpSlice) |
I64 |
— |
msg_hex(v: I64) |
Str |
— |
msg_request_line(method: Str, target: Str, ver: I64) |
Str |
— |
msg_status_line(ver: I64, status: I64, reason: Str) |
Str |
— |
msg_header(name: Str, value: Str) |
Str |
— |
msg_head_end() |
Str |
— |
msg_cl_header(n: I64) |
Str |
— |
msg_request_head(method: Str, target: Str, host: Str, ver: I64, body_len: I64) |
Str |
— |
msg_response_head(ver: I64, status: I64, reason: Str, body_len: I64) |
Str |
— |
msg_chunk_header(size: I64) |
Str |
— |
msg_last_chunk() |
Str |
— |
msg_last_chunk_trailer(name: Str, value: Str) |
Str |
— |
msg_continue() |
Str |
— |
msg_expect_header() |
Str |
— |
msg_should_expect(body_len: I64, threshold: I64) |
I64 |
— |
msg_body_remaining(head_end: I64, clen: I64, fed: I64) |
I64 |
— |
chunk_st_new() |
ChunkSt |
— |
cr_rc(r: ChunkRet) |
I64 |
— |
cr_err(r: ChunkRet) |
I64 |
— |
cr_consumed(r: ChunkRet) |
I64 |
— |
cr_produced(r: ChunkRet) |
I64 |
— |
cr_phase(r: ChunkRet) |
I64 |
— |
cr_remain(r: ChunkRet) |
I64 |
— |
chunk_step(src: &[I64], n: I64, pos: I64, st: ChunkSt, dst: &[I64], dfill: I64, dcap: I64) |
ChunkRet |
— |