koa进阶史(一)

1,设置静态文件目录,将__dirname 写成_dirname,乍看没什么毛病,但是一运行之后发现,_dirname is not defined,下次注意哈

app.use(express.static(__dirname + '/public'));
该__dirname是node的一个全局变量,表示当前模块的文件夹名称。
相对的__filename,当前模块的文件名称---解析后的绝对路径。
app.use(serve(path.join(__dirname, 'public/src')));path.join是用于两个文件夹路径的拼接,path.resolve类似于linux命令的cd。
 
2,用koa-router进行post请求时候拿不到请求数据,原来,koa用post请求URL时,post会发送表单或者json,作为request的body发送,node还是koa的request对象都不提供解析request的body对象,必须用中间件进行解析。koa提供了koa-parser中间件进行解析原始的request对象。
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());

需要注意的是:该middleware的顺序很重要,必须在router之前被注册到app对象上。至此就拿到了这个ctx.request.body对象,就是我们的请求数据。

 3,说个比较傻傻的问题,昨天是用node的request获取后台接口,返回是有了,但是因为后台接口要过cas校验,也就是要登录域账号,如果后台接口的status是302,就要重定向到相应的location,刚刚解决了这个问题,至此在记录下。
(1)在node中间层我未能够转发服务成功的原因是:koa是基于promise的,express是基于回调的,所以我在进行request方法调用的时候,需要返回一个promise对象。
(2)ctx.response的赋值是成功了,但是服务一直pending,一直以为是因为ctx.end(),PS:ctx是没有end的方法的。真是是因为我的promise没有resolve或者reject,所以接口一直处于pending状态,也就是promise的pending状态,promise的中断是需要进行resolve或者reject的。 
router 
 .get('/', pages.schedule)
 .get('/schedule', pages.schedule)
 .post('/schedule/getMeetingList/byWorkAndDate',function(ctx, next){
    let param = ctx.request.body;
    console.log('请求体===》',param)
    return new Promise((resolve,reject) => {
        request.post({
            url: byWorkAndDate,
            method: "POST",
            json: true,
            headers: {
                "content-type": "application/json",
            },
            body: JSON.stringify(param)
        },function(error,response,body){
            //重定向
            if(!error && response.statusCode == 302){
                ctx.response.status = 302;
                console.log("返回的response===>",response.headers)
                ctx.response.header = response.headers;
                ctx.response.body= null;
                console.log('ctx的设置是===》',ctx);
                let loc = response.headers.location;
                ctx.redirect('back',loc);
            }  
             
            if (!error && response.statusCode == 200) {
               ctx.body = res.body;
            }
            resolve()
        }); 
  })     
 })

4,但是重定向未跳转成功,上面的3又进行了重组,我以为问题都搞定了呢,其实没有,在设置response.header的时候那种写法是错误的,正确的写法是:

res.set(fields):使用对象同时设置 response header 中多个字段的值。

ctx.set({
  'Etag': '1234',
  'Last-Modified': date
});

代码如下:

 router 
 .get('/', pages.schedule)
 .get('/schedule', pages.schedule)
 .post('/schedule/getMeetingList/byWorkAndDate',async (ctx, next)=>{  
           let param = ctx.request.body;  
           await requestData(byWorkAndDate,param).then(result=>{
            if(result[0] == 302){
                ctx.status = 302;
                ctx.set(result[1]);
                ctx.set({
                    "Referer":result[1].location
                })
                ctx.response.redirect(result[1].location);
            }
            console.log('ctx==>',ctx);
           });
           await next(); 
 })

上面的requestData是用request进行后台请求接口数据的方法,然后resolve了两个参数,一个是statusCode,另外一个302时候是response.header,如果200就返回response.body。

{
    request: {
        method: 'POST',
        url: '/schedule/getMeetingList/byWorkAndDate',
        header: {
            host: 'localhost:3000',
            connection: 'keep-alive',
            'content-length': '81',
            accept: '*/*',
            origin: 'http://localhost:3000',
            'x-requested-with': 'XMLHttpRequest',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
            'content-type': 'application/json;charset=UTF-8',
            referer: 'http://localhost:3000/',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'zh-CN,zh;q=0.9',
            cookie: 'ESG_SFIM_SMS_SZ22_APP=ESG_SFIM_SMS_SZ22_JT_112_6'
        }
    },
    response: {
        status: 302,
        message: 'Found',
        header: {
            location: 'http://cas.sit.sf-express.com/cas/login?service=http://sfim-sms-bg.sit.sf-express.com/schedule/getMeetingList/byWorkAndDate',
            'content-length': '301',
            server: 'Jetty(9.2.7.v20150116)',
            'set-cookie': [Array],
            connection: 'close',
            via: '1.1 ID-0002262062176300 uproxy-7',
            referer: 'http://cas.sit.sf-express.com/cas/login?service=http://sfim-sms-bg.sit.sf-express.com/schedule/getMeetingList/byWorkAndDate',
            'content-type': 'text/html; charset=utf-8'
        }
    },
    app: {
        subdomainOffset: 2,
        proxy: false,
        env: 'development'
    },
    originalUrl: '/schedule/getMeetingList/byWorkAndDate',
    req: '<original node req>',
    res: '<original node res>',
    socket: '<original node socket>'
}

可以看出ctx.response是彻底被赋值成功,而且status是302,里面的location是正常的跳转链接。但是response.header里面加了Referer跳转仍然不成功;正在解决中。

 5,重定向的问题是解决了,因为前端是ajax进行接口请求的,所以在status是302的时候,node中间层进行了重置,仍然statusCode返回200,但是ctx.body里面的返回是:

redirectUrl = result[1].location.split('?')[0]+'?service=http://localhost:3000';
ctx.body={status:302,location:redirectUrl}

在前端拿到返回的数据后,先判断status的状态,如果是302则进行location的跳转,所以重定向是在前端做的。

目前node中间层开发过程中遇到的问题就是CAS认证通不过,所以日程项目的改造经过一周的时间以失败告终,因为SIT环境的CAS不支持本地服务的认证。

但是在开发过程中我进行了项目结构的模块化:

app.js   主要用来进行服务的启动,中间件的引入。

router.js  主路由

routerMap.js  路由信息

server.js     后台接口信息

【完】
 
知识就是力量。
原文地址:https://www.cnblogs.com/tangjiao/p/9465368.html