跳转至

web.openapi

运行期 /openapi.json 端点:自路由表同源导出最小 OpenAPI 3 (Plan 2b Task 2;设计 docs/superpowers/specs/2026-09-27-web-framework-design.md §4.1;纪律 §14-1)

形态:openapi_json(r, title, ver) -> Resp——装配点一行挂载 r.get("/openapi.json", |rq| openapi_json(app, title, ver))(app 为终态 Router; spec §4.1 .openapi(标题, 版本) 链式糖即此二行的封装,v1 不另入 Router 面)。 spec §13-⑥ 惰性缓存不在此件——端点闭包自持缓存归装配点,本件恒纯函数。

导出面(最小 OpenAPI 3.0.3):openapi/info.title/info.version/paths; 路由模式段还原 —— lit 原样、:par → {par}、*splat → {splat}(OpenAPI 无尾通配概念,模板化登记);同模板多方法归并进同一 path 对象(声明序); 每方法 responses 恒 200 → description "ok"(v1 无逐路由响应模型,登记志向)。

JSON 构建:§14-1 收集+join 一遍成形(无中途拼接);字符串经 oapi_esc 转义 (core.json_esc 私有不可复用,core 增导出会牵动 2a 冻结面——本件自铸,名面隔开)。 method 小写化逐字节 +32(utf8_enc 单字符),A-Z 域外原样。

pub struct

struct Pair

Field Type
k Str
v Str

struct Resp

Field Type
status I32
headers List[Pair]
body Str

struct JObj

Field Type
parts List[Str]

struct Req[S]

Field Type
method Str
path Str
query Str
body Str
headers List[Pair]
cookies List[Pair]
params List[Pair]
session List[Pair]
state S

struct RouteSeg

Field Type
kind Str
text Str

struct Route[S]

Field Type
m Str
segs List[RouteSeg]
chain List[fn(&Req[S], fn(&Req[S]) -> Resp) -> Resp]
h fn(&Req[S]) -> Resp

struct Router[S]

Field Type
state S
routes List[Route[S]]
mws List[fn(&Req[S], fn(&Req[S]) -> Resp) -> Resp]
not_found_h List[fn(&Req[S]) -> Resp]
not_allowed_h List[fn(&Req[S]) -> Resp]

struct Match[S]

Field Type
kind I32
route Route[S]
params List[Pair]
splat Str
allow Str

pub fn

Signature Returns Description
openapi_json[S](r: Router[S], title: Str, ver: Str) Resp —
html(body: Str) Resp —
json(body: Str) Resp —
text(body: Str) Resp —
redirect(loc: Str) Resp —
status(n: I32, body: Str) Resp —
xml(body: Str) Resp —
yaml(body: Str) Resp —
err_json(n: I32, msg: Str) Resp —
attachment(r: Resp, filename: Str) Resp —
with(r: Resp, k: Str, v: Str) Resp —
with_status(r: Resp, n: I32) Resp —
resp_header(r: Resp, k: Str) Str —
resp_body(r: Resp) Str —
resp_status(r: Resp) I32 —
json_obj() JObj —
str(b: JObj, k: Str, v: Str) JObj —
i64(b: JObj, k: Str, v: I64) JObj —
bool(b: JObj, k: Str, v: Bool) JObj —
strs(b: JObj, k: Str, xs: List[Str]) JObj —
end(b: JObj) Str —
end_status(b: JObj, n: I32) Resp —
csv_rows(headers: List[Str], rows: List[List[Str]]) Str —
req_of[S](method: Str, path: Str, state: S) Req[S] —
req_full[S](method: Str, path: Str, body: Str, hdrs: List[Pair], state: S) Req[S] —
req_set_params[S](r: &Req[S], params: List[Pair]) Req[S] —
req_set_session[S](r: &Req[S], sess: List[Pair]) Req[S] —
pdec(s: Str) Str —
param[S](r: &Req[S], name: Str) Str —
pair_get(ps: List[Pair], k: Str) Str —
param_i64[S](r: &Req[S], name: Str) Option[I64] —
param_f64[S](r: &Req[S], name: Str) Option[F64] —
query[S](r: &Req[S], name: Str) Str —
query_all[S](r: &Req[S], name: Str) List[Str] —
form[S](r: &Req[S], name: Str) Str —
form_all[S](r: &Req[S], name: Str) List[Str] —
header[S](r: &Req[S], name: Str) Str —
cookie[S](r: &Req[S], name: Str) Str —
session[S](r: &Req[S], name: Str) Str —
router[S](state: S) Router[S] —
get[S](r: Router[S], p: Str, h: fn(&Req[S]) -> Resp) Router[S] —
post[S](r: Router[S], p: Str, h: fn(&Req[S]) -> Resp) Router[S] —
put[S](r: Router[S], p: Str, h: fn(&Req[S]) -> Resp) Router[S] —
middleware[S](r: Router[S], mw: fn(&Req[S], fn(&Req[S]) -> Resp) -> Resp) Router[S] —
mount_at[S](r: Router[S], prefix: Str, sub: Router[S]) Router[S] —
has_conflict[S](r: Router[S]) Bool —
install[S](r: Router[S], p: fn(Router[S]) -> Router[S]) Router[S] —
not_found[S](r: Router[S], h: fn(&Req[S]) -> Resp) Router[S] —
method_not_allowed[S](r: Router[S], h: fn(&Req[S]) -> Resp) Router[S] —
test_call[S](r: Router[S], method: Str, path: Str, body: Str) Resp —
route_match[S](r: Router[S], m: Str, path: Str) Match[S] —
dispatch_h[S](r: Router[S], method: Str, path: Str, body: Str, hdrs: List[Pair]) Resp —
dispatch[S](r: Router[S], method: Str, path: Str, body: Str) Resp —