node-koa实践
主要目的是,让node作为中间层去请求第三方接口,避开浏览器的跨域问题。
完成后的为解决的问题,第三方接口做了ip限制,除非给本服务接入ip池,因此此解决方案并未使用。
框架&使用
const Koa = require('koa');
const app = new Koa();
const port = '8082'
const host = '0.0.0.0'
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(port, host, () => {
console.log(`API server listening on ${host}:${port}`);
});
通过yarn start,启动服务,在浏览器打开就会显示'Hello World',表示可以正常响应。
nodemon使用
- 在之前我们启动应用服务采用的方式都是node app.js,但我们每次修改完node代码之后都需要重启服务器即是重新运行命令才能完成修改。
- 使用nodemon替代node在开发环境下启动服务.nodemon将监视启动目录中的文件,如果有任何文件更改,nodemon将自动重新启动node应用程序。
- nodemon不需要对代码或开发方式进行任何更改。 nodemon只是简单的包装你的node应用程序,并监控任何已经改变的文件。nodemon只是node的替换包,只是在运行脚本时将其替换命令行上的node。
- 在node服务中开启debugger模式,
改造路由
- 不同路由对应不同的需求
const app = new Koa();
const port = '8082'
const host = '0.0.0.0'
app.use(async ctx => {
const { path } = ctx
if (path === '/a') {
// 功能 A
ctx.body = 'a';
} else if (path === '/b') {
// 功能 B
ctx.body = 'b';
} else if (path === '/c') {
// 功能 C
ctx.body = 'c';
} else {
ctx.body = 'hello world'
}
});
app.listen(port, host, () => {
console.log(`API server listening on ${host}:${port}`);
});
当项目功能越来越多时,将路由和路由处理函数堆在一起,后期会难以维护。因此我们拆分一下路由和路由处理函数。
1. 建一个router目录,并使用路由管理插件koa-router管理路由。
2. 在router/index中编写路由代码
const koaRouter = require('koa-router');
const router = new koaRouter();
router.get('/a', ctx => {
ctx.body = 'a'
});
router.get('/b', ctx => {
ctx.body = 'b'
});
router.get('/c', ctx => {
ctx.body = 'c'
});
module.exports = router;
3. 修改app/index
//加载路由中间件
app.use(router.routes());
app.use(router.allowedMethods());
-
拆分业务和路由
//app/router/routes.js 路由列表文件
//app/contronllers/index.js 业务处理统一导出
//app/contronllers/demo.js 业务处理文件 -
具体的拆分实现看代码...
get&post
- get请求不带参数没啥问题
- get和post请求存在拿不到数据,需要加一个参数解析的中间件。
-
我们将参数解析部分拆分出来新建app/middlewares const router = require('../router');
/** * 路由处理 */ const mdRoute = router.routes(); const mdRouterAllowed = router.allowedMethods(); module.exports = [ mdRoute, mdRouterAllowed ]; -
修改app.js .../ const compose = require('koa-compose'); const MD = require('./middlewares/');
const app = new Koa(); const port = '8082' const host = '0.0.0.0' app.use(compose(MD)); app.listen(port, host, () => { console.log(`API server listening on ${host}:${port}`); });koa-compose简化引用中间件的写法.koa-compose串联中间件可以继续了解下原理(洋葱模型) www.cnblogs.com/qiqiloved/p…
-
- 参数校验
-
安装koa-bodyparser处理请求中的参数,修改middlewares/index const koaBody = require('koa-bodyparser');
const router = require('../router'); /** * 参数解析 * https://github.com/koajs/bodyparser */ const mdKoaBody = koaBody({ enableTypes: [ 'json', 'form', 'text', 'xml' ], //解析器仅在请求类型命中 enableTypes 时才会解析,支持json/form/text/xml,默认为['json', 'form'] formLimit: '56kb', //urlencoded身体的限制。如果正文最终大于此限制,则返回 413 错误代码。默认为56kb。 jsonLimit: '1mb', textLimit: '1mb', xmlLimit: '1mb', strict: true //当设置为 true 时,JSON 解析器将只接受数组和对象。默认为true。在严格模式下,ctx.request.body将始终是一个对象(或数组),这避免了大量的类型判断。但文本正文将始终返回字符串类型。 }); /** * 路由处理 */ const mdRoute = router.routes(); const mdRouterAllowed = router.allowedMethods(); module.exports = [ mdKoaBody, mdRoute, mdRouterAllowed ];
-
不同环境下的配置
日志配置
const log4js = require('log4js');
const { outDir, flag, level } = require('../config').logConfig;
log4js.configure({
appenders: {
out: { type: 'stdout' },
cheese: { type: 'file', filename: `${outDir}/receive.log` }
},
categories: { default: { appenders: ['cheese'], level: 'info' } },
// pm2: true
});
const logger = log4js.getLogger();
logger.level = level;
module.exports = () => {
return async (ctx, next) => {
const { method, path, origin, query, body, headers, ip } = ctx.request;
const data = {
method,
path,
origin,
query,
body,
ip,
headers
};
await next();
if (flag) {
const { status, params } = ctx;
data.status = status;
data.params = params;
data.result = ctx.body || 'no content';
if(data.status!==200){
logger.error(JSON.stringify(data));
return
}
if (ctx.body.code !== 0) {
logger.error(JSON.stringify(data));
} else {
logger.info(JSON.stringify(data));
}
}
};
};
跨域配置
/**
* 跨域资源共享
*/
const mdCors = cors({
origin: "*",
credentials: true,
allowMethods: ["GET", "HEAD", "PUT", "POST", "DELETE", "PATCH"],
});
统一返回格式&报错处理
参数校验
整体框架
- common 工具
- config 环境配置
- controllers 具体的操作
- logInfo 日志打印
- middlewares 中间层
- router 路由控制
- verifyParams 参数校验 缺少service层,接入数据库和对数据做具体的处理。
用到的中间件总结
- koa-router //路由
- koa-compose //洋葱模型*
- koa-koarequest //请求接口
- koa-bodyparser //参数解析
- @hapi/joi //参数校验
- @koa/cors //跨域