写个人博客的时候,提交博客内容到数据库的时候,后台报错Cannot render headers after they are sent to the client,搜索发现,是连续发送了2条入库请求导致的,到数据库查看发现插入了2条新数据
猜测可能是传入的数据太大,被截断了分成了2条插入数据库的
Error [ERR_HTTP_HEADERS_SENT]: Cannot render headers after they are sent to the client
at ServerResponse.writeHead (_http_server.js:236:13)
at D:\xhn\programs\deltaning.com\web\BlogController.js:139:17
at Query.<anonymous> (D:\xhn\programs\deltaning.com\dao\BlogDao.js:23:13)
at Query.<anonymous> (D:\xhn\programs\deltaning.com\node_modules\mysql\lib\Connection.js:526:10)
at Query._callback (D:\xhn\programs\deltaning.com\node_modules\mysql\lib\Connection.js:488:16)
at Query.Sequence.end (D:\xhn\programs\deltaning.com\node_modules\mysql\lib\protocol\sequences\Sequence.js:83:24)
at Query._handleFinalResultPacket (D:\xhn\programs\deltaning.com\node_modules\mysql\lib\protocol\sequences\Query.js:149:8)
at Query.OkPacket (D:\xhn\programs\deltaning.com\node_modules\mysql\lib\protocol\sequences\Query.js:74:10)
at Protocol._parsePacket (D:\xhn\programs\deltaning.com\node_modules\mysql\lib\protocol\Protocol.js:291:23)
at Parser._parsePacket (D:\xhn\programs\deltaning.com\node_modules\mysql\lib\protocol\Parser.js:433:10)
1、检查插入库的方法
在插入库的方法中,打印传入的数据,发现打印了2次,就是一条数据被截断成两条分别被打印出来的,打印结果如下
insert blog.................
77777777777777 { content:
'<p>之前公司有https的需求,就在服务器上用nginx配置ssl证书。</p><p><br></p><p>今天突然有用户说安卓手机提示网站证书有问题</p><p class="">我在pc端浏览器和ios手机上访问都没有出现这个问题,有个别安卓机出现了这个问题,就找了个一个<a href="https://www.geocerts.com/ssl-checker" target="_blank" rel="nofollow noopener noreferrer">网站</a>检查一下网站的ssl证书,发现确实存在问题</p><p class="">如下图所示,说是证书链不完整</p><p class=""><br></p><p><img src="data:image/jpeg;base64,iVBORw0KG
views: 0,
tags: 'yujj',
ctime: 1585798851,
utime: 1585798851 }
insert blog.................
77777777777777 { content:
'CiCFDIiiEEEIIICYII="><br></p><p><br></p><p>其实问题就是crt文件中缺少中间证书,使用<a href="https://myssl.com/chain_download.html" target="_blank" rel="nofollow noopener noreferrer">myssl.com/chain_downl…</a>可以生成中间证书,生产中间证书之后,把中间证书的内容完完全全的复制并追加到crt/cer文件后面(不要有空格,空行)就可以了</p><div><br></div>',
title: '888888888888888888',
views: 0,
tags: 'yujj',
ctime: 1585798851,
utime: 1585798851 }如上面的代码所示,content字段被分成了2段打印出来的
2、检查调用插入库方法的接口
app.post('/editBlog', function editBlog(req, res) {
// 获取url中的参数
var params = url.parse(req.url, true).query;
var tags = params.tags.replace(/ /g, "").replace(/,/g, ',');
req.on('data', function (data) {
// 将数据插入到数据库
console.log('6666666666666666666666',data.toString());
blogDao.insertBlog(data.toString(), params.title, tags, 0, timeUtil.getNowDate(), timeUtil.getNowDate(), function (result) {
res.writeHead(200);
res.write(respUtil.writeResult('success', '操作成功', null));
res.end();
})
})
})
打印结果
6666666666666666666666 <p>之前公司有https的需求,就在服务器上用nginx配置ssl证书。</p><p><br></p><p>今天突然有用户说安卓手机提示网站证书有问题</p><p class="">我在pc端浏览器和ios手机上访问都没有出现这个问题,有个别安卓机出现了这个问题,就找了个一个<a href="https://www.geocerts.com/ssl-checker" target="_blank" rel="nofollow noopener noreferrer">网站</a>检查一下网站的ssl证书,发现确实存在问题</p><p class="">如下图所示,说是证书链不完整</p><p class=""><br></p><p><img src="data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAzEAAAEQCAYAAACA+fo6AAAAAX
...
6666666666666666666666 EEENFUfw/kznzSCFaxZMAAAAASUVORK5CYII="><br></p><p><br></p><p>其实问题就是crt文件中缺少中间证书,使用<a href="https://myssl.com/chain_download.html" target="_blank" rel="nofollow noopener noreferrer">myssl.com/chain_downl…</a>可以生成中间证书,生产中间证书之后,把中间证书的内容完完全全的复制并追加到crt/cer文件后面(不要有空格,空行)就可以了</p><div><br></div>
果然,打印出了2段被分裂的内容
就说明其实是接口调用了2次入库的方法,到底是什么原因在往上查
3、检查前端调用接口传入的数据
发现只调用了1次接口,传输的数据也是完整的
由此发现,是接口层接收数据出了问题
就猜想是不是req.on('data', function() {})监听data事件对数据有接收限制,就改成了使用body-parser去接收数据
Request Payload方式是以“流“”的方式出入到后台,需要监听data事件来获取完整的数据。
app.post('/editBlog', function editBlog(req, res) {
// 获取url中的参数
var params = url.parse(req.url, true).query;
var tags = params.tags.replace(/ /g, "").replace(/,/g, ',');
// 监听client端发送的请求数据
console.log(req.body.content)
if (!req.body) {
return res.sendStatus(400)
}
var content = req.body.content;
blogDao.insertBlog(content, params.title, tags, 0, timeUtil.getNowDate(), timeUtil.getNowDate(), function (result) {
// console.log('controller 22222222222222222222222', content);
res.writeHead(200);
res.write(respUtil.writeResult('success', '操作成功', null));
res.end();
});
})
使用了body-parser之后,发现报错Error: request entity too large
传入的参数太大了,body-parser默认的负载限制是100kb,修改负载限制为50mb
app.use(bodyParser.urlencoded({limit: '50mb', extende:true}));
app.use(bodyParser.json({limit: '50mb'}));不报错了,后台打印的数据也是完成的一条数据,去查看数据发现只插入了1条,以为没问题了,点击content字段发现,插入的内容不完整,oh my god~ 这是怎么回事呢,content字段的类型已经设置为了text,难道text还是不够,把text类型改成了longtext,然后发现,ok了,没有报错,数据库插入了1条数据,数据是完整的
完美解决
附赠一下mysql字符串类型的长度
问题解决之后,我又把body-parser改回了req.on('data', function() {})尝试了一下,还是插入了2条数据到数据库,数据是被截断的,就确认是监听data事件的问题,data事件把收到的请求数据分成了2条分别插入数据库的,也返回了2条响应数据给浏览器,浏览器接收到1条之后,接口通道就关闭了,所以后台发送第2条数据的时候就报错了