如何在koa-send中使用opt.setHeaders?头被覆盖原因及示例求解
官方文档指出:"你仅应当在需要修改Cache-Control或Last-Modified响应头时使用setHeaders配置项,因为在send执行前设置头是无效的(会被send方法覆盖),而在send执行后设置又太晚,此时响应头已经发送完成。"
自定义响应头被send覆盖的原因
常见服务端框架(如Express、Koa的静态资源中间件等)的send方法是对HTTP响应发送流程的标准化封装,固定执行逻辑如下:
- 第一步:接收响应体内容,自动计算响应体的MIME类型、字节长度等核心参数
- 第二步:清空所有未提交的临时响应头配置,写入和响应体匹配的默认核心头(包括
Content-Type、Content-Length、默认Cache-Control等) - 第三步:执行预留的
setHeaders钩子函数,仅允许用户修改Cache-Control、Last-Modified两类头,避免破坏核心头和响应体的匹配关系 - 第四步:将响应头正式发送给客户端
- 第五步:发送响应体内容,结束请求
如果不在setHeaders钩子中配置头:
- 在
send调用前设置的头会被第二步的重置逻辑直接覆盖,完全不生效 - 在
send调用后设置的头,此时已经走完第四步,响应头已经发送到客户端,会直接抛出Cannot set headers after they are sent to the client类错误
使用示例
以下以Express框架的静态资源服务配置为例:
const express = require('express'); const app = express(); // 正确用法:通过setHeaders配置缓存相关响应头 app.use(express.static('public', { setHeaders: (res, filePath) => { // 给html文件设置协商缓存 if (filePath.endsWith('.html')) { res.setHeader('Cache-Control', 'public, max-age=0'); res.setHeader('Last-Modified', new Date().toUTCString()); } // 给图片、字体等静态资源设置7天强缓存 if (/\.(png|jpg|woff2)$/.test(filePath)) { res.setHeader('Cache-Control', 'public, max-age=604800, immutable'); } } })); // 错误用法1:send前直接设置头,会被覆盖 app.get('/wrong-demo1', (req, res) => { res.setHeader('X-Custom-Test', '123'); // 该头会被send方法的重置逻辑删除 res.send('<h1>测试页面</h1>'); }); // 错误用法2:send后设置头,响应头已发送,会报错 app.get('/wrong-demo2', (req, res) => { res.send('<h1>测试页面</h1>'); res.setHeader('Cache-Control', 'no-cache'); // 直接抛出请求头已发送的错误 }); app.listen(3000, () => console.log('服务启动在3000端口'));
内容的提问来源于stack exchange,提问作者lin Lin
相关产品推荐
相关产品推荐

