章节摘要:本章跟着响应走右半弧——业务写完 body 之后,状态码怎么定、头怎么加、主体怎么序列化、格式由谁说了算、静态资源怎么带缓存出去。出层的每一站都决定用户与客户端实际拿到的东西。
第 4 章末尾,订单处理器给 ctx.body 赋了值。但"赋值"离"用户看到响应"还有一段路:出层阶段,响应头层要补齐安全与追踪头,压缩层要决定压不压,内核要按 body 的类型挑序列化器,还要和客户端协商格式、和缓存层对暗号。本章主线跟踪这段旅程的四个停靠点:状态码与头的最终控制(5.1)、JSON 与页面等多格式响应(5.2)、内容协商——同一资源按客户端口味变格式(5.2 后半)、静态资源与缓存控制(5.3)。主线走完你会明白:响应不是"返回"的,是在出层半程里被一层层定型的。
本章拐点在 5.2 的一个实验:同一个接口,浏览器拿到 HTML、命令行拿到 JSON,代码里却只有一份处理器。多数人第一反应是"写两个接口",看完协商机制才明白 Accept 头早已把选择权交给了协议。结论是:出层的核心心智是把响应当成"声明"而非"动作"——你只负责声明 body、status 与头,序列化、压缩、协商、发送全部由内核与外层在出阶段完成;声明得越语义化,出层的自动化程度越高。
响应定型的完整链路如下。

进层半程的每类层,在出层都有镜像的对应物,理解这组对称能让两章的知识互相咬合。进层的鉴权在出层对应安全响应头的收尾;进层的参数解析在出层对应主体序列化——解析把字节变成对象,序列化把对象变回字节,方向相反规则同源;进层的限流在出层对应配额余量响应头的回写(第 3 章限流层把 X-RateLimit 系列头写在截停判断之后,正是利用了出层仍可改头的窗口)。唯一的非对称点是错误:异常只向外出、不向内,所以出层路径上的错误处理(2.4 节的兜底层)天然只有一份,不像进层的校验可以按路由各挂各的。把这张对称表放在心里,第 9 章复盘网关层序时会再用到一次。
响应出去了,但如果内层某处炸了、某个异步没接住、某个 Promise 静默失败了呢?下一章回到层间语义,把 async/await 的传播规则与进程级异常兜底讲透——那决定了你的出层流水线在异常路径上是否同样可靠。