express-generator用户接口响应

马和硕
2023-12-01

express-generator

本文主要分享 通过使用express-generator脚手架 来配置用户接口的响应

app.js:

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var logger = require('morgan');
let multer  = require('multer');

// var indexRouter = require('./routes/index');
// var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views')); //指明项目里面模板引擎的位置放在views目录
app.set('view engine', 'ejs');  //当前项目可以通过res.render来去渲染一个ejs模板

//配置控制台打印日志的中间件
app.use(logger('dev'));

//中间件的安装 body-parser  req.body获取到非地址栏里面的数据
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

//multer中间件的配置(1.可以获取上传图片req.files  2.req.body可以获取非地址栏的数据)
//通过multer实现上传图片的不同分发目录
// let upload = multer({dest:path.join(__dirname,"public","upload")})

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    //如果接口中存在reg或者user,那么我就上传到/upload/user文件夹中
    if(req.url.indexOf("user")!==-1 || req.url.indexOf("reg")!==-1){
      cb(null, path.join(__dirname,"public","upload","user"))
    }else if(req.url.indexOf("banner") !== -1){
      cb(null, path.join(__dirname,"public","upload","banner"))
    }else{
      cb(null, path.join(__dirname,"public","upload","product"))
    }
  }
})
let upload = multer({ storage: storage })
app.use(upload.any())




//多目录的静态资源托管
app.use(express.static(path.join(__dirname, 'public',"template")));
app.use("/admin",express.static(path.join(__dirname, 'public',"admin")));
app.use(express.static(path.join(__dirname,"public")))


// 用户的接口的响应
app.all("/api/*",require("./routes/api/params")) //处理api下发出的所有的接口的公共参数
app.use('/api/reg', require('./routes/api/reg'));
app.use('/api/login', require('./routes/api/login'));
app.use('/api/goods', require('./routes/api/goods'));

app.use('/api/user', require('./routes/api/user'));
//app.use('/api/logout', require('./routes/api/logout')); //session  delete req.session[key]





// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);

  //如果上面的接口不存在或者静态资源不存在,就会走下面的错误处理.....
  if(req.url.includes("/api")){ //说明是用户接口不存在
    res.send({err:1,msg:"用户端接口不存在..."})
  }else if(req.url.includes("/admin")){ //说明是管理端接口不存在
    res.render('error')
  }else{ //静态资源不存在
    res.sendFile(path.join(__dirname,"public","template","404.html"))
  }
});

module.exports = app;

在routes 目录下创建 api文件夹 ,分别新建params.jsreg.jslogin.jsgoods.jsuser.js用来配置接口的响应。

params.js:

let jwt = require("../../utils/jwt")
module.exports = (req,res,next)=>{
    //处理公共参数(放在地址栏里面进行传递)
    req.query._page = req.query._page ? req.query._page - 1 : require("../../config/global")._page
    req.query._limit = req.query._limit ? req.query._limit - 0 : require("../../config/global")._limit
    req.query.q = req.query.q ? req.query.q : require("../../config/global").q
    req.query._sort = req.query._sort ? req.query._sort : require("../../config/global")._sort

    //处理公共的授权业务
    //如果前端接口包含 login/reg/logout,那么就可以不需要携带token   /api/login  
    if( /login|logout|reg/.test(req.url) ){
        //next必须要放行
        next()
    }else{ //除此之外的接口必须要携带token才能进行数据获取   /api/goods/home
        //获取前端传递来的token
        let token = req.headers.token || req.body.token || req.query.token
        //校验前端传递来的token
        jwt.verify(token).then(decode=>{ 
            req.query.decode = decode //如果后续的接口需要数据的话,方便获取到  {username,_id} 
            next() 
        }).catch(message=>res.send({err:1,msg:"token验证失效或者未登录..."+message}))
    }
}

reg.js:

