Thứ Bảy, 2 tháng 11, 2019

Build API với express + firebase

Xây dựng API đơn giản với express và firebase
Chuẩn bị:

Expressjs framework
: đây là 1 framework nhỏ gọn và mạnh mẽ cho việc build 1 api, mình sử dụng express là để tận dụng khả năng routing mạnh mẽ linh hoạt của nó trong việc cấu trúc các endpoint cho api.
Mình sử dụng Express application generator, các bước cài đặt mọi người tham khảo sâu hơn tại trang chủ của nó.
Trong khuôn khổ bài này mình chỉ giới thiệu cách tổ chức thư mục và file để phục vụ nhu cầu như đã nói.
Mình chia ứng dụng thành các phần như sau:
  1. config.js: chứa các config của server
  2. app.js: file main, include router, middleware, chạy server ...
  3. firebase-key.json: key của firebase, ở phần dưới mình sẽ hướng dẫn các bạn lấy key này (cho những ai chưa biết)
  4. models: là nơi mình chứa các model để tương tác với tầng database, validate dữ liệu,…, tuy nhiên trong bài này, mình chỉ sử dụng model cho nhiệm vụ validate dữ liệu mà thôi
  5. routes: nơi chứa các router của ứng dụng
  6. middlewares: là nơi khai báo các custommiddleware cho ứng dụng của bạn. Bạn muốn mỗi request lên server sẽ hiện log, hoặc check authenticate.... thì sẽ khai báo ở đây và sử dụng trong app.js
  7. components: là nơi mình khai báo các thư viện như kết nối database…
  8. helps: các hàm tiện ích khác mình sẽ khai báo ở trong này

Các module cần cài đặt thêm bao gồm
  1. “validate”, để validate dữ liệu
  2. “firebase-admin”, sdk cung cấp các phương thức truy xuất dữ liệu firebase
Ok nào bắt đầu thôi.
Việc đầu tiên là mình cần phải có firebase-key.  Quá dễ dàng, nếu chưa bao giờ tạo các bạn đăng nhập vào: https://firebase.google.com/
Sau đó bấm vào “Go to console” ở góc phải trên cùng như trong hình dưới


Tiếp theo bạn “add project”, đặt tên cho project (thích tên gì thì đặt tên đó) rồi continue như hình dưới.


Bước tiếp theo google sẽ hỏi bạn có add google analytics cho project này không? Bạn chọn continue


Nếu chưa có tài khoản google analytics thì google cho phép mình tạo luôn, và cuối cùng là hoàn thành create 1 project.

Việc tiếp theo, ta đi lấy private key (firebase-key.json)
Bước 1: vào trang quản lý project, bấm vào cái bánh xe bên trái góc trên (khoanh đỏ) => project settings => click vào tab Service accounts => click vào nút “Generate private key” (hình dưới)
Vậy là xong, chúng ta có file private key, để nhất quán cho ví dụ này, ta đổi tên file thành firebase-key.json, còn ai thích đặt tên gì thì tùy.


Tiếp theo ta sẽ viết mã nhé.
Bây giờ mình sẽ phải xây dựng CRUD cho api của mình, tổ chức nó theo các endpoits như sau để thực hiện quản lý bài viết
Create: POST data đến http://your.api.domain/v1/articles //tạo bài viết
Read: GET http://your.api.domain/v1/articles   // liệt kê bài viết
Update: PATCH http://your.api.domain/v1/articles/{article_id} // cập nhật bài viết
Delete: DELETE http://your.api.domain/v1/articles/{article_id}  // xóa bài viết
Đầu tiên, ở phần models, mình tạo 1 file là “articleModel.js”, trong ví dụ này, với model mình chỉ sử dụng khai báo Schema để validate dữ liệu thôi.


/models/articleModel.js

Ở thư mục components mình tạo 1 file là “firebase.js”. File này mục đích là sử dụng sdk để thực hiện kết nối đến firebase

