Blog#29: Tạo một Middleware chuẩn chỉnh trong Nodejs Express – [Express Tutorial – Part 2/10] 😊 (Series: Bí kíp Javascript – PHẦN 24)

Mình là TUẤN hiện đang là một Full-stack Developer tại Tokyo 😉. Nếu bạn thấy Blog này hay xin hãy cho mình một like và đăng ký để ủng hộ mình nhé 😊. Tổng quan Các hàm middleware là các hàm có quyền truy cập vào đối tượng request (req), đối tượng response(res) và hàm

Mình là TUẤN hiện đang là một Full-stack Developer tại Tokyo 😉.
Nếu bạn thấy Blog này hay xin hãy cho mình một like và đăng ký để ủng hộ mình nhé 😊.

Tổng quan

Các hàm middleware là các hàm có quyền truy cập vào đối tượng request (req), đối tượng response(res) và hàm next trong chu trình request-response của ứng dụng. Hàm next này là một hàm trong Routing Express, khi được gọi, sẽ thực thi middleware kế tiếp ngay sau middleware hiện tại trong stack.

Các hàm middleware có thể thực hiện các tác vụ sau:

  • Thực thi bất kỳ logic code nào mà bạn muốn.
  • Thực hiện các thay đổi đối với các đối tượng request và các đối tượng response.
  • Kết thúc chu kỳ request-response.
  • Gọi middleware tiếp theo trong call-stack (ngăn xếp).

Nếu hàm middleware hiện tại không kết thúc chu kỳ request-response, nó phải gọi hàm next() để chuyển quyền điều khiển cho hàm middleware tiếp theo. Nếu không, request sẽ bị treo. (Cái này rất quan trọng nên các bạn chú ý nhé)

Hình sau cho thấy các phần tử của hàm middleware:

Bắt đầu với Express 5, các hàm middleware trả về một Promise sẽ gọi next(value) khi chúng từ chối hoặc gặp lỗi. Hàm next sẽ được gọi với value bị từ chối hoặc Lỗi được ném ra.

Một số ví dụ KINH ĐIỂN

Đây là một ví dụ về ứng dụng ExpressHello World” đơn giản. Phần còn lại của bài viết này sẽ giới thiệu và thêm ba hàm middleware kinh điển: hàm đầu tiên được gọi là myLogger sẽ in một thông báo nhật ký đơn giản, một cái khác được gọi là requestTime sẽ hiển thị dấu thời gian của request HTTP và hàm còn lại được gọi là validateCookies authentication các cookie được gửi đến server.

const express =require('express')const app =express()

app.get('/',(req, res)=>{
  res.send('Hello World!')})

app.listen(3000)

Hàm middleware: myLogger

Đây là một ví dụ đơn giản về hàm middleware được gọi là “myLogger”. Hàm này chỉ in đoạn text “LOGGED” khi một request được gửi đến ứng dụng. Hàm middleware được gán cho một biến có tên myLogger.

constmyLogger=function(req, res, next){
  console.log('LOGGED')next()}

Lưu ý ở trên việc gọi tới hàm next() này sẽ gọi hàm middleware tiếp theo trong ứng dụng. Hàm next() không phải là một phần của Node.js hoặc Express API, nhưng là đối số thứ ba được chuyển cho hàm middleware. Hàm next() có thể được đặt tên tùy ý có thể là bất kỳ thứ gì, nhưng theo quy ước, nó luôn được đặt tên là “next”. Để tránh nhầm lẫn, hãy luôn sử dụng quy ước này.

Để sử dụng hàm middleware, hãy gọi app.use() và chỉ định hàm middleware làm đối số. Ví dụ, đoạn code sau tải hàm middleware myLogger trước khi Routing đến đường dẫn gốc (/).

const express =require('express')const app =express()constmyLogger=function(req, res, next){
  console.log('LOGGED')next()}

app.use(myLogger)

app.get('/',(req, res)=>{
  res.send('Hello World!')})

app.listen(3000)

Mỗi khi ứng dụng nhận được một request, nó sẽ in đoạn text “LOGGED” lên terminal.

Lưu ý: Thứ tự tải middleware rất quan trọng: các hàm middleware được tải trước cũng được thực thi trước.

Nếu myLogger được tải sau route dẫn đến đường dẫn gốc (/), request sẽ không bao giờ in “LOGGED”, vì route handler của đường dẫn gốc chấm dứt chu kỳ request-response trước khi loadmiddlewaremyLogger😄.

Hàm middleware myLogger chỉ đơn giản là in một đoạn text, sau đó chuyển request đến hàm middleware tiếp theo trong ngăn xếp bằng cách gọi hàm next().

Hàm middleware: requestTime

Tiếp theo, chúng ta sẽ tạo một hàm middleware được gọi là “requestTime” và thêm một thuộc tính được gọi requestTime vào đối tượng request. Đây là một tính năng mạnh mẽ của Middleware giúp ta thêm bất kỳ data gì vào reqres và cứ thế gửi nó thông qua callback của các middleware tiếp theo vào thế là dữ liệu có thể đi tới mọi nợi mà chúng ta muôn (Quá đỉnh).

