Midway 数据响应统一封装指南:ServerResponse 与 HttpServerResponse 实战
后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载从 v3.17.0 开始Midway 框架提供了ServerResponse与HttpServerResponse两套响应类实现用于在服务端统一定制成功与失败场景下的通用返回格式解决传统「在ctx上挂ok/fail方法、或分别在中间件与错误过滤器里维护返回逻辑」难以统一维护的问题。读完本文你将掌握在 Koa 场景下使用链式响应对象返回 JSON / Text / Blob / 文件 / 流式数据 / SSE并通过静态模板TPL覆盖与类继承定制返回结构的完整方案。Http 通用响应为什么要统一返回格式在 Koa 场景下一个控制器通常会处理业务逻辑后返回结果过程中必然存在成功与失败两种分支。最常见的两种历史做法是在ctx上扩展ok()、fail()等方法业务代码里try/catch后分别调用例如import { Controller, Get, Inject } from midwayjs/core; import { Context } from midwayjs/koa; Controller(/) export class HomeController { Inject() ctx: Context; Get(/) async home() { try { // ... return this.ctx.ok(/*...*/); } catch (err) { return this.ctx.fail(/*...*/); } } }在 Web 中间件中处理成功返回在错误过滤器中处理失败返回。这两种方式都存在同样的痛点返回逻辑分散在多个位置格式难以全局统一也难以维护。为此框架提供了一套「统一返回」方案——以最常见的返回 JSON 数据为例创建HttpServerResponse实例后调用json()方法链式返回数据。import { Controller, Get, Inject, HttpServerResponse } from midwayjs/core; import { Context } from midwayjs/koa; Controller(/) export class HomeController { Inject() ctx: Context; Get(/success) async home() { return new HttpServerResponse(this.ctx).success().json({ // ... }); } Get(/fail) async home2() { return new HttpServerResponse(this.ctx).fail().json({ // ... }); } }默认情况下HttpServerResponse在成功和失败场景下会提供 JSON 的通用包裹结构。成功场景下接收到的数据如下{ success: true, data: //... }失败场景下接收到的数据如下{ success: false, message: //... }注意json()等数据设置方法必须在链式调用的最后一步调用。从源码实现看这一套行为在 response/base.ts 中定义ServerResponse内部维护一个isSuccess状态位默认为truesuccess()与fail()分别将其置为true/false并返回this以支持链式调用而json()、text()、blob()方法则读取该状态位并调用对应的静态模板。HttpServerResponse继承自ServerResponse在 response/http.ts 中补充了status、header、file、sse、stream等 HTTP 专属能力其中json()会额外写入Content-Type: application/json响应头。两个类的导出入口位于 response/index.ts。常用的响应格式与链式快捷方法HttpServerResponse需要传入当前请求的上下文对象ctx才能实例化const serverResponse new HttpServerResponse(this.ctx);之后以链式形式调用各数据设置方法// json serverResponse.json({ a: 1, }); // text serverResponse.text(abcde); // blob serverResponse.blob(Buffer.from(hello world));除了设置数据的方法还提供了一些快捷方法组合使用例如设置状态码与响应头// status serverResponse.status(200).text(abcde); // header serverResponse.header(Content-Type, text/html).text(divhello/div); // headers serverResponse.headers({ Content-Type: text/plain, Content-Length: 100 }).text(a.repeat(100));从源码看这些快捷方法的实现位于 response/http.tsstatus(code)直接写入this.ctx.res.statusCodeheader(key, value)调用this.ctx.res.setHeader(key, value)headers(headers)优先使用ctx.res.setHeaders批量设置否则逐条调用header()json()/text()会自动写入对应的Content-Typeblob(data, mimeType?)支持第二个参数指定 MIME 类型默认application/octet-stream此外还提供了html(data)text/html与redirect(url, status 302)等未在文档中展开但可直接使用的快捷方法。对应的行为在 test/response/base.test.ts 中有完整断言例如success().json({ a: 1 })会精确返回{ success: true, data: { a: 1 } }而success().blob(Buffer.from(abc))原样返回 Buffer。响应模板全局覆盖与继承定制针对不同的数据设置方法框架提供了不同模板TPL供用户自定义。比如json()方法的默认模板如下源码见 response/base.tsclass ServerResponse { // ... static JSON_TPL (data: Recordany, any, isSuccess: boolean): unknown { if (isSuccess) { return { success: true, data, }; } else { return { success: false, message: data || fail, }; } }; }可以看到失败分支中的message直接取自data如果未传数据则回退为字符串fail。直接覆盖全局模板将全局模板覆盖即可实现自定义HttpServerResponse.JSON_TPL (data, isSuccess) { if (isSuccess) { // ... } else { // ... } };注意直接赋值会修改类级别的静态属性影响所有使用HttpServerResponse的实例。通过继承定制局部模板更推荐的方式是通过继承来定义不同的响应模板这样不会影响全局默认模板class CustomServerResponse extends HttpServerResponse {} CustomServerResponse.JSON_TPL (data, isSuccess) { if (isSuccess) { // ... } else { // ... } };使用时创建实例即可// ... Controller(/) export class HomeController { Inject() ctx: Context; Get(/) async home() { return new CustomServerResponse(this.ctx).success().json({ // ... }); } }继承生效的机制在源码中很关键json()、text()、blob()均通过Object.getPrototypeOf(this).constructor.JSON_TPL(...)获取模板而不是直接引用ServerResponse.JSON_TPL。这意味着只要子类覆写了静态模板实例就会自动使用子类模板无需修改基类。针对text、blob方法的模板同样可以覆盖HttpServerResponse.TEXT_TPL (data, isSuccess) { /*...*/}; HttpServerResponse.BLOB_TPL (data, isSuccess) { /*...*/};需要说明的是从源码看模板回调实际接收三个参数data、isSuccess、ctx文档示例中的两参数写法同样可用第三个参数可用来在模板内访问请求上下文。数据流式响应Stream使用内置的HttpServerResponse的stream()方法处理流式数据返回import { Controller, Get, Inject, sleep, HttpServerResponse } from midwayjs/core; import { Context } from midwayjs/koa; Controller(/) export class HomeController { Inject() ctx: Context; Get(/) async home() { const res new HttpServerResponse(this.ctx).stream(); setTimeout(() { for (let i 0; i 100; i) { await sleep(100); res.send(abc.repeat(100)); } res.end(); }, 1000); return res; } }底层实现位于 response/stream.tsHttpStreamResponse继承自 Node.js 的Transform首次写入数据时自动设置statusCode 200、Transfer-Encoding: chunked与Cache-Control: no-cache并关闭 socket 超时字符串数据直接write非字符串数据会经过JSON.stringify后写出_flush时结束响应。send()写入的数据会先经过STREAM_TPL处理sendError()会记录日志并结束响应。通过STREAM_TPL可以修改数据的返回结构HttpServerResponse.STREAM_TPL (data) { /*...*/};注意这个模板只处理成功的数据且从签名看不接收isSuccess参数。文件流式响应File Download从 v3.17.0 开始可以通过HttpServerResponse简单处理文件下载。传递一个文件路径即可默认使用application/octet-stream响应头返回import { Controller, Get, Inject, sleep, HttpServerResponse } from midwayjs/core; import { Context } from midwayjs/koa; Controller(/) export class HomeController { Inject() ctx: Context; Get(/) async home() { const filePath join(__dirname, ../../package.json); return new HttpServerResponse(this.ctx).file(filePath); } }如需返回不同的类型可通过第二个参数指定 MIME 类型import { Controller, Get, Inject, sleep, HttpServerResponse } from midwayjs/core; import { Context } from midwayjs/koa; Controller(/) export class HomeController { Inject() ctx: Context; Get(/) async home() { const filePath join(__dirname, ../../package.json); return new HttpServerResponse(this.ctx).file(filePath, application/json); } }源码层面file(filePath, mimeType?)的实现response/http.ts会写入Content-Type默认application/octet-stream写入Content-Disposition: attachment; filename文件名其中文件名取自路径的basename从而触发浏览器下载行为通过createReadStream将文件包装为Readable流后交给FILE_TPL处理。通过FILE_TPL可以修改返回结构HttpServerResponse.FILE_TPL (data: Readable, isSuccess: boolean) { /*...*/};SSE 响应Server-Sent Events从 v3.17.0 开始框架提供了内置的 SSEServer-Sent Events支持。SSE 的数据定义如下需要按下面的格式返回接口定义见 interface.tsexport interface ServerSendEventMessage { data?: string | object; event?: string; id?: string; retry?: number; }通过HttpServerResponse定义一个返回实例import { Controller, Get, Inject, sleep, HttpServerResponse } from midwayjs/core; import { Context } from midwayjs/koa; Controller(/) export class HomeController { Inject() ctx: Context; Get(/) async home() { const res new HttpServerResponse(this.ctx).sse(); // ... return res; } }可以通过send和sendEnd进行数据传递const res new HttpServerResponse(this.ctx).sse(); res.send({ data: abcde }); res.sendEnd({ data: end });调用sendEnd后请求将被关闭。也可以通过sendError发送错误const res new HttpServerResponse(this.ctx).sse(); res.sendError(new Error(test error));SSE 的底层行为ServerSendEventStream的实现位于 response/sse.ts是一个继承自Transform的流对象其关键行为包括首次收到数据时自动设置Content-Type: text/event-stream、Cache-Control: no-cache, no-transform、Connection: keep-alive、X-Accel-Buffering: no等 SSE 标准响应头并开启 socket 的setKeepAlive(true)将每条消息按 SSE 协议格式化为event:/retry:/id:/data:行对象类型的data会先JSON.stringify多行文本按\n拆分逐行发送消息之间以空行分隔sendError(error)实际发送一条event: error、data为错误消息的帧sendEnd(message)会为消息补充event: close后发送并关闭请求构造时监听ctx.req的close事件客户端断开时自动结束流handleClose此外还提供了forward()方法可将 OpenAI / Anthropic SDK 等异步迭代流按eventsource、openai、anthropic协议转发为兼容的 SSE 帧openai协议结束时发送[DONE]标记相关选项定义见 interface.ts并在 test/response/http.test.ts 中有基于真实eventsource客户端与 OpenAI / Anthropic SDK 的端到端测试。覆盖 SSE 模板通过SSE_TPL可以修改返回结构import { ServerSendEventMessage } from midwayjs/core; HttpServerResponse.SSE_TPL (data: ServerSendEventMessage) { /*...*/};注意文档中该示例写作FILE_TPL属于笔误正确属性为SSE_TPL见 response/http.ts 源码定义。这个模板只处理成功的数据不会处理sendError的情况且返回也必须是ServerSendEventMessage格式。基础数据响应脱离 Http 场景的 ServerResponse除了 Http 场景之外框架提供了基础的ServerResponse类用于其他非 HTTP场景。ServerResponse包含json、text、blob三种数据返回方法以及success和fail两个设置状态的方法行为和HttpServerResponse一致区别仅在于HttpServerResponse会额外写入 HTTP 响应头。通过继承、覆盖等行为可以非常简单地处理响应值。比如对不同用户做返回区分// src/response/api.ts export class UserServerResponse extends HttpServerResponse {} UserServerResponse.JSON_TPL (data, isSuccess) { if (isSuccess) { return { status: 200, ...data, }; } else { return { status: 500, message: limit exceed }; } }; export class AdminServerResponse extends HttpServerResponse {} AdminServerResponse.JSON_TPL (data, isSuccess) { if (isSuccess) { return { status: 200, router: data.router, ...data }; } else { return { status: 500, message: interal error, ...data }; } };使用返回import { Controller, Get, Inject, sleep, HttpServerResponse } from midwayjs/core; import { Context } from midwayjs/koa; import { UserServerResponse, AdminServerResponse } from ../response/api; Controller(/) export class HomeController { Inject() ctx: Context; Get(/) async home() { // ... if (this.ctx.user xxx) { return new AdminServerResponse(this.ctx).json({ router: /, dbInfo: { // ... }, userInfo: { role: admin, }, status: ok, }); } return new UserServerResponse(this.ctx).json({ status: ok, }); } }这个示例同时展示了两种定制方式的组合UserServerResponse与AdminServerResponse各自继承HttpServerResponse并覆写JSON_TPL互不影响全局默认模板而模板内通过...data展开传入的数据实现了「在不同业务分支返回不同结构」的诉求可复用于控制器、服务层乃至非 HTTP 场景的返回值封装。赞分享后端微服务云原生【免费下载链接】midway A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 项目地址https://gitcode.com/gh_mirrors/mi/midway点击查看免费下载相关推荐Midway 数据响应统一方案ServerResponse 与 HttpServerResponse 实战指南Midway 数据响应统一方案ServerResponse 与 HttpServerResponse 实战指南 导读 从 v3.17.0 开始Midway后端微服务云原生Midway 数据响应Data Response体系详解ServerResponse / HttpServerResponse 统一响应格式实战Midway 数据响应Data Response体系详解ServerResponse / HttpServerResponse 统一响应格式实战 自 v3后端微服务云原生ASP.NET Boilerplate AJAX 实战指南abp.ajax 封装、统一响应模型与错误处理ASP.NET Boilerplate AJAX 实战指南abp.ajax 封装、统一响应模型与错误处理 本文以 ASP.NET BoilerplateAB后端Web框架依赖注入认证鉴权上一篇Telegraf Serializer 插件开发指南基于 EXAMPLE_README 模板编写高质量序列化器文档下一篇Flipper Zero 固件中的 nanopb 安全模型可信数据划分、内存不变量与防御性解码实践创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Apollo Vue 查询状态模型:深入解析 @vue/apollo-composable 的 Current 接口

Apollo Vue 查询状态模型:深入解析 @vue/apollo-composable 的 Current 接口

前端GraphQL 【免费下载链接】apollo 🚀 Apollo/GraphQL integration for VueJS 项目地址: https://gitcode.com/gh_mirrors/apollo2/apollo 点击查看 免费下载 导读 Current 是 vue/apollo-composable 中 useQuery 返回的判别联合(discrim…

2026/10/10 2:38:02 阅读更多 →
cyberstrikelab database 1(猜测)

cyberstrikelab database 1(猜测)

这个可能涉及下载oracle,这个月流量不够了,下个月在验证 可能涉及cve-2012-1675和cve2012-3137 cve-2012-1675工具 GitHub - interference-security/oracle-tns-poison: Oracle TNS Listener Remote Poisoning GitHub cve-2012-3137工具 GitHub - h…

2026/10/10 2:38:02 阅读更多 →
VSCode里clangd跳转失效?从compile_commands.json到TaoToken的排查路径

VSCode里clangd跳转失效?从compile_commands.json到TaoToken的排查路径

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 2:38:02 阅读更多 →

最新新闻

Docker安装报错全解析:从daemon权限到内核模块的排查指南

Docker安装报错全解析:从daemon权限到内核模块的排查指南

你有没有遇到过这样的场景:费了好大劲把 Docker 装上,兴冲冲地敲下docker ps,结果屏幕上一行红字:permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock这种感觉就像门锁装好了…

2026/10/10 3:19:15 阅读更多 →
CE318太阳光度计数据处理:AOD与WV反演实战指南

CE318太阳光度计数据处理:AOD与WV反演实战指南

简介:这份资源面向大气科学、遥感与气象观测方向的学习者和科研人员,围绕CE318型太阳光度计的观测数据,提供从原始数据读取到气溶胶光学厚度(AOD)与水汽含量(WV)反演的完整处理思路。资源包共5个…

2026/10/10 3:19:15 阅读更多 →
C++排序选型指南:sort、stable_sort与partial_sort

C++排序选型指南:sort、stable_sort与partial_sort

最开始被排序这件事坑到,是在某个线上榜单的开发任务里。数据量其实不大,也就几千条,需求说得很直白:按分数从高到低排,分数相同的先提交者靠前。我想都没想就调了sort,自己写了个分数比较的lambda&#xf…

2026/10/10 3:19:15 阅读更多 →
环境模拟中的木马程序分析:从渗透测试到防御反推

环境模拟中的木马程序分析:从渗透测试到防御反推

"基于环境模拟的木马程序制作与渗透测试"——说实话,第一次看到这个标题的人,多半会以为这是某种"黑客速成教程"。但我做了几年安全方向的研究,可以负责任地说:真正有价值的东西不在"制作"本身&…

2026/10/10 3:19:15 阅读更多 →
练得够不够狠?openGym的RIR/RPE努力度评分及统计功能详解

练得够不够狠?openGym的RIR/RPE努力度评分及统计功能详解

练得够不够狠?openGym的RIR/RPE努力度评分及统计功能详解 【免费下载链接】openGym https://github.com/DuarteSantos8/openGym 项目地址: https://gitcode.com/gh_mirrors/ope/openGym openGym 是一款自托管的健身训练追踪器,除了记录重量和次数…

2026/10/10 3:19:15 阅读更多 →
C++编译期分支全解析:if constexpr、enable_if与标签分发

C++编译期分支全解析:if constexpr、enable_if与标签分发

1. 为什么编译期的“分支”值得单独拿出来讲1.1 一个每天都在发生的真实场景写 C 模板写久了,谁都会被同一件事卡过:函数模板里拿到一个泛型 T,你想对不同的 T 做不同的处理,最直觉的写法是在函数体里写一个运行期 if 去判断类型&…

2026/10/10 3:18:15 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →