1. 安装redis库

npm install --save redis

2. ../../.../config.js

module.exports = {
    // ...
    redis: {
        host: "172.16.0.224",
        port: 6379,
        options: {
            password: "myredispassword",
            timeout: 3000
        }
    },
    spam: {
        limit: 3,
        seconds: 60,
    },
    // ...
}

3. Cache.js

const redis = require("redis");
const config = require("../config/config");

let c = config.redis,
    client = redis.createClient(c.port, c.host, c.options);

client.on("error",function(err){
    console.log(err);
});

function Cache() {}

let text = async(key)=>{
    let doc = await new Promise( (resolve) => {
        client.get(key,function(err, res){
            return resolve(res);
        });
    });
    return JSON.parse(doc);
};

Cache.set = function(key, value) {
    value = JSON.stringify(value);
    return client.set(key, value, function(err){
        if (err) {
            console.error(err);
        }
    });
};

Cache.get = async(key)=>{
    return await text(key);
};

Cache.expire = function(key, time) {
    return client.expire(key, time);
};

module.exports = Cache;

Usage:

    // begin 请求频繁限制
    let ip = Client.getIP(req);
    let key = "mail:" + ip;
    let ans = await Cache.get(key);

    let count = 0;
    if (ans) {
        logger.debug(ans);
        count = parseInt(ans);
    }
    count++;
    Cache.set(key, count);
    // 一分钟过期时间
    Cache.expire(key, config.spam.seconds);

    if (count > config.spam.limit) {
        res.json({
            code: 16,
            data: count,
            message: "请求太频繁"
        });
        return;
    }
    // end 请求频繁限制

 

///

 另一种方法 bluebird

需要用到的库:

http://bluebirdjs.com/docs/getting-started.html

 

* ./config/cache.js

redis配置

module.exports = function() {
    return {
        session: {
            host: "172.16.0.224",
            port: 6379,
            option: {
                password: "Mzh123",
                db: 0,
                connect_timeout: 500,
            }
        },
        app: {
            host: "172.16.0.224",
            port: 6379,
            option: {
                password: "Mzh123",
                db: 1,
                connect_timeout: 500,
            }
        }
    };
};

* ./providers/Redis.js

const redis = require("redis");
const cacheConfig = require("../config/cache")();
const bluebird = require('bluebird');

function Redis() {}

/**
 *
 * @type {{session: null|RedisClient}}
 * @private
 */
Redis._connection = {
    "session": undefined,
    "app": undefined,
};

Redis.getConnection = function(name) {
    name = name || "session";
    if ( Redis._connection[name] ) {
        return Redis._connection[name];
    }

    let opt = cacheConfig[ name ];
    let client = redis.createClient(opt.port, opt.host, opt.option);
    client.on('connect', function() {
        console.log('Redis connected.')
    });
    client = bluebird.promisifyAll(client);
    Redis._connection[name] = client;

    return Redis._connection[name];
};

module.exports = Redis;

关键代码: 

client = bluebird.promisifyAll(client);

promisifyAll 之后要重新赋值给client

 

* ./app/controllers/Middleware.js

'use strict';

var jwt = require('jsonwebtoken');
// var koaJwt = require('koa-jwt');
var constants = require('../../config/const');
var Redis = require('../../providers/Redis');

function Middleware() {}

Middleware.hasBody = async (ctx, next) => {
    let body = ctx.request.body || {};
    console.log(body);

    if (Object.keys(body).length === 0) {
        ctx.body = {
            code: 2,
            err: '参数'
        };

        return next
    }
    await next()
};

// 检验token
Middleware.hasToken = async (ctx, next) => {
    var accessToken = ctx.headers.token;

    if (!accessToken) {
        accessToken = ctx.request.body['token'];
    }

    if (!accessToken) {
        ctx.body = {
            code: 4,
            data: null,
            message: 'Token missing'
        };
        return next
    }

    // :{"userid":"5cc7f30396e85920c0c5b885","username":"mingzhanghui","iat":1556609542,"exp":1556609602}
    let c = constants();
    let tokenContext = jwt.decode(accessToken);
    /**
     * @type RedisClient
     */
    let cache = Redis.getConnection('session');
    let key = c.session_prefix + tokenContext.userid;
    console.log(key);
    // if (+new Date() >= c.exp * 1000) {
    const res = await cache.getAsync( key );
    if (! res) {
        ctx.body = {
            code: 5,
            data: null,
            message: 'Token expired',
        };
        return
    }
    let sess = JSON.parse(res);
    console.log(sess);

    ctx.session.user = {
        id: sess.userid,
        name:sess.username
    };
    await next();
};

