跳转至

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 —