Express 的本體。
什麼是 Middleware
先來看一張圖:
簡單來說,Middleware 就是收到 request 後要做什麼處理的 function。
所以你仔細看就會發現 Express 就是各種 Middleware 來組成的:
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 26 27 28 29 30 31 32
|
app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true, })) app.use(flash());
app.use((req, res, next) => { res.locals.username = req.session.username; res.locals.errorMessage = req.flash('errorMessage'); next(); })
const toPreviousPage = (req, res) => { return res.redirect('back'); }
app.get('/login', usersController.login); app.post('/login', usersController.handleLogin, toPreviousPage); app.get('/logout', usersController.logout); app.get('/register', usersController.register); app.post('/register', usersController.handleRegister, toPreviousPage);
|
只要是 Middleware 都會有三個參數:req
、res
和 next
1 2 3 4 5
| function middleware (req, res, next) { next() }
|
實際範例
先來介紹 app.use
,可以想成是「全域的 Middleware」,它會影響到所有路由:
1 2 3 4 5 6
| app.use((req, res, next) => { console.log('now: ', new Date()); next(); }); app.get('/todos', todoController.getAll) app.get('/todos/:id', todoController.get)
|
所以只要不管我到 /todos
或 /todos/:id
,console 裡都會顯示目前時間,因為它的順序是這樣的:
顯示時間的 Middleware > 顯示 todo 的 Middleware(todoContoller)
但有些時候我們可能只想把 Middleware 綁在特定的路由上,這時候就可以這樣寫:
1 2 3 4 5 6 7 8
| function localMiddleware (req, res, next) { console.log('now: ', new Date()); next(); }
app.get('/todos', localMiddleware, todoController.getAll)
app.get('/todos/:id', todoController.get)
|
為什麼需要 Middleware
前面介紹了這麼多,還沒講到一個重點,為什麼需要 Middleware?
來舉個例子,如果我想要取得 request body 的內容的話怎麼辦?你可能很直覺的這樣寫:
(假設是一個新增 todo 的 request)
1 2 3
| app.post('/todos', (req, res) => { console.log(req.body); })
|
這樣的想法是正確的。但很抱歉,Express 預設的 Middleware 是沒有提供這個功能的,你必須透過另外一個 Middleware,讓它先處理好 request body 的部分後,才傳給你現在的 Middleware,大概會長這樣:
1 2 3 4 5 6
| const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
|
剛有說過 app.use
會是被視為全域的 Middleware,所以接下來在其他的 Middleware 裡面都可以直接用 req.body.key
來拿內容。
剛剛是騙你的,其實在 4.0 以後 Express 有提供內建的 Middleware,所以不需要在下載 body-parser:
1 2 3
| app.use(express.urlencoded({ extended: true })); app.use(express.json());
|
順道一提,Express 內建的 middleware 有提供取得 query string 的功能:
1 2 3
| app.get('/'. (req, res, next) => { console.log(req.query); })
|
其他注意事項
res.end
後不可以再呼叫 next()
,因為 response 已經送出去了。
- INSERT 指令會拿到的 result:
1 2 3 4 5 6 7 8 9 10
| result: OkPacket { fieldCount: 0, affectedRows: 1, insertId: 4, serverStatus: 2, warningCount: 0, message: '', protocol41: true, changedRows: 0 }
|
資訊蠻多的,但最常用的應該會是 affectedRows
和 insertId
。
- ejs 有分
=
和 -
的差別
=
會自動做文字跳脫,-
不會。
1 2
| <%= '<h1>safe</h1>' %> <%- '<h1>unsafe</h1>' %>
|
- 關於 flash 和 session
請務必記得這個順序:
1 2 3 4 5 6 7 8 9 10
| const flash = require('connect-flash'); const session = require('express-session');
app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true, }))
app.use(flash());
|