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

Trong lĩnh vực lập trình backend, đặc biệt là khi làm việc với các API REST, khái niệm Middleware đã trở thành một phần quan trọng. Trong bài viết này, chúng ta sẽ cùng nhau khám phá công dụng, phân loại và cách ứng dụng Middleware trong việc phát triển ứng dụng, đặc biệt là với Golang.

Middleware Là Gì?

Middleware có thể được hiểu đơn giản là phần mềm trung gian, đóng vai trò là cầu nối giữa các thành phần của hệ thống, phần mềm hoặc dịch vụ. Khi nói đến lập trình backend, middleware hoạt động ở giữa RequestResponse, giúp tiếp nhận, xử lý thông tin và hỗ trợ cho các middleware khác hoặc cho chính Request/Response đó.

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

Trong các hệ thống phân tán, middleware trở thành các dịch vụ trung gian giúp kết nối các thành phần quan trọng với nhau.

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

Phân Loại Middleware

Dựa trên thông tin từ Wikipedia, chúng ta có thể phân loại middleware thành 4 loại chính:

  1. Transactional: Xử lý các giao dịch đồng bộ và bất đồng bộ, chẳng hạn như giao dịch ngân hàng hoặc thanh toán thẻ tín dụng.
  2. Message: Dùng trong các hàng đợi thông điệp và kiến trúc gửi thông điệp, hỗ trợ giao tiếp đồng bộ và bất đồng bộ.
  3. Procedural: Các kiến trúc từ xa và cục bộ để kết nối, chuyển đổi và truy xuất phản hồi của các giao tiếp hệ thống không đồng bộ.
  4. Object-oriented: Kết hợp các nguyên tắc của lập trình hướng đối tượng để cung cấp chức năng tương tự như middleware hướng thủ tục, bao gồm tham chiếu đối tượng, exceptions và kế thừa thuộc tính.

Tại Sao Nên Sử Dụng Middleware?

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

Khi xử lý một Request trong REST API, thường có nhiều logic nghiệp vụ lặp đi lặp lại như: Logging, Authentication, và Parse body data. Việc sử dụng middleware không chỉ giúp giảm thiểu code lặp nhưng còn giúp tổ chức mã nguồn một cách rõ ràng và dễ bảo trì hơn.

Ví dụ, trong trường hợp kiểm tra Authorization (quyền truy cập) cho các Request mà client gửi kèm access token, middleware có thể nhanh chóng phản hồi lỗi nếu access token không hợp lệ hoặc đã hết hạn trước khi quá trình xử lý tiếp theo diễn ra.

Hầu hết các framework xây dựng website và REST API như Express, Gin, Echo, hay Laravel đều hỗ trợ middleware, giúp các lập trình viên dễ dàng quản lý logic chạy trước và sau các yêu cầu.

Cách Sử Dụng Middleware Trong GIN Golang

Trong Gin – một framework phổ biến của Golang, middleware được định nghĩa dưới dạng các hàm HandlerFunc, tương tự như các hàm xử lý Request thông thường. Dưới đây là cách định nghĩa một middleware đơn giản.

Định Nghĩa Một Middleware Đơn Giản

Chúng ta có thể khai báo một middleware để ghi 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() cho phép chuyển tiếp Request tới các Handler/Middleware tiếp theo. Ngược lại, nếu bạn muốn dừng Request và trả về phản hồi ngay lập tức, hãy sử dụng hàm Abort().

Sử Dụng Middleware Trong GIN

Có vài cách để sử dụng middleware trong Gin, bao gồm:

1. Dùng cho Tất Cả Request

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

Với cách này, tất cả Request sẽ chạy qua middleware logger.

2. Dùng cho Một Nhóm

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

Tất cả request trong nhóm /v1/* đều sẽ chạy qua middleware logger.

3. 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.

4. Phối Hợp Nhiều Middleware

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

Chúng ta có thể phối hợp nhiều 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: kiểm tra Access Token và lấy thông tin User từ Token. Nếu OK thì cho phép tiếp tục, ngược lại sẽ hủy bỏ – gọi là (1).
  2. Khai báo Middleware thứ hai: kiểm tra nếu role của User là Admin/Mod thì tiếp tục, ngược lại sẽ hủy bỏ – gọi là (2).

Giả sử với API GET /v1/users/1, bạn chỉ cần sử dụng Middleware thứ nhất. Nhưng với nhóm API /admin, bạn sẽ cần đến 2 middleware theo đúng thứ tự (1)(2).

Đây chính 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.

Mặc dù bài viết này sử dụng Golang làm ví dụ, nhưng cách tư duy này cũng có thể áp dụng cho các framework khác tương tự. Hy vọng bạn sẽ nắm vững kiến thức về Middleware và áp dụng một cách linh hoạt và hiệu quả trong công việc của mình.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *