10 cách thực hành tốt nhất để viết API REST của Node.js

Trong bài viết này, chúng tôi đề cập đến các cách thực hành tốt nhất để viết API REST của Node.js, bao gồm các chủ đề như đặt tên tuyến đường của bạn, xác thực, kiểm tra hộp đen và sử dụng các tiêu đề bộ đệm phù hợp cho các tài nguyên này.

Một trong những trường hợp sử dụng phổ biến nhất cho Node.js là viết API RESTful bằng cách sử dụng nó. Tuy nhiên, trong khi chúng tôi giúp khách hàng tìm ra các vấn đề trong ứng dụng của họ với Trace, công cụ giám sát Node.js của chúng tôi, chúng tôi liên tục gặp phải rằng các nhà phát triển gặp nhiều vấn đề với API REST.

Tôi hy vọng những cách thực hành tốt nhất mà chúng tôi sử dụng tại RisingStack có thể giúp:

# 1: Sử dụng Phương thức HTTP & Tuyến đường API

Hãy tưởng tượng rằng bạn đang xây dựng API RESTful của Node.js để tạo, cập nhật, truy xuất hoặc xóa người dùng. Đối với các hoạt động này, HTTP đã có bộ công cụ đầy đủ: POST, PUT, GET, PATCH hoặc DELETE.

Như một cách thực hành tốt nhất, các tuyến API của bạn phải luôn sử dụng các danh từ làm định danh tài nguyên. Nói về tài nguyên của người dùng, việc định tuyến có thể như sau:

  • POST / người dùng hoặc PUT / người dùng: / id để tạo người dùng mới,
  • NHẬN / người dùng để lấy danh sách người dùng,
  • GET / user /: id để truy xuất người dùng,
  • PATCH / user /: id để sửa đổi bản ghi người dùng hiện có,
  • XÓA / người dùng /: id để xóa người dùng.

# 2: Sử dụng mã trạng thái HTTP đúng

Nếu có lỗi xảy ra trong khi phục vụ yêu cầu, bạn phải đặt mã trạng thái chính xác cho yêu cầu đó trong phản hồi:

  • 2xx, nếu mọi thứ đều ổn,
  • 3xx, nếu tài nguyên đã được di chuyển,
  • 4xx, nếu yêu cầu không thể được thực hiện do lỗi máy khách (như yêu cầu tài nguyên không tồn tại),
  • 5xx, nếu có lỗi xảy ra ở phía API (như một ngoại lệ đã xảy ra).

Nếu bạn đang sử dụng Express, việc đặt mã trạng thái cũng dễ như res.status (500) .send ({error: 'Đã xảy ra lỗi máy chủ nội bộ'}). Tương tự với Restify: res.status (201).

Để biết danh sách đầy đủ, hãy kiểm tra danh sách mã trạng thái HTTP

# 3: Sử dụng các tiêu đề HTTP để gửi siêu dữ liệu

Để đính kèm siêu dữ liệu về tải trọng bạn sắp gửi, hãy sử dụng các tiêu đề HTTP. Các tiêu đề như thế này có thể là thông tin về:

  • phân trang,
  • giới hạn tỷ lệ,
  • hoặc xác thực.

Một danh sách các tiêu đề HTTP được tiêu chuẩn hóa có thể được tìm thấy ở đây.

Nếu bạn cần đặt bất kỳ siêu dữ liệu tùy chỉnh nào trong các tiêu đề của mình, thì cách tốt nhất là đặt tiền tố cho chúng bằng X. Ví dụ: nếu bạn đang sử dụng mã thông báo CSRF, thì đó là cách phổ biến (nhưng không chuẩn) để đặt tên cho chúng là X-Csrf -Mã thông báo. Tuy nhiên, với RFC 6648, họ đã bị từ chối. Các API mới nên nỗ lực hết sức để không sử dụng tên tiêu đề có thể xung đột với các ứng dụng khác. Ví dụ: OpenStack tiền tố các tiêu đề của nó với OpenStack:

OpenStack-Danh tính-Tài khoản-ID
OpenStack-Network-Host-Name
OpenStack-Object-Storage-Chính sách

