Sử dụng Ktor cho việc tạo các REST APIs cho mobile (phần 2)

Tram Ho

Tiếp theo sau phần 1, ở phần này chúng ta sẽ đi sâu vào các thiết lập và định nghĩa các ClassFunction từ IntelliJ để xử lý cho việc gọi API từ phía client.

Xây dựng các lớp Model

Để tương tác với các dữ liệu được lưu trữ từ Postgres ta cần xây dựng các lớp model tương ứng kết hợp với việc sử dụng repository. Như đã trình bày từ phần 1 chúng ta sẽ cần xây dựng 2 lớp UserTodo

Đầu tiên chúng ta tạo một thư mục có tên là models và định nghĩa một class User có nội dung như sau:

Class này được sử dụng để tạo một User với các thành phần cần có là email, tên và mật khẩu dưới dạng hash cái mà giúp tăng bảo mật cho database

Kế tiếp trong thư mục models ta tạo tiếp một class là Todo:

Class này có tác dụng để khai báo thông tin công việc cần làm của 1 user, với các tham số là user ID, nội dung công việc cần làm và trạng thái công việc đã làm xong hay chưa.

Xây dựng các lớp Database

Ở bước này chúng ta sẽ tạo ra các class để giúp cho việc tương tác với các bảng của database.

Đầu tiên ta tạo thư mục có tên là repository để lưu trữ các class liên quan này. Kế đến ta tạo một file có tên là Users để giúp cho việc tạo bảng user trên database, file có nội dung như sau:

Class trên sẽ giúp cho chúng ta tạo ra 1 đối tượng user với 4 cột là id, email, tên và mật khẩu. Việc này giúp ta có thể lưu thông tin của user vào database dễ dàng.

Tiếp theo cũng trong thư mục repository ta tạo tiếp 1 object Todos với nội dung như sau:

Class này sẽ giúp tạo đối tượng Todos với việc liên kết đến user id ở bảng Users.

Kế đến, chúng ta tạo một classs là DatabaseFactory giúp cho việc tạo các bảng cần thiết và các thiết lập cơ bản để kết nối tới database của Postgres

Class trên sẽ chứa 3 hàm:

  • Hàm init(): khởi tạo việc kết nối đến database và tạo 2 bảng là Users và Todos
  • Hàm hikari(): thiết lập các tham số cần cho việc kết nối đến database, các tham số này chúng ta đã cấu hình ở bước trước đó gồm JDBC_DRIVER, JDBC_DATABASE_URL. Nếu chúng ta dùng một tải khoản khác ngoài tài khoản mặc định của postgres thì cần thêm 2 tham số là DB_USER, DB_PASSWORD để giúp chứng thực việc kết nối tới database.
  • Hàm dbQuery(block: () -> T): sử dụng cơ chế của Coroutines để chạy các hàm gọi đến database trong IO thread, giúp cho các tác vụ xử lý của server không bị chậm và gián đoạn.

Tạo Repository cho việc quản lý các hàm gọi tới Database

Ở bước này chúng ta sẽ định nghĩa ra các phương thức để truy cập và thao tác lên database của Postgres từ bên trong project IntelliJ.

Để thực hiện việc này tại thư mục repository ta thêm một interface tên là Repostiory và khai báo các phương thức như sau:

Ta có thể thấy inteface này gồm các phương thức: thêm user, tìm user bởi id và email, thêm công việc và lấy danh sách công việc của user.
Tất cả các hàm đều sử dụng cơ chế Coroutines giúp cho việc chạy có thể hoạt động bất đồng bộ, không làm gián đoạn server.

Kế đến ta sẽ thực hiện việc cài đặt các phương thức này. Tại thư mục repository ta tạo thêm file có tên là TodoRepository để bắt đầu việc cài đặt, nội dung như sau:

Ở đây ta thấy hàm addUser sẽ nhận các tham số đầu vào là chuỗi email và password. Dựa trên các phần đánh dấu bên trong thân hàm ta có thể thấy nó gồm các bước chính:

  1. Sử dụng câu lệnh InsertStatement của thư viện Exposed mà ta đã khai báo trước đó trong file build.gradle để giúp thêm dữ liệu vào database của Postgres.
  2. dbQuery sử dụng cơ chế Coroutines để chạy các hàm thao tác đến database.
  3. Sử dụng câu lệnh insert có sẵn từ lớp Table để tiến hành thêm 1 record vào bảng.
  4. Thực hiện hàm rowToUser để phục vụ cho việc chuyển đổi dạng dữ liệu từ ResultRow đến User.

