使用koa2+mongodb搭建后端

目录如下:


image.png

app.js

const path = require('path')
const config = require('./config')
const router = require('./router')
const Koa = require('koa')
const logger = require('koa-logger')
const bodyParser = require('koa-bodyparser')
const serve = require('koa-static')
const cors = require('koa-cors')
const convert = require('koa-convert')
const jwt = require('koa-jwt')
const errorHandler = require('./middlewares/errorhandler')
const log = require('./utils/log')
const Token = require('./utils/token')
const app = new Koa()

require('events').EventEmitter.defaultMaxListeners = 15

const mongoose = require('mongoose')
mongoose.connect(config.db.url)

const port = config.port || '8080'

const secret = Token.getSecret('public.pem')
const jwtOpts = {
    secret,
    isRevoked: Token.isRevoked, // 判断token是否过期
    tokenKey: 'token' // 设置ctx.state.token
}

const jwtUnlessOpts = {
    path: [
        /^\/api\/register/,
        /^\/api\/login/,
        /^\/api\/getMenuList/,
        /^\/api\/getPage/,
        /^\/api\/getDetailPage/,
        /^\/js/,
        /^\/css/,
        /^\/fonts/,
        /.jpg$/
    ]
}

// middlewares
const middlewares = [
    convert(cors()),
    logger(),
    bodyParser(),
    serve(path.join(__dirname, config.publicPath)),
    serve(path.join(__dirname, config.uploadPath)),
    // 验证是否需要token请求,unless是例外,不需要token就可以请求
    jwt(jwtOpts).unless(jwtUnlessOpts),
    errorHandler,
    router.routes(),
    router.allowedMethods()
]

middlewares.forEach(middleware => {
    if (!middleware) {
        return
    }
    app.use(middleware)
})

app.on('error', (err) => {
    log('cyan', err)
})

// koa static server
const server = app.listen(port, () => {
    log('magenta', 'The server is start on port ' + port)
})

// terminal ctrl+c to exit the server
process.on('SIGINT', () => {
    log('yellow', 'Stopping dev server')
    server.close(() => {
        process.exit(0)
    })
})

config.js

// server config
const config = {
    port: 3000, // server port
    db: {
        url: 'mongodb://localhost:27017/blog'
    },
    publicPath: '../static',
    uploadPath: '../uploads',
    secretKey: 'halapro'
}

module.exports = config

token.js

const fs = require('fs')
const path = require('path')
const jwt = require('jsonwebtoken')

module.exports = {
    getSecret (file) {
        return fs.readFileSync(path.join(__dirname, '../config/' + file))
    },
    // 通过私钥生成token
    generateToken (data) {
        // 过期时间
        let date = Math.floor(Date.now() / 1000)
        const cert = this.getSecret('private.pem')
        const token = jwt.sign({data, exp: date + 3600 * 24}, cert, { algorithm: 'RS256' })
        return token
    },
    verifyToken (token) {
        if (token) {
            let res
            const cert = this.getSecret('public.pem')
            try {
                let result = jwt.verify(token, cert, { algorithm: 'RS256' }) || {}
                let { exp = 0 } = result, current = Math.floor(Date.now() / 1000)
                if (current <= exp) {
                    res = result.data || {}
                }
            } catch (err) {
                console.log('verifyToken error:', err)
                throw err
            }
            return res
        }
    },
    isRevoked (ctx, decodedToken, token) {
        let currentTime = Math.floor(Date.now() / 1000)
        let { exp = 0 } = decodedToken, current = Math.floor(Date.now() / 1000)
        if (current <= exp) {
            return 0
        } else {
            return 1
        }
    }
}

errorHandler.js

/**
 * @description 异常处理
 * @author halapro.liu
 * @param {*} ctx
 * @param {*} next
 */
const errorHandler = async (ctx, next) => {
    try {
        await next()
    } catch (err) {
        console.log(`--------------------------------err---------------------------:`, err)
        ctx.status = err.statusCode || err.status || '500'
        ctx.body = {
            code: ctx.status,
            message: err.message
        }
    }
}

module.exports = errorHandler

详见https://github.com/halaproliu/blog

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • # Awesome Python [![Awesome](https://cdn.rawgit.com/sindr...
    emily_007阅读 6,598评论 0 3
  • # Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列...
    小迈克阅读 8,148评论 1 3
  • 在莫高窟一直逛到3点半,才和小伙伴们离开,到我住的驼铃宾馆的酒店,又叫驼铃酒店,点了一份牛肉面片汤,实在是太好吃了...
    蜕变的林林阅读 2,563评论 1 1
  • 这节课,讲毁了! 我是这么感觉的,虽然孩子们那明亮的眼睛、兴奋的表情告诉我,他们是有所得的。 课程本来的本来是这样...
    蝶化文澜阅读 4,549评论 7 30
  • 照例写在2018年末,给自己。 我在2016年开始写年末总结,当初少年不知道愁滋味,为赋新词强说愁,而今却道天凉...
    18岁少年的求索阅读 2,833评论 0 1