var express = require('express');
var router = express.Router();
var fs = require("fs")
var pathLib = require("path")
var mongodb = require("../../utils/mongodb")
var bcrypt = require("../../utils/bcrypt")
/* 
    reg代表注册逻辑   往数据库里面进行数据的插入  
    restful接口规范:
        插入数据   post方式
        删除数据   delete方式
        修改数据   patch/put方式   put是覆盖性修改  patch代表局部修改
        查询数据   get方式
*/
// /api/reg ===> post请求 (username,password)
router.post('/', function(req, res, next) {
    //1.获取前端传递来的username/password/nickname/icon等   
    let {username,password,nickname} = req.body;
    //2.对于前端必传参数username、password的验证
    if(!username || !password){
        res.send({err:1,msg:"用户名或者密码是必传参数!"})
        return
    }
    //3.整理其他的需要入库的参数(nickname/icon)
    nickname = nickname || "系统生成的默认昵称"
    let follow = 0 //关注数
    let fans = 0 //粉丝数
    let time = Date.now() //服务器生成注册时间
    let icon = "/upload/default.jpg" //用户的默认头像

    //判断用户是否上传了头像 multer中间件如果有用,req.files不在是undefined
    if(req.files && req.files.length>0){ //代表用户上传头像了
        //给上传好的图片添加后缀名
        //文件改名
        fs.renameSync(req.files[0].path,req.files[0].path + pathLib.parse(req.files[0].originalname).ext)
        //覆盖掉默认头像
        icon = "/upload/user/"+req.files[0].filename + pathLib.parse(req.files[0].originalname).ext
    }
    //4.校验用户是否在数据库存在(username的唯一性)
    mongodb.open({
        collectionName:"user"
    }).then(({collection,client})=>{
        //根据注册的用户名从库里面执行查询操作
        collection.find({username}).toArray((err,result)=>{
            if(err){
                res.send({err:1,msg:"集合操作失败..."})
                client.close()
            }else{
                if(result.length ===0 ){// 4-1 如果不存在的话,直接入库操作
                    //说明需要注册的用户在数据库里面不存在,进行入库操作
                    //密码需要进行加密
                    password = bcrypt.hashSync(password)
                    //console.log(username,password,nickname,fans,follow,time,icon)
                    //入库
                    collection.insertOne({
                        username,password,nickname,fans,follow,time,icon
                    },(err,result)=>{
                        if(!err){
                            //插入后的信息中不需要给用户返回用户名与密码
                            delete result.ops[0].username
                            delete result.ops[0].password
                            res.send({
                                err:0,
                                msg:"恭喜您,注册成功!",
                                data:result.ops[0]
                            })
                        }else{
                            res.send({err:1,msg:"入库失败..."})
                        }
                        client.close()
                    })
                }else{ // 4-2 用户存在提示用户已存在信息   /upload/user/XXXXX.png
                    if(icon.indexOf("default")===-1){ //用户上传的头像路径不包含default
                        // fs.unlinkSync("./public"+icon)
                        fs.unlinkSync(pathLib.join(__dirname,"../../public",icon))
                    }
                    res.send({err:1,msg:"此用户已经存在,注册失败!"})
                    client.close()
                }
            }
        })
    }).catch(err=>{
        console.log({err:1,msg:"数据库连接失败...."})
    })
});

module.exports = router;

login.js:

var express = require('express');
var router = express.Router();
var mongodb = require("../../utils/mongodb")
var bcrypt = require("../../utils/bcrypt")
var jwt = require("../../utils/jwt")
/* GET home page. */
router.post('/', function(req, res, next) {
    //1.获取前端传递来的用户名与密码
    let {username,password} = req.body
    //2.验证必传参数
    if(!username || !password){
        res.send({
            err:1,
            msg:"用户名与密码为必传参数..."
        })
        return
    }
    //3.需要查询数据库
    mongodb.open({
        collectionName:"user"
    }).then(({collection,client})=>{
        //进行查询操作
        collection.find({username}).toArray((err,result)=>{
            if(err){
                res.send({err:1,msg:"集合操作失败..."})
                client.close()
            }else{
                if(result.length>0){
                    //3-1 代表用户在数据库是存在的 ==> 登录的密码与数据库里面的密码进行校验 ==> 登录成功(token)
                    let flag = bcrypt.compareSync(password,result[0].password)
                    if(flag){ //说明密码输入正确
                        //生成token令牌
                        let token = jwt.sign({username,_id:result[0]._id})
                        delete result[0].username
                        delete result[0].password
                        res.send({
                            err:0,
                            msg:"恭喜您,登录成功!",
                            token,
                            data:result[0]  
                        })
                    }else{
                        res.send({err:1,msg:"用户名或者密码输入有误..."})
                    }
                    client.close()
                }else{ //3-2 用户在数据库里面不存在
                    res.send({err:1,msg:"此用户不存在,请注册!"})
                    client.close()
                }
            }
        })
    }).catch(err=>{
        res.send({err:1,msg:"数据库连接失败..."})
    })
});

module.exports = router;

goods.js:

var express = require('express');
var router = express.Router();
var mongodb = require("../../utils/mongodb")

//列表查询商品   /api/goods/home就会进来
router.get("/:goodsName",(req,res,next)=>{
    //判断是否有_id参数
    if(req.query._id){
        res.redirect(`/api/goods/${req.params.goodsName}/${req.query._id}`)
        return;
    }
    // console.log("goods列表进入了...")
    let collectionName = req.params.goodsName;
    let {_page,_limit,_sort,q} = req.query
    mongodb.findList({
        collectionName,
        _page,_limit,_sort,q
    }).then(result=>{
        res.send(result)
    }).catch(err=>res.send(err))
})

//详情    /api/goods/home/224242342
router.get("/:goodsName/:_id",(req,res,next)=>{
    let collectionName = req.params.goodsName;
    let _id = req.params._id;
    mongodb.findDetail({collectionName,_id}).then(result=>{
        res.send(result)
    }).catch(err=>res.send(err))
})




module.exports = router;

user.js:

var express = require('express');
var router = express.Router();