Các hàm còn lại như findUser, addTodo, getTodos cũng thực hiện theo cơ chế tương tự như trên.

Xây dựng các lớp cho việc chứng thực User

Khi làm việc với các dữ liệu liên quan đến User chúng ta cần phải xây dựng các lớp chứng thực để giúp server được xây dựng có tính bảo mật và phục vụ đúng đối tượng gửi request. Ở bước tạo dự án trước đó chúng ta đã chọn phương pháp chứng thực là JWT, giờ đây chúng ta sẽ tạo ra các phương thức dựa trên phương pháp này.

Đầu tiên, chúng ta tạo một thư mục có tên là auth. Từ thư mục đó tạo file Auth.kt với nội dung như sau:

File trên có tác dụng là lấy ra hashKey thông qua biến môi trường SECRET_KEY ta đã tạo từ bước trước đó và một hàm để hash một chuỗi bất kì sử dụng thuật toán HmacSHA1.

Kế đến ở thư mục auth, ta tạo tiếp một file JwtService.kt với nội dung:

File này giúp cho ta tạo một service JWT có tác dụng chứng thực các request từ phía client gửi lên. Hàm generateToken có tác dụng tạo ra một token sử dụng cho việc chứng thực các request của user sau khi user đã đăng nhập thành công. Chuỗi token này sẽ hết hạn sau 24h.

Cuối cùng tại thư mục auth này ta tạo thêm một data class MySession để lưu trữ session của user, nội dung lưu trữ chính là id của user

Cập nhật các cấu hình cho việc chạy Application

Ở bước này, ta sẽ sử dụng các lớp đã định nghĩa ở trên để cấu hình lại cho việc chạy server đang xây dựng.

Tại file Application.kt, ta thay thế class MySession bằng lớp Mysession chúng ta vừa tạo.
Phía dưới câu lệnh install(Sessions) ta thêm các đoạn code sau:

Đoạn code trên có tác dụng cho việc khởi tạo database và các chứng thực về JWT ta đã xây dựng ở bước trên

Tiếp đến ở phần install(Authentication) ta cập nhật lại nội dung để sử dụng JWT service cho việc verify các request từ client gửi đến.

Hàm trên có nhiệm vụ là chứng thực lời gọi của user có hợp lệ hay không dựa vào id của user từ database đã lưu và id của user gửi lên có tồn tại hay không.

Cuối cùng chúng ta build lại server và đảm bảo có thể thấy được các log liên quan đến Hikari và có thể kết nối database thành công mà không báo lỗi gì.

Xây dựng các Routes

Ở bước này chúng ta sẽ xây dựng các Route giúp cho phía client có thể thực hiện các request lên server, cùng đó là các xử lý tương ứng với các request gửi lên để trả kết quả về cho phía client.

Việc đầu tiên là ở file Application.kt, chúng ta tạo một đường dẫn prefix cho các Route, việc này không bắt buộc nhưng được khuyến khích để có những update cho server về sau chúng ta sẽ dễ dàng quản lý các route và bảo trì. Ta add đoạn code sau vào cuối file Application.kt

Ta sẽ bắt đầu xây dựng các Route liên quan đến User. Tạ tạo thư mục routes để lưu giữ các file liên quan, tiếp đến tạo một file là UserRoute, chúng ta import các thư viện liên quan ở đầu file để tránh các vấn đề chọn sai thư viện như sau:

Kế đến, định nghĩa các đường dẫn route liên quan đến users

Đối với mỗi đường dẫn Route, ta tạo các class để xử lý các chức năng liên quan đến nó, ở đây ta có 2 đường dẫn là “users/login” và “users/create” ta sẽ khai báo lần lượt 2 class là UserLoginRoute và UserCreateRoute như sau:

Ta thấy mỗi định nghĩa sẽ có 3 phần:

  • KtorExperimentalLocationsAPI: dùng để loại bỏ các warning khi compile code
  • Location(USER_CREATE): xác định đường dẫn Route cần cài đặt
  • class UserCreateRoute: định nghĩa class xử lý việc thực thi khi client gọi tới Route tương ứng