constrequestTime=function(req, res, next){
  req.requestTime = Date.now()next()}

Ứng dụng hiện sử dụng hàm middleware requestTime. Ngoài ra, hàm callback của route (/) sử dụng thuộc tính mà hàm middleware đã thêm vào req (đối tượng request).

const express =require('express')const app =express()constrequestTime=function(req, res, next){
  req.requestTime = Date.now()next()}

app.use(requestTime)

app.get('/',(req, res)=>{let responseText ='Hello World!<br>'
  responseText +=`<small>Requested at: ${req.requestTime}</small>`
  res.send(responseText)})

app.listen(3000)

Khi bạn thực hiện request tới (/), ứng dụng hiện hiển thị dấu thời gian request của bạn trong trình duyệt.

Hàm middleware: validateCookies

Cuối cùng, chúng ta sẽ tạo một hàm middleware để validate các Cookies đến và gửi phản hồi status 400 nếu cookie không hợp lệ.

Đây là một ví dụ về hàm validateCookies với một service asynchronous bên ngoài. (cứ ví dụ như mình dùng hàm externallyValidateCookie của một ông nào đố code hoặc của một bên thứ 3 cũng được)

asyncfunctioncookieValidator(cookies){try{awaitexternallyValidateCookie(cookies);// Nếu các bạn muốn chạy thử có thể thay thế bằng 1 Promise bất kỳ// await new Promise((resolve) => resolve(cookies)); }catch{thrownewError('Invalid cookies')}}

Ở đây chúng ta sử dụng middleware cookie-parser (nếu bạn chưa cài thì cứ: npm i cookie-parser là sẽ cài đặt được middleware này) để phân tích các cookie đến từ đối tượng req và chuyển chúng đến hàm cookieValidator của chúng ta. Middleware validateCookies trả về một Promise mà khi bị Reject sẽ tự động kích hoạt trình error Handling của chúng ta.

const express =require("express");const app =express();const cookieParser =require("cookie-parser");

app.use(cookieParser());// Hiện tại mình MOCK đơn giản hàm này như vậy.// Trong thực tế nó có thể là một thư viện hoặc một cái gì gì đấy trả về 1 Promoise.v.v.constexternallyValidateCookie=(cookies)=>newPromise((resolve)=>resolve(cookies));asyncfunctioncookieValidator(cookies){try{awaitexternallyValidateCookie(cookies);}catch{thrownewError("Invalid cookies");}}asyncfunctionvalidateCookies(req, res, next){awaitcookieValidator(req.cookies ||"cookies");
  console.log("req.cookies :>> ", req.cookies);next();}

app.use(validateCookies);

app.get("/",(req, res)=>{let responseText ="Hello World!<br>";
  responseText +=`<small>Requested at: ${req.requestTime}</small>`;
  res.send(responseText);});// error handler
app.use((err, req, res, next)=>{
  res.status(400).send(err.message)})

app.listen(3000);

Lưu ý cách gọi next() sau block-codeawait cookieValidator(req.cookies): Điều này đảm bảo rằng nếu cookieValidator được giải quyết, middleware tiếp theo trong ngăn xếp sẽ được gọi. Nếu bạn chuyển bất kỳ thứ gì vào làm đối số cho hàm next() (ngoại trừ string 'route'hoặc 'router'), Express sẽ coi như request hiện tại hặp lỗi và sẽ bỏ qua mọi function Routingmiddleware đi thẳng đến vị trí error handler.

Bởi vì chúng ta có quyền truy cập vào đối tượng request, đối tượng response và các hàm middleware tiếp theo trong ngăn xếptoàn bộ API Node.js => khả năng của hàm middleware là vô tận và nó có thể làm mọi thứ. NAI SƠ 😄

Configurable middleware

Nếu bạn cần middleware của mình có thể định các configure một cách linh hoạt, hãy exports một hàm chấp nhận một đối tượng tùy chọn hoặc các tham số khác, sau đó trả về một middleware dựa trên các tham số input. (Nó gần gần như Abstract Factory Design Pattern)

Ví dụ mình tạo 1 file: my-middleware.js

module.exports=function(options){returnfunction(req, res, next){// Implement the middleware function based on the options objectnext()}}

Middleware bây giờ có thể được sử dụng như hình dưới đây.

const mw =require('./my-middleware.js')

app.use(mw({ option1:'1', option2:'2'}))

Roundup

Như mọi khi, mình hy vọng bạn thích bài viết này và học thêm được điều gì đó mới.

Cảm ơn và hẹn gặp lại các bạn trong những bài viết tiếp theo! 😍

Nếu bạn thấy Blog này hay xin hãy cho mình một like và đăng ký để ủng hộ mình nhé. Thank you.😉2

Ref

Nguồn: viblo.asia

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