木灵鱼儿
阅读:1778
koa框架25 整合2
session
session需要创建keys,所以在调用session之前我们需要创建一个keys生成器
创建utils目录
在该目录下创建一个genkey.js文件
const {
v4: uuid
} = require("uuid");
const config = require("../config");
const fs = require("fs");
//循环生成keys
let keys = [];
for (let i = 0; i < config.keys_count; i++) {
let key = "";
while (key.length < config.keys_len) {
key += uuid().replace(/\-/g, "");
};
key = key.substring(0, config.keys_len);
keys.push(key);
};
//保存到本地
fs.writeFileSync(config.keys_path, JSON.stringify(keys));
console.log(`create keys ${config.keys_count}`);
for循环生成keys后保存到本地,config.js里面增加三个配置
config.js
const path = require("path");
module.exports = {
//服务器
port: 8081,
//数据库
sql: {
host: "localhost",
prot: 3306,
user: "root",
password: "123456",
database: "koa"
},
//redis
radsi: {
host: "localhost",
port: 6379,
pass: undefined, //redis密码为空用undefined表示
},
//upload
up_path: path.resolve(__dirname, "upload"), //默认上传路径
up_size: 20 * 1024 * 1024, //默认文件大小
//keys
keys_count: 1024,
keys_path: path.resolve(__dirname, ".keys"),
keys_len: 1024
}
keys生成完毕后我们需要引入
libs/session.js
const session = require("koa-session");
const client = require("./redis");
const config = require("../config");
const fs = require("promise-fs");
module.exports = async function (server) {
//读取本地的keys文件
try {
let buffer = await fs.readFile(config.keys_path);
server.keys = JSON.parse(buffer.toString());
} catch (e) {
console.error("读取key文件失败,请重新生成", e);
return;
};
//激活session
server.use(session({
maxAge: config.session_maxAge,
renew: true,
store: {
async get(key, maxAge) {
const data = await client.getAsync(key);
if (!data) return {};
try {
return JSON.parse(data);
} catch (e) {
return {};
}
},
async set(key, session, maxAge) {
await client.psetexAsync(key, maxAge, JSON.stringify(session));
},
async destroy(key) {
await client.delAsync(key);
}
}
}, server));
}
server.js
const Koa = require("koa");
const config = require("./config");
const opn = require("opn");
const network = require("./libs/network");
const { post, upload } = require("./libs/post-body");
const Router = require("koa-router");
//server
let server = new Koa();
(async () => {
//数据库
server.context.db = await require("./libs/mysql");
//Redis
let client = await require("./libs/redis");
server.context.redis = client;
//全局错误处理
server.use(async (ctx, next) => {
try {
await next();
} catch (e) {
ctx.status = 500;
ctx.body = 'internal server error';
}
});
//session
await require("./libs/session")(server);
//router
let router = new Router();
//post
// router.post("/post", post(), async ctx => {
// console.log(ctx.request.fields);
// });
//upload
// router.post("/upload", ...upload({
// path: undefined,
// size: undefined,
// error: (ctx, e) => { }, //错误回调
// sizeError: (ctx, e) => { } //文件过大的错误回调
// }), async ctx => {
// console.log(ctx.request.fields);
// ctx.body = '上传成功';
// });
router.get("/", async ctx => {
if (!ctx.session.view) {
ctx.session.view = 1;
} else {
ctx.session.view++;
}
ctx.body = `第${ctx.session.view}次`;
})
//激活router
server.use(router.routes());
//监听
server.listen(config.port);
//输出运行地址
network(config.port);
opn(`http://localhost:${config.port}`, { app: 'chrome' });
})();
我们只需要传入server对象就行了,而redis对象,在node里面只要有一个地方先引入并使用了,第二次引入这个文件并不会再创建一个redis对象,而是对上一个redis对象的引用,所以我们requery同一个js文件,不会创建多个。
这样的话,其他的东西都是独立的,不需要再传什么参数了。
路由
路由有一个专门存放的文件夹:router,一般我们会在下面创建不同的文件夹作为区分,再通过index.js来着作为入口文件。
router
|
—— admin
| |
| —— index.js
—— web
| |
| —— index.js
|
—— index.js
大概是这么一个结构,可以自己进行嵌套。
router/index.js
const Router = require("koa-router");
let router = new Router();
//admin
router.use("/admin", require("./admin"));
//web
router.use("", require("./web"));
module.exports = router.routes();
admin&wen下的index
这两个目前没啥东西,内容都一样的.
const Router = require("koa-router");
let router = new Router();
module.exports = router.routes();
server.js
const Koa = require("koa");
const config = require("./config");
const opn = require("opn");
const network = require("./libs/network");
const { post, upload } = require("./libs/post-body");
//server
let server = new Koa();
(async () => {
//数据库
server.context.db = await require("./libs/mysql");
//Redis
server.context.redis = await require("./libs/redis");;
//全局错误处理
server.use(async (ctx, next) => {
try {
await next();
} catch (e) {
ctx.status = 500;
ctx.body = 'internal server error';
}
});
//session
await require("./libs/session")(server);
//router
server.use(require("./router"));
//监听
server.listen(config.port);
//输出运行地址
network(config.port);
opn(`http://localhost:${config.port}`, { app: 'chrome' });
})();
server里面直接引入router文件夹下的index就行了。
静态资源
也就是koa-static的使用,我们之前讲过,针对不同类型的资源,自定义缓存周期。
libs/static.js
const static = require("koa-static");
const { static_path } = require("../config");
module.exports = function (router) {
//图片
router.all(/\.(jpg|png|gif|tiff|ico)$/i, static(static_path, {
maxage: 20 * 86400 * 1000
}));
//js
router.all(/\.jsx?$/i, static(static_path, {
maxage: 3 * 86400 * 1000
}));
//css
router.all(/\.css$/i, static(static_path, {
maxage: 7 * 86400 * 1000
}));
//网页
router.all(/\.(html|htm|shtml)$/i, static(static_path, {
maxage: 1 * 86400 * 1000
}));
router.all('/(.*)', static(static_path, {
maxage: 20 * 86400 * 1000
}));
};
config里面保存一个默认静态文件的路径
config.js
const path = require("path");
module.exports = {
//服务器
port: 8081,
//数据库
sql: {
host: "localhost",
prot: 3306,
user: "root",
password: "123456",
database: "koa"
},
//redis
radsi: {
host: "localhost",
port: 6379,
pass: undefined, //redis密码为空用undefined表示
},
//upload
up_path: path.resolve(__dirname, "upload"), //默认上传路径
up_size: 20 * 1024 * 1024, //默认文件大小
//keys
keys_count: 1024,
keys_path: path.resolve(__dirname, ".keys"),
keys_len: 1024,
//session
session_maxAge: 20 * 60 * 1000,
//static
static_path: path.resolve(__dirname, "static"),
}
router/index.js
因为static需要配合路由,所以我们在主路由引入
const Router = require("koa-router");
const staric = require("../libs/static");
let router = new Router();
//admin
router.use("/admin", require("./admin"));
//web
router.use("", require("./web"));
//static
staric(router);
module.exports = router.routes();
全局错误处理
也就是对404错误,和500错误优化一下。
原来我们写的全局,只有服务器报错才输出错误信息,给网页发送了一个简短的文字,但是如果ctx.body里面没有东西,有可能是没有这个路由,那么就应该返回404的,我们要针对这些做一个优化。
美化404和500一般就是通过返回一个html文件。
创建一个error目录,里面存放404.html,500.html文件
server.js
const Koa = require("koa");
const config = require("./config");
const opn = require("opn");
const network = require("./libs/network");
const { post, upload } = require("./libs/post-body");
const fs = require("promise-fs");
//server
let server = new Koa();
(async () => {
//数据库
server.context.db = await require("./libs/mysql");
//Redis
server.context.redis = await require("./libs/redis");;
//全局错误处理
let error_404 = "";
try {
error_404 = await fs.readFile(config.error_404_path);
error_404 = error_404.toString();
} catch (e) {
console.error("read 404 file error");
};
let error_500 = "";
try {
error_500 = await fs.readFile(config.error_500_path);
error_500 = error_500.toString();
} catch (e) {
console.error("read 500 file error");
};
server.use(async (ctx, next) => {
try {
await next();
if (!ctx.body) {
ctx.status = 404;
ctx.body = error_404 || "404 Error";
}
} catch (e) {
ctx.status = 500;
ctx.body = error_500 || 'internal server error';
}
});
//session
await require("./libs/session")(server);
//router
server.use(require("./router"));
//监听
server.listen(config.port);
//输出运行地址
network(config.port);
opn(`http://localhost:${config.port}`, { app: 'chrome' });
})();
ctx.body没有东西,就说明没有获取到内容,那就可以返回404了
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
centos 安装最新版 node.js
[hide]先用yum 安装一次node先升级yum update 提示下载程序,回复y安装nodeyum install nodejsyum安装的node一般都不是最新的,所以我们还需要升级node的版本npm i n -g全局安装一个n插件n lts表示安装最新的稳定版!一些常用命令n ls查看已安装的node版本n rm 16.0.3删除16.0.3版本更多功能阅读插件文档:n等待安装完毕后,此时其实版本已经安装好了,但是输入node -v还是低版本,是因为centos的用户缓存问题。我们退出登录再登录就会刷新缓存了,此时的node -v输出的就是最新版本exit 退...
node npm yarn 如何同时运行多个指令
node的bash命令其实是有对应的指令字符的,但是,这个指令只能再linux,mac上才有生效,再windows是无效的,所以了解一下就行。命令说明&&顺序执行多条命令,当碰到执行出错的命令后将不执行后面的命令&并行执行多条命令||顺序执行多条命令,当碰到执行正确的命令后将不执行后面的命令|管道符windows上进行多命令"scripts": { "dev": "cross-env NODE_ENV=development webpack --env development --progress -...
koa教程2 HttpBearerAuth 传递token
前端发送token到后端,一般有三种方式:链接中携带token,query参数post这种请求body中携带token头信息携带token但是事实上http已经为我们提供了传token的方式,是一个相对来说比较安全的方式,就是HttpBearerAuth 其实他也是一个头信息来着,只是相对来说多了一点操作,在apipost软件中,我们可以直接可视化设置如果是axios,则是需要添加一个头信息:axios({ method: 'get', url: url, responseType: 'blob', headers: { 'Authoriz...

koa教程2 微信openid登录
微信的openid,前端登录时,会发送一个code码到后端,后端接收到这个code,然后配合appid、appsecret参数,像wx发送一个get请求。wx的请求地址:GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code具体查看文档:微信官方文档-服务端可以看到这段get请求有四个参数:属性类型默认值必填说明appidstring 是小程序 appIdsecretstring 是...
koa教程2 权限分级控制
在之前的代码中,我们使用了一个scope属性来表示用户的权限,但是scope是一个数字,他的阅读性是非常差的,当其他人开发的时候,可能并不知道你这个数字是什么意思?所以,我们需要将它转义成文本。为了方便判断,我们在enum.js中增加一个用户等级的对象enum.js://通用判断是否存在该类型 function isThisType(val) { let flag = false; Object.keys(this).find(key => { if (this[key] === val) { return flag = true; } })...
koa教程2 token鉴权
之前我们在token中传入我们的自定义参数,现在我们要做一个token鉴权,很简单,如果他的token合法,就可以访问这个路由,如果不合法,就打回。这个也不能说是真正意义上的鉴权,因为他还没有判断scope值,所以只能说是简单判断。做这个判断我们就可以通过中间件的形式,于是我们在middlewares目录下创建一个auth.js文件auth.js:const parseBearerToken = require("@utils/paresBearerToken"); const jwt = require("jsonwebtoken"); cons...
koa教程2 用户登录
登录类型用户注册之后,自然是用户登录,登录的时候我们需要考虑到登录的方式,往往在正式的项目里面,登录的方式可能会有很多种:账号密码登录手机号登录小程序一键登录那么我们登录的时候就要进行判断,设置一个type的属性,用于在登录时判断用户是什么类型的登录,这个由前端那边设定参数。type:1为账号密码登录,2为手机号登录,3为小程序一键登录作为判断,我们可以写一个查询表(枚举),在项目根目录创建一个lib目录,在里面创建一个enum.js文件。enum.js://通用判断是否存在该类型 function isThisType(val) { let flag = false; Obje...
node 自定义路径别名
用过vue cli的话,对路径中的@应该不陌生,他表示根目录,但是在node的环境里面,我们编写模块并引入时,并没有这种方便的写法。在node环境中,我们可以通过process.cwd()来表示根目录,但是这样的话,每次使用绝对路径引入,路径总是需要写一大堆拼接。const db = require(`${process.cwd()}/config/config`).database;这样略显麻烦,于是我们可以在全局写一个引入插件的方法:global.myRequire = function (path) { return require(`${process.cwd()}/${pa...
koa教程2 密码加密
默认情况下,我们通过User.create({ email, password, nickname });模型传入的数据,是无加密的,也就是说,在数据库中密码是明文显示的,这样肯定是不行,我们需要使用bcrypt插件进行加密yarn add bcryptjs --dev打开models/user.jsuser.js:const bcrypt = require("bcryptjs"); const { sequelize } = require(`${process.cwd()}/core/db`); const { Sequelize, Model, DataTy...

koa教程2 使用sequelize连接数据库,创建用户模型
数据库的连接处理,我们需要使用sequelize插件。这个插件还有对应的数据库驱动,如果是使用mysql,那么驱动是mysql2,具体可以查看中文版的入门教程:入门yarn add sequelize mysql2 --dev安装完成后我们先需要创建数据库连接。连接数据库在根目录/core目录**下创建一个db.js文件用于连接数据库。在连接数据库之前,我们需要一些数据库的参数,如账号,密码,端口,数据库名字,数据库地址,为了方便管理配置,我们在根目录创建一个config目录,里面存放一config.js文件 ,这个之前的教程我们就已经创建好了。config.js:module.expo...