跳转至

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 —