本文為 [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 有自動幫你寫好,所以用 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
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 喔。