Lưu ý rằng tiêu chuẩn HTTP không xác định bất kỳ giới hạn kích thước nào trên các tiêu đề; tuy nhiên, Node.js (khi viết bài viết này) áp đặt giới hạn kích thước 80KB cho đối tượng tiêu đề vì lý do thực tế.

Thời gian Don cho phép tổng kích thước của các tiêu đề HTTP (bao gồm cả dòng trạng thái) vượt quá HTTP_MAX_HEADER_SIZE. Kiểm tra này ở đây để bảo vệ các trình nhúng chống lại các cuộc tấn công từ chối dịch vụ trong đó kẻ tấn công cung cấp cho chúng tôi một tiêu đề không bao giờ kết thúc mà trình nhúng tiếp tục đệm. "
Từ trình phân tích cú pháp HTTP Node.js

# 4: Chọn khung phù hợp cho API REST của Node.js

Điều quan trọng là chọn khung phù hợp nhất với trường hợp sử dụng của bạn nhất.

Express, Koa hoặc Hapi

Express, Koa và Hapi có thể được sử dụng để tạo các ứng dụng trình duyệt và do đó, chúng hỗ trợ tạo khuôn mẫu và kết xuất - chỉ để đặt tên cho một vài tính năng. Nếu ứng dụng của bạn cũng cần cung cấp phía người dùng, điều đó có ý nghĩa đối với họ.

Phục hồi

Mặt khác, Restify đang tập trung vào việc giúp bạn xây dựng các dịch vụ REST. Nó tồn tại để cho phép bạn xây dựng các dịch vụ API API nghiêm ngặt có thể duy trì và quan sát được. Restify cũng đi kèm với hỗ trợ DTrace tự động cho tất cả các trình xử lý của bạn.

Restify được sử dụng trong sản xuất trong các ứng dụng lớn như npm hoặc Netflix.

# 5: Hộp đen Kiểm tra API REST của Node.js

Một trong những cách tốt nhất để kiểm tra API REST của bạn là coi chúng là hộp đen.

Kiểm thử hộp đen là một phương pháp kiểm tra trong đó chức năng của một ứng dụng được kiểm tra mà không có kiến ​​thức về cấu trúc bên trong hoặc hoạt động của nó. Vì vậy, không có phụ thuộc nào bị chế giễu hoặc sơ khai, nhưng hệ thống được kiểm tra toàn bộ.

Một trong những mô-đun có thể giúp bạn với API REST của Node.js thử nghiệm hộp đen là chắc chắn nhất.

Một trường hợp thử nghiệm đơn giản để kiểm tra xem người dùng có được trả lại bằng cách sử dụng trình chạy thử mocha có thể được thực hiện như thế này không:

const request = request ('supertest')
 
mô tả ('GET / user /: id', function () {
  nó ('trả về người dùng', function () {
    // phiên bản mocha mới hơn cũng chấp nhận lời hứa
    yêu cầu trả lại (ứng dụng)
      .get ('/ người dùng')
      .set ('Chấp nhận', 'ứng dụng / json')
      .Exect (200, {
        id: '1',
        tên: 'John Math'
      }, làm xong)
  })
})

Bạn có thể hỏi: làm thế nào để dữ liệu được đưa vào cơ sở dữ liệu phục vụ API REST?

Nói chung, đó là một cách tiếp cận tốt để viết bài kiểm tra của bạn theo cách mà họ đưa ra càng ít giả định về trạng thái của hệ thống càng tốt. Tuy nhiên, trong một số trường hợp, bạn có thể thấy mình ở một vị trí khi bạn cần biết chính xác trạng thái của hệ thống là gì, để bạn có thể đưa ra các xác nhận và đạt được phạm vi kiểm tra cao hơn.

Vì vậy, dựa trên nhu cầu của bạn, bạn có thể điền vào cơ sở dữ liệu dữ liệu thử nghiệm theo một trong các cách sau:

  • chạy các kịch bản kiểm tra hộp đen của bạn trên một tập hợp con dữ liệu sản xuất đã biết,
  • điền dữ liệu vào cơ sở dữ liệu được tạo trước khi các trường hợp thử nghiệm được chạy.