Kế tiếp ta thực hiện việc cài đặt phần UserCreateRoute và UserLoginRoute như sau:

Phân tích thử hàm UserCreateRoute ta thấy có các công việc sau:

  1. Định nghĩa một extension function của class Route có tên là users. Hàm này nhận các tham số đầu vào là repository, JWT serveice và một hàm hash.
  2. Khởi tạo một route với tác vụ POST
  3. Thực hiện lệnh call để lấy về các tham số được truyền khi request
  4. Thức hiện check các tham số password, displayName, email nếu không có thì trả về mã lỗi
  5. Tạo một hash string từ mật khẩu nhận được
  6. Thực hiện câu lệnh thêm user vào database

Với hàm UserLoginRoute thì việc check cũng tương ứng, nhận vào email và password. Sau đó kiểm tra email và password sau khi hash có tồn tại trong database không. Nếu có trả về login thành công, ngược lại trả về lỗi.

Kế tiếp, tại thư mục routes ta tạo file TodosRoute.kt để xây dựng các route và xử lý liên quan đến danh sách công việc Todo, nội dung như bên dưới:

Về cơ bản nó sẽ gồm 2 công việc, sử dụng phương thức POST cho việc thêm công việc của một user đến database, và một thức GET cho việc lấy danh sách công việc từ user id được truyền lên từ request.
Ở đây ta lưu ý là có thể sử dụng cùng một route cho 3 phương thức khác nhau là POST, GET hoặc DELETE.

Cơ bản, chúng ta đã xây dựng xong các phương pháp cần thiết cho việc xử lý các route từ phía server. Bước cuối cùng là ta thông báo cho server chúng ta có thể chấp nhận xử lý các request nào gọi tới.
Để làm việc này ta mở lại file Application.kt và tìm đến dòng routing, ta sẽ thêm vào 2 function route đã xây dựng:

Đến đây, chúng ta đã hoàn thành việc xây dựng server cơ bản, bước kế tiếp chúng ta sẽ kiểm tra việc hoạt động của nó.

Kiểm tra việc chạy server

Để thực hiện việc kiểm tra các API đã xây dựng hoạt động có chính xác không, ta dùng 1 công cụ rất hay là Postman (https://www.postman.com/) để chạy thực nghiệm.

Sau khi cài đặt Postman, ta tiến hành test việc tạo một user với các thông tin như sau:

  • Phương thức: POST
  • Đường dẫn: localhost:8080/v1/users/create
  • Body: với 3 tham số displayName, email, password

Sau khi nhập đầy đủ các thông tin, chúng ta nhấn Send. Thông tin trả về sẽ là một chuỗi token như hình bên dưới

Ta sẽ tiến hành lưu chuỗi token này lại, sử dụng cho các lần truy cập sau của user này, để thực hiện ta mở tab Test và gõ dòng lệnh sau

Các dòng lệnh trên giúp ta lưu trữ token vào một biến có tên là jwt_token.

Kế tiếp ta sẽ thực viện việc gọi login cho user với các thông tin đã đăng kí ở trên, ta thiết lập trên Postman như sau:

  • Phương thức: POST
  • Đường dẫn: localhost:8080/v1/users/login
  • Body: với 2 tham số email, password

Nếu nhận được thông tin token là việc login đã thành công, xem hình mình hoạ bên dưới

Với user đã đăng nhập thành công, ta sẽ thực hiện chạy API về tạo danh sách Todo các công việc của user đó. Trước tiên ta cần chứng thực thông tin user đã login bằng các thêm vào tab Authorization một chuỗi token có tên là jwt_token đã định nghĩa ở bước trên

Tiếp theo tạo thông tin như sau:

  • Phương thức: POST
  • Đường dẫn: localhost:8080/v1/todos
  • Body: với 2 tham số todo, done

Khi các bước chạy thành công, ta sẽ thấy kết quả trả về như hình bên dưới

Đối việc lấy danh sách Todos, chúng ta chỉ cần chuyển đổi phương thức từ POST đến GET là có thể thực hiện.

Đến đây chúng ta có thể kiểm tra thành công 4 API chúng ta vừa tạo từ server.

Tham khảo

  1. https://www.raywenderlich.com/7265034-ktor-rest-api-for-mobile
Chia sẻ bài viết ngay

Nguồn bài viết : Viblo