Koa router的反思 - 利用函数式编程封装中间件

2017-08-19  本文已影响133人  编程go

关键词: Koa router、函数式编程、 中间件

问题描述:
在开发微信公众号时,微信服务器与我自己的服务频繁的交互。微信的服务器对我的服务器目前也仅仅有两种方式: 一种是Get 请求另外一种是Post 请求。于是我在设计Koa 的router 时,想把所有关于微信服务器与我的服务器交互的逻辑统一写在一个中间件中。如下:

export const router = app => {
    const router = new Router()  
    router.all('/wechat-hear', async (ctx, next) => {
        // call wetchat middleware
        wechatMiddle(config.wechat, reply)(ctx, next)
    })
 
    app
        .use(router.routes())
        .use(router.allowedMethods())
}

明显可以看出wechatMiddle 利用了函数式编程,这样的设计自认为代码的逻辑更强了。但是在测试时总是出现下面的exception:

(node:41169) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError [ERR_ASSERTION]: headers have already been sent

下面时中间件的代码:

export default function (opts, reply) {
    return async function(ctx, next) {
        // Get wechat access token,.
        if (ctx.method === 'GET') {
              // do validation
        } else if (ctx.method === 'POST') {
              // do validation
        }
        // parse request from wchat to object
        const data = await getRawBody(ctx.req, {
            length: ctx.length,
            limit: '1mb',
            encoding: ctx.charset
        })
        const content = await util.parseXML (data)

        var xml = 
        `<xml>
                <ToUserName><![CDATA[${content.xml.FromUserName[0]}]]></ToUserName>
                <FromUserName><![CDATA[${content.xml.ToUserName[0]}]]></FromUserName>
        </xml>`
        ctx.body = xml
        ctx.status = 200
        ctx.type = 'application/xml' 
    }
} 

踩过的坑:

    router.all('/wechat-hear', async (ctx, next) => {
        // call wetchat middleware
        await wechatMiddle(config.wechat, reply)(ctx, next)
    })

坑后总结:
前两步思路还是正确的,第三步上半部分也没有问题,但是在后来暴力调试劳力伤神这一点要总结,如果在第三步的下半部分可以稍微王router koa中调用中间件的方法思考下,这个问题则可以很快完美的解决了。

上一篇下一篇

猜你喜欢

热点阅读