module.exports = Middleware;

 

因为用了bluebird 的PromisifyAll 所以根据get方法 有了 getAsync

await cache.get(key, function(err, res) {

 // ...

})

这里返回bool类型,不是期望的redis 返回结果

改为 const res = await cache.getAsync( key );

这样 res 就是redis的返回结果

 

* router.js

'use strict';

const Router = require('koa-router');
const Middleware = require('./app/controllers/middleware');
const UserController = require('./app/controllers/UserController');
const TestController = require('./app/controllers/TestController');

module.exports = function(){
  var router = new Router({
      prefix: ''   /* /api */
  });

  router.get('/ping', async function(ctx, next) {
      ctx.body = {
          "code": 0,
          "data": null,
          "message": "pong"
      };
      ctx.contentType = 'application/json';
  });

  // user
  router.post("/users/login", Middleware.hasBody, (new UserController()).login);
  // need login  middleware.hasToken
  router.get('/users/getInfo', Middleware.hasToken, (new UserController()).getInfo);
  router.get('/users/logout', Middleware.hasToken, (new UserController()).logout);

  router.post('/users/signup', Middleware.hasBody, (new UserController()).signup);

  router.post('/users/update', Middleware.hasBody, (new UserController()).update);
  // router.get('/users/delete', (new UserController()).delete);
  // DB Interface test
  router.get('/users/all', (new UserController()).all);

  router.get('/test', (new TestController()).date);

  return router
};

* ./app/controllers/UserController.js

 

/**
 * 取得用户信息
 * @param ctx
 * @param next
 * @returns {Promise<void>}
 */
UserController.prototype.getInfo = async function(ctx, next) {
    // let token = ctx.headers.token;
    let userid = ctx.session.user.id;
    console.log("userid=" + userid);
    if (!userid) {
        ctx.body = {
            code: -1,
            data: null,
            message: "Redis get error"
        };
        return;
    }

    await Users.findOne({"_id": userid}).exec().then(function (doc) {
        if (!doc) {
            ctx.body = {
                code: 2,
                data: doc,
                message: "User not found"
            };
            return;
        }
        ctx.body = {
            code:0,
            data: doc,
            message: "OK"
        };
    });

};

 

mongodb:

* ./config/db.js

module.exports = function() {
    return {
        default: 'mongodb://eclassuser:eclassweb123@172.16.0.224/crm_sale'
    };
};

* ./app/models/mongoose.js

"use strict";

const bluebird = require('bluebird');
const Mongoose = require('mongoose');

const dbDefaultURI = require('../../config/db.js')().default;

let mongoose = bluebird.promisifyAll(Mongoose);
let defaultMongooseConn = mongoose.createConnection(dbDefaultURI);

defaultMongooseConn.on('error', function(err) {
    // logger.error(err);
    console.error(err);
});

module.exports = {
    mongoose: mongoose,
    defaultMongooseConn: defaultMongooseConn
};

* ./app/models/Users.js

"use strict";

let m = require("./mongoose");
const mongoose = m.mongoose;
const defaultMongooseConn = m.defaultMongooseConn;

var Schema = mongoose.Schema;

var schema = new Schema({
    username: {type: String, required: true},
    password: {type: String},
    createdAt: {type: Date, default: Date.now()},
    updatedAt: {type: Date, default: Date.now()},
});
schema.index({username: 1}, {unique: true});

// Defines a pre hook for the document.
schema.pre('save', function(next) {
    if (this.isNew) {
        this.createdAt = this.updatedAt = Date.now()
    }
    else {
        this.updatedAt = Date.now()
    }
    next()
});

var Users = defaultMongooseConn.model('users', schema);

module.exports = Users;