Tất nhiên, kiểm tra hộp đen không có nghĩa là bạn không phải thực hiện kiểm tra đơn vị, bạn vẫn phải viết kiểm tra đơn vị cho các API của mình.

# 6: Xác thực không trạng thái, dựa trên JWT

Vì API REST của bạn phải không trạng thái, lớp xác thực của bạn cũng vậy. Đối với điều này, JWT (JSON Web Token) là lý tưởng.

JWT bao gồm ba phần:

  • Tiêu đề, chứa loại mã thông báo và thuật toán băm
  • Tải trọng, chứa các yêu cầu
  • Chữ ký (JWT không mã hóa tải trọng, chỉ cần ký tên!)

Việc thêm xác thực dựa trên JWT vào ứng dụng của bạn rất đơn giản:

const koa = Yêu cầu ('koa')
const jwt = Yêu cầu ('koa-jwt')
ứng dụng const = koa ()
app.use (jwt ({
  bí mật: 'rất bí mật'
}))
// Phần mềm trung gian được bảo vệ
app.use (hàm * () {
  // nội dung của mã thông báo sẽ có sẵn trên this.state.user
  này.body = {
    bí mật: '42'
  }
})

Sau đó, các điểm cuối API được bảo vệ bằng JWT. Để truy cập các điểm cuối được bảo vệ, bạn phải cung cấp mã thông báo trong trường tiêu đề ủy quyền.

curl --header "Ủy quyền: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwI
iwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30
RMHrHDcEfxjoYZgeFONFh7HgQ "my-website.com

Một điều mà bạn có thể nhận thấy là mô-đun JWT không phụ thuộc vào bất kỳ lớp cơ sở dữ liệu nào. Đây là trường hợp vì tất cả các mã thông báo JWT có thể được xác minh theo cách riêng của chúng và chúng cũng có thể chứa thời gian để giá trị sống.

Ngoài ra, bạn luôn phải đảm bảo rằng tất cả các điểm cuối API của bạn chỉ có thể truy cập được thông qua kết nối an toàn bằng HTTPS.

Trong một bài viết trước, chúng tôi đã giải thích chi tiết về các phương thức xác thực web - Tôi khuyên bạn nên kiểm tra!

# 7: Sử dụng các yêu cầu có điều kiện

Yêu cầu có điều kiện là các yêu cầu HTTP được thực thi khác nhau tùy thuộc vào các tiêu đề HTTP cụ thể. Bạn có thể nghĩ về các tiêu đề này như điều kiện tiên quyết: nếu chúng được đáp ứng, các yêu cầu sẽ được thực hiện theo một cách khác.

Các tiêu đề này cố gắng kiểm tra xem phiên bản của tài nguyên được lưu trữ trên máy chủ có khớp với phiên bản đã cho của cùng một tài nguyên không. Vì lý do này, những tiêu đề này có thể là:

  • dấu thời gian của sửa đổi cuối cùng,
  • hoặc một thẻ thực thể, khác nhau cho mỗi phiên bản.

Những tiêu đề này là:

  • Sửa đổi lần cuối (để cho biết khi nào tài nguyên được sửa đổi lần cuối),
  • Etag (để chỉ thẻ thực thể),
  • If-Modified-Because (được sử dụng với tiêu đề Sửa đổi lần cuối),
  • If-none-Match (được sử dụng với tiêu đề Etag),

Hãy cùng xem một ví dụ!

Ứng dụng khách bên dưới không có bất kỳ phiên bản trước nào của tài nguyên tài liệu, do đó, cả tiêu đề If-Modified-Because, hay If-none-Match đều không được áp dụng khi tài nguyên được gửi. Sau đó, máy chủ phản hồi với các tiêu đề Etag và Last-Modified được đặt đúng.

Từ tài liệu yêu cầu có điều kiện MDN

Máy khách có thể đặt các tiêu đề If-Modified-Because và If-none-Match một khi nó cố gắng yêu cầu cùng một tài nguyên - vì hiện tại nó đã có phiên bản. Nếu phản hồi sẽ giống nhau, máy chủ chỉ phản hồi với trạng thái 304 - Không được sửa đổi và không gửi lại tài nguyên.

Từ tài liệu yêu cầu có điều kiện MDN

# 8: Giới hạn tỷ lệ ôm

