koa踩坑日记(一)

957 阅读1分钟

在学习koa的过程中,遇到了一个比较坑的地方,我以为是koa的bug,还给koa提了个issue,然后有个朋友给了个能解决问题的方法,我试了下,确实报错解决了,但是方法太粗暴。后来还是通过看koa源码和nodejs的http模块,找到了问题所在。

废话不多说,“Talk is cheap, show me the code”.

const Koa = require("koa")
const app = new Koa()

const [port, host] = ["8082", "0.0.0.0"]

app.use(async (ctx, next) => {
    ctx.body = "hello world"
    // 当把ctx.message设置为中文或者其他语言,例如日语的时候,会抛出
    // TypeError [ERR_INVALID_CHAR]: Invalid character in statusMessage这个错误
    ctx.message = "随便一串中文"
    
    await next()
});

// 格式化返回数据,对这个问题没有影响
app.use(async (ctx, next) => {
    ctx.body = {
        code: 0,
        data: ctx.body,
        msg: ctx.message
    }
    
    await next()
})

app.listen(port, host, () => {
    console.log(`APP server running on http://${host}:${port}`);
})

当把ctx.message设置为中文或者其他语言,例如日语的时候,服务会报错,并且这个错误通过app.on('error')也是捕捉不到的,然后浏览器会提示'500 Internal Server Error'。什么原因呢?

koa源码

response.js中:

image.png 可以看到,当设置ctx.message = '随便一串中文'时,调用的是

set message(msg) {
    this.res.statusMessage = msg;
}

那么res.statusMessage是啥? 在application.js中:

image.png

image.png

image.png 可以看到,res.statusMessage实际上是nodejs的response对象的response.statusMessage,那这个是干嘛的呢?statusMessage其实是http状态码的一部分,我查了下http协议的RFC2616,这个东西叫做Reason Phrase,是对http状态码描述,给人看的。至于为什么不能设置为中文或其他语言,我没找到原因,应该涉及到协议底层编码的问题,我不懂这个!

总结

遇到问题,多找资料(^o^)/~