後端好朋友 Express middleware


Posted by Christy on 2022-01-11

本文為 [BE201] 後端 Express 學習筆記,主要紀錄學習過程,裡面包含 express Middleware 介紹

零、內容摘要

1. 可以把 middleware 看成是中間商,就是幫忙處理行為的函式,並用 next() 交接給下一個 middleware。舉例來說,我要到某地旅遊,我把旅遊行程、交通、住宿分別外包給三個不同的中間商,而我從交通 → 行程 → 住宿都有人幫我處理好了,我只負責旅行,這中間的箭頭就是 next()

2. 常用的 middleware

a. Request body 有話要說,解析 Request 必備:body-parser

b. Session middleware,處理登入登出機制

c. connect-flash,處理錯誤訊息;提到把東西放在 locals 讓其他人也可以用

3. 基本用法:

a. 找到官方說明文件,然後下載

b. 在 index.js 引入使用

c. 找範例把程式碼拿進來

d. 在 index.js 新增路由,哪個網址可以讀哪些內容等等

e. controller 新增拿到資料以後的行動

f. views 處理畫面

一、什麼是 middleware?

是一個中間件,簡單來說就是幫忙處理行為的函式,利用 next() 把行動交給下一個函式:

fn A → next() → fn B …

  • 在 express 預設沒有能夠解析 req body 的內容如 POST、DELETE 這些 methods,也沒有 sessioin 管理機制,這些都要靠 middleware 完成

  • 在 express 裡有內建的是「可以拿到網址列的 query string」

二、解析 Request 必備:body-parser

必用,不然拿不到 req body 裡面的資料

body-parser

註:在新版的 body-parser 有自動幫你寫好,所以用 express.json() 其實就是在用 body-parser,因此新版來說,就用 express.json() 就好。可以參考 W17_直播檢討 Q7。

a. $ npm install body-parser

b. "Express/Connect top-level generic" 找範例

c. contetn type 兩個都拿進來,都會用到

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())

d. 在 index.js 新增一個路由處理

app.post('/todos', todoController.newTodo)

e. views 的畫面 addTodo.ejs

<h1>Add Todo</h1>
<form method="POST" action="/todos">
  Content: <input type="text" name="content" />
  <input type="submit" />
</form>

f. 在 controller 新增一個 newTodo method

newTodo: (req, res) => {
  // 這裡的 req.body.content 就是上面 views input 裡面的 name
  const content = req.body.content
  res.end(content)
}

三、負責管理 Session 的 Session middleware

express-session

a. $ npm install express-session

b. 在 index.js 引入 const session = require('express-session')

c. 使用 session

// index.js
app.use(session({
  secret: 'keyboard cat',
  resave: false,
  saveUninitialized: true,
  // 老師的範例沒有下面這一行,所以我無法登入
  // cookie: { secure: true }
}))

d. .get() 讀取畫面 & .post() 寫入登入行為

// index.js

app.get('/login', (req, res) => {
  res.render('login')
})

app.post('/login', (req, res) => {
  if (req.body.password === 'abc') {
    req.session.isLogin = true
    res.redirect('/')
  } else {
    res.redirect('/login')
  }
})

app.get('/logout', (req, res) => {
  req.session.isLogin = false
  res.redirect('/')
})

e. 在 controller 的 addTodo 新增登入

// controller > todo.js

addTodo: (req, res) => {
  res.render('addTodo', {
    isLogin: req.session.isLogin
  })
},

f. views > addTodo.ejs

// addTodo.ejs

<h1>Add Todo</h1>

<% if(isLogin) { %>
  Hello, user! <a href="/logout">logout</a>
<% } else { %>
  Wanna login?
<% } %>

<form method="POST" action="/todos">
  Content: <input type="text" name="content" />
  <input type="submit" />
</form>

g. login.ejs

// login.ejs

<h1>Login</h1>
<form method="POST" action="/login">
  password: <input type="password" name="password" />
  <input type="submit" />
</form>

四、connect-flash

1. 介紹 flash 這個 lib 怎麼用

2. 把東西放在 locals 讓其他人也可以用views 可以用任何來自 local 的東西,記得要用 res.locals,不是 req 喔。

a. connect-flash,安裝 $ npm install connect-flash

b. 在 index.js 引入 const flash = require('connect-flash')

c. 在 index.js 使用 app.use(flash())

d. 在登入裡面使用 flash: req.flash('errorMessage', 'invalid password') 兩個參數,前面錯誤訊息,後面訊息內容

app.get('/login', (req, res) => {
  res.render('login', {
    errorMessage: req.flash('errorMessage')
  })
})

app.post('/login', (req, res) => {
  if (req.body.password === 'abc') {
    req.session.isLogin = true
    res.redirect('/')
  } else {
    req.flash('errorMessage', 'invalid password')
    res.redirect('/login')
  }
})

e. 寫一個模板來給大家使用

app.use((req, res, next) => {
  res.locals.isLogin = req.session.isLogin
  res.locals.errorMessage = req.flash('errorMessage')
  next()
})

上面的 errorMessage: req.flash('errorMessage') 就不用了

views 可以用任何來自 local 的東西,記得要用 res.locals,不是 req 喔。










Related Posts

[ 紀錄 ] 實戰練習 - Todo List ( 以 JS 實作前端 + PHP 後端 )

[ 紀錄 ] 實戰練習 - Todo List ( 以 JS 實作前端 + PHP 後端 )

程式解題新手入門注意事項

程式解題新手入門注意事項

v-model 與.修飾符

v-model 與.修飾符


Comments