Giới hạn tỷ lệ được sử dụng để kiểm soát số lượng yêu cầu mà người tiêu dùng có thể gửi tới API.

Để cho người dùng API biết bạn còn bao nhiêu yêu cầu, hãy đặt các tiêu đề sau:

  • Giới hạn X-Rate-Giới hạn, số lượng yêu cầu được phép trong một khoảng thời gian nhất định
  • X-Rate-Giới hạn-Còn lại, số lượng yêu cầu còn lại trong cùng khoảng thời gian,
  • X-Rate-Giới hạn-Đặt lại, thời gian giới hạn tốc độ sẽ được đặt lại.

Hầu hết các khung HTTP hỗ trợ nó ra khỏi hộp (hoặc với các plugin). Ví dụ: nếu bạn đang sử dụng Koa, có gói koa-rat006it.

Lưu ý rằng cửa sổ thời gian có thể thay đổi dựa trên các nhà cung cấp API khác nhau - ví dụ: GitHub sử dụng một giờ cho việc đó, trong khi Twitter 15 phút.

# 9: Tạo Tài liệu API phù hợp

Bạn viết API để người khác có thể sử dụng chúng, được hưởng lợi từ chúng. Việc cung cấp tài liệu API cho API REST của Node.js là rất quan trọng.

Các dự án nguồn mở sau đây có thể giúp bạn tạo tài liệu cho API của mình:

  • API kế hoạch chi tiết
  • Đi vênh vang

Ngoài ra, nếu bạn muốn sử dụng một sản phẩm được lưu trữ, bạn có thể truy cập Aparies.

# 10: Don mệnh Hoa hậu Tương lai của API

Trong những năm qua, hai ngôn ngữ truy vấn chính cho API đã phát sinh - đó là GraphQL từ Facebook và Falcor từ Netflix. Nhưng tại sao chúng ta thậm chí cần chúng?

Hãy tưởng tượng yêu cầu tài nguyên RESTful sau đây:

/ org / 1 / space / 2 / docs / 1 / cộng tác viên?
bao gồm = email & trang = 1 & giới hạn = 10

Điều này có thể vượt khỏi tầm tay khá dễ dàng - vì bạn muốn nhận được cùng một định dạng phản hồi cho tất cả các mô hình của mình. Đây là nơi mà GraphQL và Falcor có thể giúp đỡ.

Giới thiệu về GraphQL

GraphQL là ngôn ngữ truy vấn cho API và thời gian chạy để thực hiện các truy vấn đó với dữ liệu hiện có của bạn. GraphQL cung cấp mô tả đầy đủ và dễ hiểu về dữ liệu trong API của bạn, cung cấp cho khách hàng khả năng yêu cầu chính xác những gì họ cần và không có gì nữa, giúp phát triển API dễ dàng hơn theo thời gian và cho phép các công cụ phát triển mạnh mẽ. - Đọc thêm tại đây.

Về Falcor

Falcor là nền tảng dữ liệu sáng tạo cung cấp năng lượng cho các UI của Netflix. Falcor cho phép bạn mô hình hóa tất cả dữ liệu phụ trợ của mình dưới dạng một đối tượng JSON ảo duy nhất trên máy chủ Node của bạn. Trên máy khách, bạn làm việc với đối tượng JSON từ xa bằng các thao tác JavaScript quen thuộc như get, set và call. Nếu bạn biết dữ liệu của mình, bạn sẽ biết API của mình. - Đọc thêm tại đây.

API REST tuyệt vời cho cảm hứng

Nếu bạn sắp bắt đầu phát triển API Node.js hoặc tạo phiên bản mới của phiên bản cũ hơn, chúng tôi đã thu thập bốn ví dụ thực tế đáng để kiểm tra:

  • API GitHub
  • API Twilio
  • API sọc
  • API DigitalOcean

Tôi hy vọng rằng bây giờ bạn đã hiểu rõ hơn về cách viết API nên sử dụng Node.js. Xin vui lòng cho tôi biết trong các ý kiến ​​nếu bạn bỏ lỡ bất cứ điều gì!

Được xuất bản lần đầu tại blog.risingstack.com vào ngày 21 tháng 2 năm 2017.