, June 27, 2022

0 kết quả được tìm thấy

Middleware là gì? Ứng dụng middleware cho REST API


  •   5 min reads
Middleware là gì? Ứng dụng middleware cho REST API

Trong bài viết này chúng ta sẽ cùng tìm hiểu khái niệm Middleware và cách chúng được sử dụng trong backend REST API.

Middleware là gì

Middleware là phần mềm trung gian để kết nối các thành phần trong hệ thống, phầm mềm hay service.

Trong lập trình backend, middleware nằm giữa RequestResponse, có nhiệm vụ tiếp nhận và xử lý thông tin hỗ trợ cho các middleware tiếp theo hoặc cho chính Request/Response đó.

Middleware hỗ trợ Request và Response
Middleware hỗ trợ RequestResponse

Trong các hệ thống phân tán, Middleware sẽ là các service trung gian để kết nối các thành phần quan trọng với nhau.

Middleware trong hệ thống phân tán

Phân loại Middleware

Dựa theo Wikipedia, ta có 4 loại middleware:

  1. Transactional: Xử lý những transaction đồng bộ và bất đồng bộ như một nhóm các yêu cầu liên kết từ các hệ thống phân tán, chẳng hạn như giao dịch ngân hàng hoặc thanh toán thẻ tín dụng.
  2. Message: Xử dụng trong các message queue và các kiến trúc gởi message, hỗ trợ giao tiếp đồng bộ và bất đồng bộ.
  3. Procedural: Các kiến trúc từ xa (remote) và cục bộ (local) để kết nối, chuyển đỏi và truy xuất các phản hồi của các giao tiếp hệ thống không đồng bộ.
  4. Object-oriented: Tương tự như phần mềm trung gian hướng thủ tục (Procedural), tuy nhiên, loại phần mềm trung gian này kết hợp các nguyên tắc thiết kế lập trình hướng đối tượng (OOP). Về mặt phân tích, thành phần của nó bao gồm các tham chiếu đối tượng, exceptions và kế thừa các thuộc tính thông qua các yêu cầu đối tượng phân tán.

Vì sao phải sử dụng Middleware

Mục đích sử dụng Middleware nhằm chi nhỏ các thành phần trong hệ thống và phần mềm, giúp dễ dàng tái sử dụng và lắp ghép cho nhiều trường hợp khác nhau.

Trong bài viết này mình sẽ tập trung vào middleware trong lập trình backend, cụ thể là REST API với Golang.

Xử lý một Request trong REST API sẽ bao gồm rất nhiều các logic nghiệp vụ. Trong đó sẽ có rất nhiều logic lặp đi lặp lại ở nhiều Request khác như: Logging, Authen, Parse body data,... Để có thể dễ dàng tái sử dụng cũng như phối hợp các logic trên, việc sử dụng Middleware là rất cần thiết.

Lấy ví dụ với trường hợp check Authorization (quyền truy cập) cho các Requests yêu cầu client gởi kèm access token. Nếu access token không hợp lệ hoặc hết hạn, Middlware có thể giúp phản hồi lỗi trước đi chạm đến các hàm xử lý tiếp theo.

Chính vì điều này, hầu hết các framework xây dựng website, REST API hỗ trợ Middleware như: Express, Gin, Echo, Lavarel,...

Sử dụng Middleware trong GIN Golang

Về bản chất các Middleware trong GIN được định nghĩa là các hàm HandlerFunc, tương đương một hàm xử lý Request bình thường:

// HandlerFunc defines the handler used by gin middleware as return value.
type HandlerFunc func(*Context)

Định nghĩa một Middleware đơn giản trong GIN

Để minh hoạ đơn giản, mình sẽ khai báo một Middleware in log mỗi khi có Request vào như sau:

func logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		log.Printf("Request from %s: %s", c.ClientIP(), c.Request.URL.Path)

		c.Next()
	}
}

Hàm Next() được sử dụng khi các bạn muốn chuyển tiếp Request tới các Handler/Middleware phía sau. Ngược lại hàm Abort() sẽ dừng Request lại và Response về client ngay lập tức.

Sử dụng Middleware trong GIN

Có vài cách để dùng được Middleware trong GIN hay đúng hơn là giới hạn tầm hoạt động của Middleware:

Dùng cho tất cả request hay toàn bộ application

//...
func main() {
	router := gin.New()
    
    router.Use(logger())
    
    router.Run()
}
//...

Với cách này tất cả Request đều sẽ chạy qua Middleware logger.

Dùng cho một group

//...
func main() {
	router := gin.New()
    
    v1 := router.Group("/v1", logger())
    
    router.Run()
}
//...

Tất cả request /v1/* đều sẽ chạy qua Middleware logger.

Dùng cho từng URL cụ thể

//...
func main() {
	router := gin.New()
    
    router.GET("/ping", logger(), func(c *gin.Context) {
		c.JSON(200, gin.H{"data": "pong"})
	})
    
    router.Run()
}
//...

Chỉ áp dụng cho API GET /ping.

Phối hợp liên tiếp các Middleware với nhau

//...
func main() {
	router := gin.New()
    
    router.GET("/ping", logger(), logger(), logger(), func(c *gin.Context) {
		c.JSON(200, gin.H{"data": "pong"})
	})
    
    router.Run()
}
//...

Trên thực tế chúng ta có thể phối hợp không giới hạn số lượng Middleware để thực hiện các logic phức tạp hơn.

Case study phối hợp nhiều Middleware

  1. Khai báo Middleware thứ nhất chịu trách nhiệm kiểm tra Access Token và lấy ra thông tin User dựa trên Token. Nếu OK thì được phép Next(), ngược lại thì Abort() - gọi là (1).
  2. Khai báo Middleware thứ hai kiểm tra nếu role User là Admin/Mod thì được phép Next() ngược lại thì Arbort() - gọi là (2).

Giả sử với API GET /v1/users/1 thì bạn chỉ cần dùng Middleware thứ nhất là đủ. Nhưng với các API trong group /admin thì sẽ cần 2 Middlware theo đúng thứ tự (1), (2).

Đương nhiên bạn không cần phải khai báo thêm 1 Middleware để làm lại 2 công việc này. Đây là lợi thế của việc tái sử dụng và kết nối các Middleware với nhau để thực hiện các logic phức tạp hơn.

Mặc dù bài viết sử dụng Golang làm ví dụ, các bạn vẫn có thể sử dụng tư duy trên để sử dụng cho các framework tương đương. Chúc các bạn nắm vững được Middleware và vận dụng linh hoạt và hiệu quả nhé.

Bài viết liên quan

Ứng dụng Clean Architecture cho service Golang REST API

Trong bài viết này mình sẽ cung cấp một ví dụ cụ thể cho việc vận dụng nguyên tắc và tư duy Clean Architecture cho một service REST API Golang...

Ứng dụng Clean Architecture cho service Golang REST API
Golang Environment Variable: Biến môi trường trong Golang

Golang Environment Variable là biến môi trường trong Golang. Chúng là các cặp key-value được sử dụng xuyên suốt hệ thống...

Golang Environment Variable: Biến môi trường trong Golang
Clean Architecture là gì - Ưu nhược và cách dùng hợp lý

Clean Architecture là một kiến trúc ứng dụng rất nổi tiếng dựa trên nguyên lý loại bỏ sự lệ thuộc giữa các đối tượng cũng như các layer trong ứng dụng. Clean Architecture bao gồm 4 layer được đại diện thông qua các vòng tròn đồng tâm...

Clean Architecture là gì - Ưu nhược và cách dùng hợp lý
Lập trình REST API TODO List với Golang - Từ UI tới triển khai

Hướng dẫn từng bước lập trình REST API với ngôn ngữ Go (Golang) sử dụng GIN và GORM...

Lập trình REST API TODO List với Golang - Từ UI tới triển khai
Lập trình backend là gì? Tự học lập trình REST API với Golang

Lập trình backend thực sự là một lĩnh vực rất thú vị và hiện đang được quan tâm hơn rất nhiều....

Lập trình backend là gì? Tự học lập trình REST API với Golang
You've successfully subscribed to 200Lab Blog
Great! Next, complete checkout for full access to 200Lab Blog
Xin chào mừng bạn đã quay trở lại
OK! Tài khoản của bạn đã kích hoạt thành công.
Success! Your billing info is updated.
Billing info update failed.
Your link has expired.