http.frm.serve
框架半层 IO 粘合(P4-B/T46;accept→read→parse→dispatch→respond)
定位(§11.7 分层纪律):frm 16 件纯层与 net 门面之间的唯一 IO use 点。 tests/http/run.sh「IO 粘合归 P4-B+」注记由本件兑现;协议编解码全走 http.parse(P4-A 既有半层,含走私面 400 族/上限 413/414/431/505),本件零解析零拼装 报文头(响应三位十进制状态行除外——message.ct msg_response_head 亦可,取直拼与 static.ct st_resp_raw 同式以保 frm 响应面一家亲)。
use 面(加载器严格树,client.ct 头注同款登记):本件【只】use http.client (单级;connect.ct 先例,发射已证)。parse/message/bind 符号经 use 合并贯穿 直引(middleware 门面同款);消费方严禁再直 use http.parse/http.message/ net.bind/http.client —— 同叶双径即 E5020。消费方树预算:serve{client→ parse,message,bind} + middleware{router→enc} + static{crypto} 三子树互斥 可并用(x_serve e2e 即三树全量)。
前缀纪律:全件 sv_(pub + 私有;合并命名空间同名 decl 即 E5030,bd_/au_ 同款; static.ct 已占 st_ 前缀与 st_serve 本名,message.ct ChunkSt getter 亦 st_)。
双面形态(装箱边界事实决定,P6-A 探针实证「fn 值装箱调用只走标量/Str」): ① 规范循环面 sv_serve/sv_serve_n:派发 fn 值参数 disp = fn(method: Str, target: Str, body: Str) -> Str(全 Str 装箱安全; middleware 链 fn(Str,I64)->Str 同族已发射实证;fn 值取参数形而非 struct 字段 —— 字段形×spawn 闭包捕获未证,参数形 frm_route 闭包链 已证)。body = 印刷域文本 (sv_str_range 全有全无;JSON/urlencoded 域无损,含 '{'——插值转义 例外面)。二进制体(文件上传)走 ②。 ② 分解直调面 sv_read_req/sv_read_body_cl/sv_body_bytes:请求缓冲 lane 在消费方作用域,体经 List[I32] 字节道直达 mp_parse(body.ct)—— 二进制安全零装箱(x_serve 上传腿即证;T46×T47 接线锚)。 缓冲口径:①面 8KB 内置(hend+clen 超即 413 不读体,Connection: close 使 短读安全);②面缓冲消费方自定,体上限sv 先验 + parse lim.max_body(1MiB 缺省)双门。chunked 请求体 → 501(v1 无分框;parse err 13 同映射)。
错误面:parse err 码 → 状态(sv_status_of):行畸/token/头/fold/smuggle/CL → 400;行超 → 414;头超族 → 431;CL 超 → 413;版本 → 505;TE → 501。 读 IO 败(io/eof)且零字节 → 静默关(客户端预请求即走);有部分字节 → 400。
shutdown 端点(§6 惯例,web 域包 serve 同款):POST /__shutdown loop 直拦 (不过派发)→ 200 "draining" 后停循环关监听;sv_serve/sv_serve_n 返 2。 返回码:0 = nmax 服务满 / 1 = 监听败 / 2 = shutdown / 3 = accept 败。 HEAD 不自动改写(frm 派发消费方自裁,router frm_m_head 槽在;web 域包 serve_with 的 HEAD 自动面属彼栈)。 v1 串行:一连接一请求,pipelining 多余字节随 close 丢弃(web 域包 §8.2 同款); keep-alive 挂 L6/L7 并发波。真并发服务(sc.spawn × sv_serve)= e2e 双 RT 矩阵实证(default 线程 + CTRON_RT=coro 协程停车于 net 垫片)。
pub struct
struct SvRead
| Field | Type |
|---|---|
rc |
I64 |
err |
I64 |
n |
I64 |
ms |
I64 |
ml |
I64 |
ts |
I64 |
tl |
I64 |
hend |
I64 |
clen |
I64 |
bkind |
I64 |
struct HttpSock
| Field | Type |
|---|---|
var fd |
I64 |
struct HttpLoc
| Field | Type |
|---|---|
ok |
I64 |
host |
Str |
port |
I64 |
path |
Str |
struct Box64
| Field | Type |
|---|---|
var v |
I64 |
impl
impl Drop for HttpSock
fn drop(var self)
pub fn
| Signature | Returns | Description |
|---|---|---|
sv_rc(r: SvRead) |
I64 |
— |
sv_err(r: SvRead) |
I64 |
— |
sv_n(r: SvRead) |
I64 |
— |
sv_ms(r: SvRead) |
I64 |
— |
sv_ml(r: SvRead) |
I64 |
— |
sv_ts(r: SvRead) |
I64 |
— |
sv_tl(r: SvRead) |
I64 |
— |
sv_hend(r: SvRead) |
I64 |
— |
sv_clen(r: SvRead) |
I64 |
— |
sv_bkind(r: SvRead) |
I64 |
— |
sv_read_req(fd: I64, buf: &[I64], cap: I64, scr: &[I64], scap: I64, tmo_ms: I64) |
SvRead |
增量头读(parse 每读一块重扫;cx_read_resp 同构,请求面): 头完 rc=1;畸形 rc=-1(err);超缓冲 rc=-4;对端 IO 败 rc=-2;净 eof rc=-3。 |
sv_read_body_cl(fd: I64, buf: &[I64], n0: I64, hend: I64, clen: I64, cap: I64, scr: &[I64], scap: I64, tmo_ms: I64) |
I64 |
CL 体读齐(头后追加; lane 无偏移读面,scratch 转运)。败 -1。 |
sv_body_bytes(buf: &[I64], a: I64, n: I64) |
List[I32] |
体/段 lane → List[I32] 字节道(二进制安全全 0..255;mp_parse 入口载体) |
sv_str_range(src: &[I64], a: I64, b: I64) |
Str |
lane 段 → Str(印刷域全有全无:任一非 0x20..0x7E 字节 → "";frm_slice_str 域一致;二进制面走 sv_body_bytes —— 文本面与字节面的分界即此) |
sv_reason(n: I64) |
Str |
— |
sv_resp(status: I64, body: Str) |
Str |
— |
sv_resp_ct(status: I64, ctype: Str, body: Str) |
Str |
— |
sv_status_of(err: I64) |
I64 |
parse err 码 → 状态(400 族缺省;414/431/413/505/501 各归位) |
sv_serve_fd(lfd: I64, h: fn(Str, Str, Str) -> Str, body_limit: I64, nmax: I32, tmo_ms: I64) |
I32 |
外置监听面:调用方自持 listen fd(client_listen :0 → client_sockname 回读 实际端口后交入;spawn 闭包捕获只剩标量 fd —— e2e 双 RT 矩阵即此形)。 本面不关监听(调用方所有权);缓冲内置 8KB/2KB。返码同 sv_serve_n。 |
sv_serve_n(host: Str, port: I64, h: fn(Str, Str, Str) -> Str, body_limit: I64, nmax: I32, tmo_ms: I64) |
I32 |
有界服务:恰 nmax 个连接(败连接不计)后返 0;shutdown 提前返 2。 测试面(e2e 单进程确定性)+ 自定义循环积木。 |
sv_serve(host: Str, port: I64, h: fn(Str, Str, Str) -> Str, body_limit: I64, tmo_ms: I64) |
I32 |
常驻服务:服务至 shutdown(返 2)或 accept 败(返 3);监听败返 1。 |
client_listen(host: Str, port: I64, out_fd: Box[Box64]) |
I64 |
— |
client_accept(lfd: I64, out_fd: Box[Box64]) |
I64 |
— |
client_read_t(fd: I64, buf: &[I64], cap: I64, timeout_ms: I64) |
I64 |
— |
client_write_str(fd: I64, s: Str) |
I64 |
— |
client_close(fd: I64) |
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 |
— |
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_start(h: HttpHead) |
I64 |
— |
http_method_len(h: HttpHead) |
I64 |
— |
http_target_start(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 |
— |