RESTful API by node jsexpress 紀錄

RESTful API by node jsexpress 紀錄

計畫要做甚麼

簡單需要登入控制的SHOP

架構圖如下:

Imgur

準備工具

PostMan

資料庫

我用 MongoDB Atlas
有免費版本流量夠測試使用

/products

  • /products:GET: 產品列表
  • /products:POST: 產品新增
  • /products/{id}:GET: 單一產品資訊
  • /products/{id}:PATCH: 單一產品修改
  • /products/{id}:DELETE: 單一產品刪除

/orders

  • /orders:GET: 訂單列表
  • /orders:POST: 訂單新增
  • /orders/{id}:GET: 單一訂單資訊
  • /orders/{id}:DELETE: 單一訂單取消

上圖紅色部分是需要使用者登入才能操作的請求。

目錄結構

Imgur

部分程式碼講解

在製作過程會有一些遇到的問題在下面我都整理了起來

完整檔案在 GITHUB

Server.js

一些基本nodejs server設定

1
2
3
4
5
6
7
8
const http = require('http');
const app = require('./app');

const port = process.env.port || 3000;

const server = http.createServer(app);
server.listen(port);

App.js 部分

錯誤控制

基本的流程或是路由錯誤控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// errro control
app.use((req, res, next)=>{
const error = new Error('Not found');
error.status=404;
next(error);
});

app.use((error,req,res,next)=>{
res.status(error.status || 500);
res.json({
error:{
message: error.message
}
});
});

使用的套件或是middleware

1
2
3
4
5
const express = require('express');
const app = express();
const morgan = require('morgan');
const bodyParser = require('body-parser')
const mongoose = require('mongoose');

nodemon & morgan

好用的自動restart與debug模組
packeage.json中加入 "start": "nodemon server.js"

morgan使用

app.js.中放入var morgan = require('morgan');app.use(morgan('dev'))

Router 部分

我是想有 orders products user5這三個部分﹐分別處理不同功能

orders products 需要跟controller 一起看

多了一個controller讓可讀性與維護性更高

基本上這部分都是一些資料庫控操作與權限控制

order部分

在mongoose models 地方有用了 ref這參數

product: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: true },
product 這一欄參數是參考 Product這個集合的

orders_get_all 就可以列出product這個集合的資料
在mongoose使用這個.populate("product", "name")函數就可以控制

api token 實作方法

這裡是使用 JWT 這個套件來實作

user/login的地方

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
const token =jwt.sign({
email:user[0].email,
userId:user[0]._id
},
process.env.JWT_key,
{
expiresIn: "1h"
}
);
return res.status(200).json({
message:'Auth successful',
token:token
});
}

讓成功登入者取得TOKEN

在使用此TOKEN 來進行上述紅色需要驗證的部分

在所有需要驗證的URL錢加上middleware 來成功實作出API+驗證機制

checkAuth使自己製作的middleware 在 middleware資料夾當中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const jwt = require('jsonwebtoken')

module.exports = (req, res, next) => {
try {
const decoded = jwt.verify(req.headers.authorization.split(" ")[1], process.env.JWT_key)
req.userData = decoded;
next();
} catch (error) {
return res.status(401).json({
message: 'Auth failed'
})
}


}

使用方式E.G. :router.post("/", checkAuth, upload.single('productImage'), ProductsController.products_create_product);

根據上面方式 使用postman 來測試

Body

Imgur

HEADER

Imgur

user部分

在signup 有用bcrypt 進行加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bcrypt.hash(req.body.password, 10,(err,hash) => {
if(err){
return res.status(500).json({
error:err
})
}else{
const addUser = new User({
_id: new mongoose.Types.ObjectId(),
email: req.body.email,
password: hash
});
addUser.save()
.then(result => {
res.status(201).json({
message: 'User created'
})
})
.catch(err => {
console.log(err);
res.status(500).json({
error:err
})
})
}
})