1. 程式人生 > >Node教程——API介面開發(MangoDB+Express)

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多行子,反覆的修改,才成型,希望大佬高抬貴手指點迷津,也希望,這篇入門的文件,能給你帶來收穫,接下里,我就用這裡的模型,開發更多的介面。敬請期待。

  • 各個模組的引用關係,用例圖

相關推薦

Node教程——API介面開發MangoDB+Express

git原始碼 說明:原始碼已經全部上傳到github,倉庫地址: https://github.com/BM-laoli/Node-api-Design 模組依賴關係圖 一、大綱 大綱: 關於架構, 首先我們的有一個app.js這個就是根路由起點,用來最初的打入口 它的功能有: 1.1 引入模組

Node教程——API介面開發(Node版的CRUD通用介面的搭建MangoDB+Express_Version2

# 1. 概述 > 時間跨度有點大,之前就跟大家嘮嗑過一些知識點,也開啟了一個Node書寫一個後臺api專案的開始,出於各種原因,遲遲沒有更新博文。現在我把這個坑填上,如果你還有閱讀過我之前的文章,我建議你先閱讀一下 *博文地址https://www.cnblogs.com/BM-laoli/p/12708

快遞鳥查詢Api介面使用PHP版

前提 專案開發中,有些需求難免會用到關於快遞的一些Api介面;本篇主要介紹的是快遞的查詢Api及與其他各家的不同之處; 常用的提供快遞Api介面的有: 快遞鳥 快遞100 愛查快遞 等等

微信JS-SDK 微信分享介面開發介紹版

本文主要是分享自己的開發過程,希望能給部分存在同樣問題的朋友一點點幫助;最近專案中的網頁通過微信分享朋友或朋友圈等功能出現了無法顯示分享圖片等資訊,後經過排查發現是微信版本升級導致,採用js-sdk完成分享介面,為了快速實現該功能效果,於是我打算通過前臺js進行實現來看看分享

一個簡單python介面開發flask_restful案例

執行環境:python3 post引數:user,pwd 介面功能:將引數轉換成字串相加並返回json from flask import Flask, g from flask_restful import reqparse, Api, Resource from f

2017高德地圖API WEB開發key申請,地圖搭建簡約教程

height 圖層 類型 開發文檔 doctype content 如何 加載 innerhtml 前端時間因為公司需要研究 了一下百度的教程 然後寫個簡約的筆記記錄一下自己學習的收獲,只為了滿足自己暫時的寫作熱情 高德地圖WEB開發(key申請、api)簡

基於django的rest api快速開發只提供一個介面服務

需求:目前我們有一個後臺的python指令碼和前臺的頁面,我們需要提供一個類似tomcat的服務,來使前臺的一個請求,通過我們搭建的服務去呼叫python模型,並最終將處理的結果返回給前臺。一:搭建django rest api 環境首先我們需要有python環境,這是基礎,

Restful風格API介面開發springMVC篇put delete請求如何設定

  Restful風格API介面開發springMVC篇 Restful風格的API是一種軟體架構風格,設計風格而不是標準,只是提供了一組設計原則和約束條件。它主要用於客戶端和伺服器互動類的軟體。基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現快取等機制。

微信公眾平臺API介面開發教程

簡介 微信公眾平臺訊息介面為開發者提供了一種新的訊息處理方式。微信公眾平臺訊息介面為開發者提供與使用者進行訊息互動的能力。對於成功接入訊息介面的微信公眾賬號,當用戶發訊息給公眾號,微信公眾平臺伺服器會使用http請求對接入的網址進行訊息推送,第三方伺服器可通過響應包回覆特

微信公眾平臺訊息介面開發24圖片識別之人臉識別API

一、微信圖片獲取 首先要獲得使用者發過來的圖片,微信公眾平臺支援接收圖片,一條圖片訊息的格式如下: <xml> <ToUserName><![CDATA[gh_13d1a3a7x46a]]></ToUserName>

微商城---傻瓜式教你微信支付收貨地址介面開發PHP

微信中比較好用的介面功能裡,微信收貨地址介面應該算一個,它本身提供了地址的新增刪除使用,可以使微商城省去收貨地址開發的步驟。微支付這個步驟並不難,本身有提供demo給你,稍微改改就能用,看一下概念也清晰了。收貨地址卻沒有。 此文章是以PHP來實現。 在做之前先確定自己有微信公眾平臺的賬號,並

RESUTFUL風格 API介面開發spring MVC篇

Restful風格API介面開發springMVC篇 Restful風格的API是一種軟體架構風格,設計風格而不是標準,只是提供了一組設計原則和約束條件。它主要用於客戶端和伺服器互動類的軟體。基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現快取等機制。 在Restful

阿里App支付服務端介面開發含後臺非同步回撥,退款

1.引入相關包檔案 maven匯入方式: <dependency> <groupId>com.alipay</groupId> <artifactId>sdk-java</artifactId> <version>

Java後臺框架篇--Spring與Restful風格API介面開發

Restful風格的API是一種軟體架構風格,設計風格而不是標準,只是提供了一組設計原則和約束條件。它主要用於客戶端和伺服器互動類的軟體。基於這個風格設計的軟體可以更簡潔,更有層次,更易於實現快取等機制。 在Restful風格中,使用者請求的url使用同一個url而用請求方式:get,post,

Qt介面開發各種控制元件以及圖表

4.六宮格介面 5.漂亮通用介面 6.淨化裝置管理 7.樹形介面通用圖 8.視窗主框架 9.tcp檔案傳輸 10.綜合元件的介面 11.Qt動態圓形進度條

OpenStack-Restful API介面測試

       在上一篇文章使用Postman簡單測試發現,Restful API客戶端能夠呼叫keytone、nova、glance服務。本文將以建立虛擬機器為例,講述使用Restful API客戶端完成OpenStack各元件複雜的操作。 1.準備工作        

Java【Java開發整合 Swagger UI生成可檢視的API文件詳細圖解

目前幾乎所有的開放平臺都是把API以文件的形式放在網站上,如下: 不知道有沒有開發人員和我一樣,有時對一些API說明的理解比較模糊,總想著能直接驗證一下自己的理解就好了,而不是需要去專案

Laravel 之道特別篇 3: 模型式 Web API 介面開發流程

轉載https://laravel-china.org/articles/20183 導語 這篇文章是我使用 Laravel 開發 Web Api 總結的自己一套開發流程。 記錄在此,方便回顧。 同時,將自己的經驗分享給大家。 這套流程,可能稍微複雜,對軟體設計方面支援還有待

API介面開發 配置、實現、測試

原文地址為: API介面開發 配置、實現、測試 Yii2 基於RESTful架構的 advanced版API介面開發 配置、實現、測試 環境配置: 開啟伺服器偽靜態 本處以apache為例,檢視apache的conf目錄下httpd.conf,找到下面的程式碼

elasticsearch介面開發

此文在上一篇文章的基礎上稍做了些許修改,主要在springboot整合ES後的包路徑上,如下是新的目錄結構 下面貼出程式碼 MyConfig.java package com.ylht.config; import org.elasticsearch.client.transport.Tra