Node教程——API接口开发(MangoDB+Express)

git源码

说明:源码已经全部上传到github,仓库地址: https://github.com/BM-laoli/Node-api-Design

一、大纲

  • 大纲:

    关于架构,

    1. 首先我们的有一个app.js这个就是根路由起点,用来最初的打入口

      它的功能有:

      1.1 引入模块创建基础的网站服务器,

      1.2 导入bodyPasser,过滤还有处理我们的post请求

      1.3 导入数据库连接

      1.4 把路由开放出去

    2. 再来一个main.js它在我的route文件夹下,

      2.1 什么需啊哟再这里做二次拦截,再进行分配路由,

      2.2 引入两个逻辑处理模块,当请求发来的时候,如果不是login那么我们就需要验证token,

      2.3 如果访问的是login那么我们需要,发post数据,来处处理验证,然后拿token,

      2.4 如果有token,那么再来访问2.2这里的不是logi的其它路由路径,的校验就通过了,于是乎我们就能分配各种接口了

    3. 详细的讲解辅助,工具代码

      3.1 这里有我们在主线逻辑里需要的一些工具

      3.2 中间件Middleware,里面有两个工具,一个是生成token的一个校验token的

      3.3 在3.2中的功能 需要依赖model下的一个util下的jwt工具生成token生成的依据是两个密钥对

      3.4 我们还有两个工具,content 创建数据库的链接,create初始化数据还有开发数据操作对象

二、展示 接口 API文档

1.1 登录

请求地址 请求方式
/main/login POST
参数名称 是否必选 参数说明
email 邮箱
password 密码
{
	"status": 200,
	"msg": "登陆成功",
	"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiNWU5MTIwMTViOWI0NmYzZmE4Y2MzMjUzIiwiZXhwIjoxNTg2OTUyMzk1LCJpYXQiOjE1ODY5NTA1OTV9.IsprCaQ_gZRh0BzS8SnAd0iJ27BOpOEb-ZGn0bTlwHVPTiYPK50wiEOL_0aAYINfNT_Mfvb726l3CpiHG9lsJ45m4eqhPeJz9TbAeQj8-ST3CAkYLrD0fhgRG9YiQ5kjVpygdR8NZEWEUV7ux-moyYe7wCoVzN9mbvAkFF3IYG0"
}

1.2 拿着token进行测试

请求地址 请求方式
/main/text get
参数名称 是否必选 参数说明
token 需要附上你的token。在请求头中
该接口不需要传递参数
{
	"status": 200,
	"msg": "登陆成功"
}

注意:以上就是Node写接口的最基础的内容。可以在这个内容上扩展更多的接口

二、 app.js模块的详解

app.js

//引入模块,创建简单服务器
const express = require(‘express‘);
//引入路径处理模块
const path = require(‘path‘);
//引入注意使用第三方模块处理post
const bodyPaser = require(‘body-parser‘)

// 引入数据库连接 不需要返回值
require(‘./model/content‘)

//创建服务器
const app = express();

/*//初始化数据库,注意reque的时候 会自动执行引入的js文件
require(‘./model/create‘)
*/

//前往小心这个要放在所有的use前面,解析我们的post请求数据
app.use(bodyPaser.urlencoded({ extended: false }));
//处理静态资源路径
const DataPath = path.join(__dirname, ‘public‘);
//这个我们后面是有用的,用来操作媒体数据,最重要的就是这个路径还有这个静态资源对象
const StaticUtils = express.static(path.join(__dirname, ‘public‘));

//拿到路由操作对象
const main = require(‘./route/mian/main‘);
//开放接口路径
//拦截请求开始匹配路由
app.use(‘/dataPath‘, (req, res) => {
    res.status(200).send(JSON.stringify({ ‘dataPath‘: DataPath }))
})
app.use(StaticUtils);
app.use(‘/main‘, main)

//监听端口
app.listen(3000)
console.log(‘服务器开启‘);

三、 main.js二次路由拦截模块

main.js

const express = require(‘express‘)

//业务逻辑
const guard = require(‘../../Middleware/loginGuard‘)
const loginPash = require(‘../../Middleware/loginPash‘)

//创建路由对象
const admin = express.Router()
    //验证token
admin.use(loginPash)

//登录路由处理
admin.post(‘/login‘, guard)

//首先要验证,然后才是放行到对应的路由接口里面取
admin.get(‘/text‘, require(‘./API/home/index‘))

module.exports = admin;
  • 携带的一个简单的测试模块(后续可以仿照这样的模式,写更多的API接口功能模块)

    home/index.js

module.exports = async(req, res) => {
    res.send({ status: 200, msg: ‘登陆成功‘, });
}

四、 辅助工具(重点!!!)

  • 数据库连接,设计还有初始化创建模块

    model/content.js && model/create.js


const mongoose = require(‘mongoose‘);

mongoose.connect(‘mongodb://localhost/blog‘)
    .then(() => {
        console.log(‘数据库连接成功‘);
    })
    .catch((erro) => {
        console.log(erro);
    })

 const mongoose = require(‘mongoose‘);

 const bcrypt = require(‘bcrypt‘)

 /*使用MongDB数据库,设计数据第一步(代码角度分析)
 1.设定规则,Schema构造器,Schema的构造函数就是规则,注意规则是一系列对象
 2.创建数据
 */

 const userSchema = new mongoose.Schema({
     username: {
         type: String,
         required: true,
         min: 2,
         max: 10
     },
     email: {
         type: String,
         //注意 我们的邮箱凭据是用户登录的令牌,我们需要指定他为唯一的
         unique: true, //这个时候,在插入的时候如果有重复的就给你抱一个错误
     },
     password: {
         type: String,
         required: true,
     },
     role: { //需要说明一下,这个地方角色,我们硬性规定,超级管理员是admin普通用户是normal,为什么不用01?因为这里string了
         type: String,
         required: true
     },
     state: {
         //我们使用O1状态来设计这个数据字段,默认值是0。0是启用状态
         type: Number,
         default: 0
     }
 })

 //使用规则创建集合,
 //一定要注意,我们的User就是代表了我目前最user数据集合,后期的增删改查我们都需要用到这个东西,所有我们暴露出去给路由业务使用
 const User = mongoose.model(‘User‘, userSchema)

 //我们再来复习一下,如何用同步的方式获取异步的api结果?使用async 还有awit就可以

 async function createUser() {
     const salt = await bcrypt.genSalt(10)
     const pass = await bcrypt.hash(‘123456‘, salt)
     const user = await User.create({
         username: ‘lli‘,
         email: ‘[email protected]‘,
         password: pass,
         role: ‘admin‘,
         state: 0,
     })
 }

 //  createUser()

 /* //  初始化用户,注意我们的create返回的是一个promies
   User.create({
     username: ‘bmlaoli‘,
     email: ‘[email protected]‘,

     password: ‘123456‘,

     role: ‘admin‘,
     state: 0,
 })
 .then(() => {
     console.log(‘用户创建成功‘);
 })
 .catch((error) => {
     console.log(‘用户创建失败‘);
 })*/

 //注意啊,es6中如果键值对的名字是一样的就可以省略值。由于我们后期还会做更多的数据集合,于是乎我这里需要暴露一个对象出去
 module.exports = {
     User
 }
  • 另一个重要的工具模块,用来创建token 根据就是文件夹下的两个密钥对文件

    jwt.js



/*
 *描述:以下是jwt工具,生成用于访问验证的token
 */

// 引入模块依赖
const fs = require(‘fs‘);
const path = require(‘path‘);
const jwt = require(‘jsonwebtoken‘);
// 创建 token 类
class Jwt {
    constructor(data) {
            this.data = data;
        }
        //生成token
    generateToken() {
        let data = this.data;
        let created = Math.floor(Date.now() / 1000);
        let cert = fs.readFileSync(path.join(__dirname, ‘../../pem/private_key.pem‘)); //私钥 可以自己生成,注意这里要使用 密钥对,请求百度下载,两对密钥对
        let token = jwt.sign({
            data,
            exp: created + 60 * 30,
        }, cert, { algorithm: ‘RS256‘ });
        return token;
    }

    // 校验token
    verifyToken() {
        let token = this.data;
        let cert = fs.readFileSync(path.join(__dirname, ‘../../pem/public_key.pem‘)); //公钥 可以自己生成
        let res;
        try {
            let result = jwt.verify(token, cert, { algorithms: [‘RS256‘] }) || {};
            let { exp = 0 } = result, current = Math.floor(Date.now() / 1000);
            if (current <= exp) {
                res = result.data || {};
            }
        } catch (e) {
            res = ‘err‘;
        }
        return res;
    }
}

module.exports = Jwt;

  • 接下里是两个具体的token校验功能模块

    我把它们都放到了middleware文件夹下

    loginGuard.js && loginPash.js

const JwtUtil = require(‘../model/util/jwt‘)
const { User } = require(‘../model/create‘)
const bcrypt = require(‘bcrypt‘)

const guard = async(req, res, next) => {
    //注意使用第三方模块处理post
    //进图具体的业务逻辑,解构出来我们需要的东西
    const { email, password, _id } = req.body; //注意啊,由于我们的中间件处理的请求于是乎我们的req身上就有这个处理的所有数据了,这个之前有说过

    console.log(req.body);

    if (email.trim().length == 0 || password.trim().length == 0) {
        res.status(400).send(
                JSON.stringify({ message: ‘邮箱或密码错误‘ })
            ) //注意send自动把状态码设置成了200,所以你需要改一下
        return
    }

    //如果用户存在就先找到这个用户额信息,注意这里的这个异步await
    let user = await User.findOne({ email });
    //这里的user就是指向当前查询出来的数据文档对象

    if (user) {
        //比对操作,第一个参数是一个明文密码,第二个参数我们查询出来的加密密码 ,方法返回一个Boolean值,对比成功就是true,异步api可以直接加await
        const isValid = await bcrypt.compare(password, user.password)
        if (isValid) {
            //用户校验成功,添加tooken
            // 登陆成功,添加token验证
            let _id = user._id.toString();
            // 将用户id传入并生成token
            let jwt = new JwtUtil(_id);
            let token = jwt.generateToken();
            // 将 token 返回给客户端
            res.send({ status: 200, msg: ‘登陆成功‘, token: token });
            //校验成功就
            next()
        } else {
            res.status(400).send(
                JSON.stringify({ message: ‘邮箱或密码错误‘ })
            )
        }

    } else {
        res.status(400).send(
            JSON.stringify({ message: ‘邮箱或密码错误‘ })
        )
    }
}

module.exports = guard

loginPash.js


const JwtUtil = require(‘../model/util/jwt‘)

//验证token
const loginPash = function(req, res, next) {
    // 我这里知识把登陆和注册请求去掉了,其他的多有请求都需要进行token校验
    if (req.url != ‘/login?‘) {
        let token = req.headers.token;
        let jwt = new JwtUtil(token);
        let result = jwt.verifyToken();
        // 如果考验通过就next,否则就返回登陆信息不正确
        if (result == ‘err‘) {
            console.log(result);
            console.log(req.url);
            res.send({ status: 403, msg: ‘登录已过期,请重新登录‘ });
            // res.render(‘login.html‘);
        } else {
            next();
        }
    } else {
        next();
    }
};

module.exports = loginPash;

五、 最后我们梳理一下,这些模块之间的关系

其实这套接口下来,我比较菜鸡,用了两天的工作之余的时间,由于我没怎么接触接口的设计,对于后台的一些设计模式还有理念不是特别懂,走了很多弯路,以上的是我写了三次笔记,长达2000多行子,反复的修改,才成型,希望大佬高抬贵手指点迷津,也希望,这篇入门的文档,能给你带来收获,接下里,我就用这里的模型,开发更多的接口。敬请期待。

  • 各个模块的引用关系,用例图

原文地址:https://www.cnblogs.com/BM-laoli/p/12708342.html

时间: 04-14

Node教程——API接口开发(MangoDB+Express)的相关文章

API接口开发 配置、实现、测试

Yii2 基于RESTful架构的 advanced版API接口开发 配置.实现.测试 环境配置: 开启服务器伪静态 本处以apache为例,查看apache的conf目录下httpd.conf,找到下面的代码 LoadModule rewrite_module modules/mod_rewrite.so 将其前面的#去掉,如果没有找到则添加进去. 找到一下代码 <Directory "C:/phpStudy/Apache/cgi-bin"> AllowOverride

(微信API接口开发) 使用HttpWebRequest进行请求时发生错误:基础连接已关闭,发送时发生错误处理

最近调试原来的微信模拟登陆时发生了"基础连接已关闭,发送时发生错误"的错误提示,原来都是好好的,只是很久没用了. 出错代码如下: ? 1 2 3 4 5 6 7 HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN");///cgi-bin/loginpage?

浅谈使用 PHP 进行手机 APP 开发(API 接口开发)

做过 API 的人应该了解,其实开发 API 比开发 WEB 更简洁,但可能逻辑更复杂,因为 API 其实就是数据输出,不用呈现页面,所以也就不存在 MVC(API 只有 M 和 C),那么我们来探讨下,如何使用php进行手机API接口开发 一.先简单回答两个问题: 1.PHP 可以开发客户端? 答:可以,因为PHP是脚本语言,是负责完成 B/S架构 或 C/S架构 的S部分,即:主要用于服务端的开发.但是,PHP可不仅仅只能在互联网站上发展,一个PHP for Android(PFA)站点表示

浅谈 PHP 与手机 APP 开发(API 接口开发)

本文内容转载自:http://www.thinkphp.cn/topic/5023.html 这个帖子写给不太了解PHP与API开发的人 一.先简单回答两个问题: 1.PHP 可以开发客户端?答:不可以,因为PHP是脚本语言,是负责完成 B/S架构 或 C/S架构 的S部分,即:服务端的开发.(别去纠结 GTK.WinBinder) 2.为什么选择 PHP 作为开发服务端的首选?答:跨平台(可以运行在UNIX.LINUX.WINDOWS.Mac OS下).低消耗(PHP消耗相当少的系统资源).运

Restful风格API接口开发springMVC篇

Restful风格的API是一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件.它主要用于客户端和服务器交互类的软件.基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制. 在Restful风格中,用户请求的url使用同一个url而用请求方式:get,post,delete,put...等方式对请求的处理方法进行区分,这样可以在前后台分离式的开发中使得前端开发人员不会对请求的资源地址产生混淆和大量的检查方法名的麻烦,形成一个统一的接口. 在Restful风格中,现

聊聊 PHP 与手机 APP 开发(API 接口开发)

对于新手开发api接口的一探讨 一.先简单回答两个问题: 1.PHP 可以开发客户端?答:不可以,因为PHP是脚本语言,是负责完成 B/S架构 或 C/S架构 的S部分,即:服务端的开发.(别去纠结 GTK.WinBinder) 2.为什么选择 PHP 作为开发服务端的首选?答:跨平台(可以运行在UNIX.LINUX.WINDOWS.Mac OS下).低消耗(PHP消耗相当少的系统资源).运行效率高(相对而言).MySQL的完美搭档,本身是免费开源的,...... 二.如何使用 PHP 开发 A

API接口开发简述

作为最流行的服务端语言PHP(PHP: Hypertext Preprocessor),在开发API方面,是很简单且极具优势的.API(Application Programming Interface,应用程序接口)架构,已经成为目前互联网产品开发中常见的软件架构模式,并且诞生很多专门API服务的公司,如:聚合数据(https://www.juhe.cn/).百度APIStore(http://apistore.baidu.com/) 先了解下 API :1.API 比开发 WEB 更简洁,但

浅谈PHP与手机APP开发(API接口开发)

1 了解PHP与API开发 2 一.先简单回答两个问题: 3 4 1.PHP 可以开发客户端? 5 答:不可以,因为PHP是脚本语言,是负责完成 B/S架构 或 C/S架构 的S部分,即:服务端的开发.(别去纠结 GTK.WinBinder) 6 7 2.为什么选择 PHP 作为开发服务端的首选? 8 答:跨平台(可以运行在UNIX.LINUX.WINDOWS.Mac OS下).低消耗(PHP消耗相当少的系统资源).运行效率高(相对而言).MySQL的完美搭档,本身是免费开源的,...... 9

转 浅谈 PHP 与手机 APP 开发(API 接口开发)

这个帖子写给不太了解PHP与API开发的人 一.先简单回答两个问题: 1.PHP 可以开发客户端?答:不可以,因为PHP是脚本语言,是负责完成 B/S架构 或 C/S架构 的S部分,即:服务端的开发.(别去纠结 GTK.WinBinder) 2.为什么选择 PHP 作为开发服务端的首选?答:跨平台(可以运行在UNIX.LINUX.WINDOWS.Mac OS下).低消耗(PHP消耗相当少的系统资源).运行效率高(相对而言).MySQL的完美搭档,本身是免费开源的,...... 二.如何使用 PH

API接口开发简述示例

作为最流行的服务端语言PHP(PHP: Hypertext Preprocessor),在开发API方面,是很简单且极具优势的.API(Application Programming Interface,应用程序接口)架构,已经成为目前互联网产品开发中常见的软件架构模式,并且诞生很多专门API服务的公司,如:聚合数据(https://www.juhe.cn/).百度APIStore(http://apistore.baidu.com/) 先了解下 API :1.API 比开发 WEB 更简洁,但