跳转至

http.frm.static

静态文件面(P6-D;ETag/If-None-Match 304/Range 206·416/穿越拒)

口径: 纯面/IO 面两分 —— st_resp_from_content(name, content, inm, range) 为全决策 纯函数(夹具双臂直测);st_serve(root, target, …) 是唯一 IO 薄胶 (fs_exists/read_file 内建),组合层 handler 终端调用,frm 零 IO 链形不变。

ETag = 强校验器 '"' + sha256_hex(content) + '"'(内容寻址;无 mtime 内建, Last-Modified 不发 —— 登记志向:mtime 内建落库后补)。If-None-Match: 精确比较 + "*" 全匹配 + 逗号列表逐段;弱比较 W/ 前缀不支持(从严,登记)。 304 响应无 Content-Type/Content-Length、无体(RFC 9110 §15.4.5)。

Range(v1 单范围 bytes=;RFC 9110 §14):"bytes=S-E"/"bytes=S-"/"bytes=-N"。 E 越界截断至 len-1;S ≥ len 或 S > E → 416(带 Content-Range: bytes */len); suffix N=0 → 416;畸形/多范围(含 ',')/非 bytes 单位 → 忽略 Range 走 200 (RFC 允许忽略,从严即默认之宽容面)。206 带 Content-Range: bytes S-E/len。

穿越拒:target 必以 '/' 开头、无 '..' 与 '.' 段、无空段(//)、无尾斜杠 (只服务文件)、无 '?'/'#' 目标内嵌(query/fragment 归调用方裁剪,入此即拒)。 命中任一 → 403(fail-closed,从严即默认)。

Content-Type = 扩展名小表(确定性穷举;缺省 application/octet-stream; 字符集参数不标 —— 登记志向)。sendfile 零拷贝列 P9(计划原文)。

use 面:std.crypto(sha256_hex)单叶;router/middleware 不 use(消费方经 middleware 门面合并 router,本模块只补 crypto 叶 —— 加载器 done 去重, 同叶多径安全,frm 家族同 body.ct 先例)。

pub fn

Signature Returns Description
st_rc(r: StRange) I64 rc:0 = 忽略 Range(200 全量) / 1 = 206 可满足 / 2 = 416 不可满足
st_s(r: StRange) I64 —
st_e(r: StRange) I64 —
st_clen(r: StRange) I64 —
st_range_parse(range: Str, len: I64) StRange 单范围解析。len = 资源总长(I64 ≥ 0)
st_slice(s: Str, start: I64, end: I64) Str 含端点字节切片(s..e 双闭;调用方保证 0 ≤ s ≤ e < len)
st_etag(content: Str) Str 强 ETag:内容寻址
st_inm_match(inm: Str, etag: Str) Bool If-None-Match 比较:""=无头 false;"*"=true;逗号列表逐段精确;W/ 弱形不支持
st_traversal_ok(target: Str) Bool —
st_ctype(name: Str) Str —
st_find(hay: Str, needle: Str) I32 子串查找(hay 内 needle 首现下标;未现 = -1;夹具断言辅助)
st_resp_from_content(name: Str, content: Str, inm: Str, range: Str) Str 全决策面:name 供 Content-Type;inm/range 为对应请求头原文(可空)
st_serve(root: Str, target: Str, inm: Str, range: Str) Str —