Ở file “app.js” ta thêm các dòng sau (các dòng bôi đen)
Mấy dòng trên là khởi tạo firebase connector, và khai báo sử dụng articleRouter

Dòng bôi đen là để khai báo sử dụng article router với enpoits /v1/articles
Ok, và giờ ta đi vào phần mất thời gian nhất, đó là phần xử lý logic trong articleRouter.
Ở phần khai báo đầu, mình khai báo sử dụng firestore để làm data base. (firebase cung cấp 2 loại database là Realtime database và firestore, giữa hai thằng này có một số điểm khác biệt, mà khác biệt cơ bản nhất khiến mình không dùng Realtime là việc truy vấn với điều kiện, Realtime database không cung cấp truy vấn đa điều kiện, còn mấy chỗ khác nhau nữa mình sẽ nói sâu hơn ở những topic sau nếu có thời gian)
Viết endpoints
Như ở phần đầu mình sẽ viết CRUD với các resource là
Create: POST data đến http://your.api.domain/v1/articles //tạo bài viết
Read: GET http://your.api.domain/v1/articles   // liệt kê bài viết
Update: PATCH http://your.api.domain/v1/articles/{article_id} // cập nhật bài viết
Delete: DELETE http://your.api.domain/v1/articles/{article_id}  // xóa bài viết
Phần create và read ta thực hiện post và get đến root router của resource như hình dưới.

Hàm get được viết như thế này


ở hàm get, mình đang lấy limit 5 bản ghi để ví dụ thôi, còn bạn nào muốn phân trang, thì nghiên cứu thêm, firebase có hỗ trợ query phân trang khá độc đáo, mình không đề cập ở đây.
Hàm post

Với update và delete, ta yêu cầu phải có id param do đó lúc này enpoits bắt buộc phải thay đổi. ta sử dụng chung 1 middleware
Mục đích đoạn middleware này là để ném firebase doc vào để sử dụng chung cho  các method sau.
Hàm patch


Hàm patch này sẽ thực hiện cập nhật data cho bản ghi xác định ở middleware
Hàm delete

Hàm delete này có một chút đặc biệt trong query.
Vì trong firebase, nếu mình thực hiện xóa 1 bản ghi (doc) thì các trường của nó vẫn không được xóa, mình vẫn có thể truy xuất dữ liệu của các trường đó nghĩa là bản ghi được xóa đi rồi, nhưng giá trị của các trường của bản ghi đó vẫn tồn tại, mặc dù không còn id của doc đó nữa, thế mới hay nhỉ!!. (cái này các bạn tìm hiểu trong tài liệu của firebase). Vì vậy nên để xóa triệt để 1 bản ghi mình sẽ thực hiện 2 query một lúc, query thứ nhất: thực hiện xóa toàn bộ các trường của bản ghi đó
Query thứ 2: thực hiện xóa doc.
Vì mình thực hiện 2 query trong cùng 1 nghiệp vụ, nên để tiện, mình sử dụng batch delete (xóa theo lô, lô ở đây là tập hợp các query).
Như vậy là mình đã hoàn thành xong 1 api đơn giản đầy đủ CRUD.
Mặc dù mình viết code lởm khởm, nhưng ưu điểm là với cách tổ chức như thế này, mình có thể sử dụng lại được rất nhiều. với những bảng dữ liệu khác, chỉ cần khai báo model, copy và đổi tên router, cấu hình router ngoài app, vậy là chỉ mất khoảng 5 phút để thêm 1 resource mới.
Dùng postman để test nhé!!
Các bạn có câu hỏi vui lòng comment nhé.

Toàn bộ mã nguồn các bạn download tại https://bitbucket.org/share_by_hung/lession1/src/master/

3 nhận xét:

  1. Bài viết rất hay và hữu ích. Cảm ơn a nhiều@@

    Trả lờiXóa
  2. bài hay quá anh ơi, chúc anh có nhiều bài mới nhé

    Trả lờiXóa
  3. Não em bắt đầu vận động nhiều hơn rồi anh ạ <3

    Trả lờiXóa