var jwt = require("../../utils/jwt")
var bcrypt = require("../../utils/bcrypt")
var mongodb = require("../../utils/mongodb")
/* GET home page. */   // /api/user个人中心
router.get('/', function(req, res, next) {
    //连接数据库
    mongodb.open({
       collectionName:"user" 
    }).then(({collection,client,ObjectId})=>{
        //查询数据
        collection.find({
            username:req.query.decode.username,  //因为app.all("/api/*") ===> 经过token认证后可以获取到username和_id
            _id:ObjectId(req.query.decode._id)
        }).toArray((err,result)=>{
            if(err){
                res.send({err:1,msg:"集合操作失败..."})
            }else{
                //判断用户是否存在
                if(result.length>0){
                    //自动登录成功 需要返回数据给前端
                    delete result[0].username
                    delete result[0].password
                    res.send({
                        err:0,
                        msg:"自动登录成功...",
                        data:result[0]
                    })
                }else{
                    res.send({err:1,msg:"自动登录失败..."})
                }
            }
            client.close()
        })
    }).catch(err=>res.send({err:1,msg:"数据库连接失败..."}))
});

module.exports = router;

utils目录下 bcrypt.js(密码加密)jwt.js(token生成与校验)mongodb.js(mongodb链接库及查询)

bcrypt.js:

//可以用来对前端传递来的密码进行加密 
let bcrypt = require("bcrypt")

module.exports = {
    //加密  const hash = bcrypt.hashSync(用户未加密的密码, salt);
    hashSync:password=>{
        return bcrypt.hashSync(password,10)
    },
    //解密校验 bcrypt.compareSync(用户未加密的密码, 用户加密之后的hash密码);
    compareSync:(password,hash)=>bcrypt.compareSync(password,hash)
}

jwt.js:

let jwt = require("jsonwebtoken")

module.exports = {
    //生成签名
    sign:({username,_id})=>{
       return jwt.sign({username,_id},"MD5",{expiresIn:60*60*24})
    },
    //校验签名
    verify:token=>{
        return new Promise((resolve,reject)=>{
            jwt.verify(token,"MD5",(err,decode)=>{
                if(!err){
                    resolve(decode)  //decode={username,_id}
                }else{
                    reject(err.message)
                }
            })
        })
    }
}

mongodb.js:

let mongodb = require("mongodb")
let mongodCt = mongodb.MongoClient
let ObjectId =  mongodb.ObjectId //把字符串转成ObjectId的对象类型
//链接库
/*
    dbName:数据库名称 默认值就是student
    collectionName:集合名字
    url:链接的url地址
*/
let open = ({dbName='newsapp',collectionName,url="mongodb://127.0.0.1:27017"})=>{
    return new Promise((resolve,reject)=>{
        mongodCt.connect(url,{useUnifiedTopology: true},(err,client)=>{
            if(err){
                reject(err)
            }else{
                let db = client.db(dbName)
                let collection = db.collection(collectionName)
                resolve({collection,client,ObjectId})
            }
        })
    })
}

//查询库集合列表数据
let findList = ({
    collectionName,//集合名字
    dbName='newsapp',//默认指明的数据库的名字
    _page,_limit,_sort,q
})=>{

    //生成检索条件
    let rule = q ? {title:new RegExp(q,'g')} : {}   //张三  张三丰   
    // let rule = q ? {username:eval('/'+q+"/")} : {}

    return new Promise((resolve,reject)=>{
        //链接数据库
        open({dbName,collectionName})
            .then(({collection,client})=>{
                //查询列表
                collection.find(rule,{
                    skip:_page*_limit,//跳过多少条数据
                    limit:_limit,//限定每一页的数量
                    sort:{[_sort]:1} //排序字段_sort  当一个变量作为key使用的时候,需要采用[]的语法
                }).toArray((err,result)=>{
                    if(!err && result.length>0){
                        resolve({err:0,data:result})
                    }else{
                        resolve({err:1,msg:"查无数据..."})
                    }
                    //关闭资源
                    client.close()
                })
            })
            .catch(err=>{ //链接数据库失败
                reject({err:1,msg:"数据库链接失败...."})
            })
    })
}


//根据动态id获取详情数据
let findDetail = ({
    dbName="newsapp",//默认查询的数据库名字
    collectionName,//集合名字
    _id=null  //外面传入的_id 
})=>{
    return new Promise((resolve,reject)=>{
        //链库操作
        open({dbName,collectionName})
            .then(({collection,client})=>{
                //查询
                if(_id.length === 24){
                    collection.find({_id:ObjectId(_id)}).toArray((err,data)=>{   
                        //返回结果 
                        if(!err && data.length>0){
                            resolve({err:0,data:data[0]}) //因为result是一个数组,里面仅仅包含一条数据
                        }else{
                            resolve({err:1,msg:"查询不到数据...."})
                        }
                    })
                }else{
                    reject({err:1,msg:"id长度有误..."})
                }
            })
            .catch(err=>reject({err:1,msg:"链接数据库失败...."}))
    })
}





exports.open = open;  //{open:函数}
exports.findList = findList;  
exports.findDetail = findDetail;  
 类似资料: