Hướng dẫn

Cách xây dựng REST API: thiết kế, bảo mật và triển khai

Để xây dựng REST API, hãy liệt kê các tài nguyên mà ứng dụng quản lý (người dùng, đơn hàng, lịch đặt), gán cho mỗi tài nguyên một URL như /orders và /orders/{id}, rồi dùng phương thức HTTP cho các thao tác: GET để đọc, POST để tạo mới, PATCH để cập nhật, DELETE để xóa. Trả về JSON với các mã trạng thái có ý nghĩa, kiểm tra mọi dữ liệu đầu vào, yêu cầu xác thực và kiểm tra quyền truy cập từng bản ghi trên máy chủ, và phân trang các danh sách. Sau đó hãy viết tài liệu cho các endpoint và triển khai API phía sau HTTPS.

Hướng dẫn này đề cập đến các quyết định thiết kế, một bộ đường dẫn mẫu, prompt cho công cụ xây dựng ứng dụng bằng AI, và những lỗi thường gây ra lỗ hổng bảo mật. Nếu API còn mới với bạn, hãy bắt đầu với API là gì.

Khi nào bạn cần REST API

  • Giao diện web cần lưu và tải dữ liệu từ máy chủ
  • Ứng dụng di động, đối tác hoặc công cụ tự động hóa cần truy cập dữ liệu của bạn
  • Các dịch vụ khác gửi sự kiện đến bạn (webhook)
  • Bạn đang chia việc giữa đội frontend và đội backend

REST là kiểu phổ biến nhất nhưng không phải kiểu duy nhất. REST và GraphQL giải thích khi nào một endpoint truy vấn linh hoạt duy nhất phù hợp hơn.

Thiết kế trước: tài nguyên và đường dẫn

Hãy viết ra các danh từ trong ứng dụng và những việc người dùng làm với chúng. Với một ứng dụng đặt lịch đơn giản:

Phương thứcĐường dẫnChức năngMã thành công
GET/api/bookingsLiệt kê lịch đặt của người gọi (có phân trang)200
POST/api/bookingsTạo lịch đặt201
GET/api/bookings/{id}Lấy một lịch đặt200
PATCH/api/bookings/{id}Thay đổi một số trường200
DELETE/api/bookings/{id}Hủy lịch đặt204
GET/api/healthKiểm tra tình trạng cho hệ thống giám sát200

Các thao tác này tương ứng với tạo, đọc, cập nhật và xóa; xem CRUD là gì. Một số quy ước nên tuân theo:

  • Danh từ số nhiều, không dùng động từ trong URL: /bookings, không phải /getBookings.
  • Chỉ lồng một cấp khi điều đó làm rõ quyền sở hữu: /bookings/{id}/notes.
  • Các hành động không thuộc CRUD có thể là tài nguyên con: POST /bookings/{id}/cancel rõ ràng hơn một PATCH "thần kỳ".
  • Đặt tên nhất quán cho các trường, chẳng hạn created_at ở mọi nơi.

Mã trạng thái và lỗi

Hãy dùng các mã HTTP chuẩn để client biết chuyện gì đã xảy ra mà không cần phân tích văn bản:

MãÝ nghĩaDùng khi
200OKĐọc hoặc cập nhật thành công
201CreatedMột yêu cầu POST đã tạo ra thứ gì đó
204No ContentThành công và không có gì để trả về
400Bad RequestDữ liệu đầu vào không qua kiểm tra
401UnauthorizedChưa đăng nhập hoặc token không hợp lệ
403ForbiddenĐã đăng nhập nhưng không có quyền
404Not FoundKhông tồn tại, hoặc người gọi không được biết nó tồn tại
409ConflictTrùng lặp, hoặc khung giờ đã được đặt
429Too Many RequestsĐã vượt giới hạn số lượt yêu cầu
500Server ErrorCó lỗi xảy ra ở phía bạn

Trả về lỗi theo một cấu trúc JSON nhất quán, ví dụ {"error": {"code": "slot_taken", "message": "Khung giờ đó không còn trống."}}, và tuyệt đối không đưa stack trace hay lỗi cơ sở dữ liệu vào phản hồi.

Lựa chọn và đánh đổi

Quyết địnhLựa chọn đơn giảnPhương án thay thế
API nằm ở đâuAPI route trong framework web của bạnMột dịch vụ API riêng, hữu ích khi có nhiều client hoặc cần ngôn ngữ khác
Xác thựcCookie phiên cho ứng dụng web của bạnToken (bearer token hoặc API key) cho ứng dụng di động và bên thứ ba
Phân trang?page=2&limit=20Dựa trên con trỏ (?after=...), ổn định hơn với danh sách lớn, thay đổi liên tục
Phiên bảnKhông có cho đến khi có người dùng bên ngoài/v1/ trong đường dẫn khi đã có người khác phụ thuộc vào nó
Tài liệuMột README liệt kê các đường dẫnĐặc tả OpenAPI, từ đó các công cụ có thể tạo tài liệu tương tác và mã client

Từng bước

  1. Liệt kê tài nguyên và đường dẫn như trên, bao gồm ai được gọi từng đường dẫn.
  2. Mô hình hóa dữ liệu trong cơ sở dữ liệu với các trường và quan hệ bạn cần.
  3. Xây dựng các đường dẫn đọc trước, sau đó đến tạo, cập nhật và xóa.
  4. Kiểm tra dữ liệu đầu vào ở mọi thao tác ghi bằng một thư viện schema: trường bắt buộc, kiểu dữ liệu, độ dài, giá trị cho phép. Từ chối các trường không xác định.
  5. Thêm xác thực, rồi đến phân quyền theo từng bản ghi: tải /bookings/42 phải kiểm tra rằng lịch đặt 42 thuộc về người gọi, không chỉ kiểm tra rằng ai đó đã đăng nhập.
  6. Phân trang mọi danh sách và giới hạn kích thước trang tối đa.
  7. Giới hạn số lượt yêu cầu cho đăng nhập và các đường dẫn tốn tài nguyên. Xem giới hạn tần suất (rate limiting).
  8. Cấu hình CORS chỉ khi trình duyệt trên các tên miền khác phải gọi API, và liệt kê rõ các origin đó. Cách sửa lỗi CORS giải thích những lỗi bạn sẽ gặp.
  9. Viết tài liệu và kiểm thử cho từng đường dẫn, bao gồm cả các trường hợp lỗi.
  10. Triển khai với khóa bí mật trong biến môi trường, HTTPS, nhật ký và kiểm tra tình trạng.

Prompt cho công cụ xây dựng bằng AI

Tạo khung ban đầu:

Tạo một REST API cho lịch đặt với các đường dẫn sau: GET /api/health, GET /api/bookings (có phân trang, tối đa 50 mục mỗi trang), POST /api/bookings, GET /api/bookings/:id, PATCH /api/bookings/:id, DELETE /api/bookings/:id. Lưu dữ liệu trong cơ sở dữ liệu của chúng tôi. Kiểm tra thân yêu cầu bằng một thư viện schema và từ chối các trường không xác định. Trả về lỗi dạng JSON theo cấu trúc {"error": {"code", "message"}} với mã trạng thái đúng (400, 401, 403, 404, 409). Lưu các khóa bí mật trong biến môi trường.

Bảo mật:

Yêu cầu đăng nhập trên mọi đường dẫn của lịch đặt. Ở mọi thao tác đọc, cập nhật và xóa, kiểm tra trên máy chủ rằng lịch đặt thuộc về người dùng hiện tại; trả về 404 nếu không. Không bao giờ chấp nhận ID người dùng hay vai trò từ thân yêu cầu. Giới hạn POST /api/bookings ở 20 lần mỗi phút cho mỗi người dùng. Ghi lỗi vào nhật ký trên máy chủ mà không trả về stack trace.

Tài liệu:

Viết mô tả OpenAPI cho các đường dẫn này, và một README ngắn với ví dụ yêu cầu và phản hồi cho từng đường dẫn.

Kiểm thử API

Hãy kiểm thử từ bên ngoài frontend, vì kẻ tấn công cũng sẽ làm vậy:

  • Mỗi đường dẫn hoạt động với dữ liệu hợp lệ và trả về đúng cấu trúc và mã đã được tài liệu hóa
  • Thiếu hoặc sai trường dữ liệu trả về 400 kèm thông báo rõ ràng
  • Không có token trả về 401 ở mọi đường dẫn được bảo vệ
  • Người dùng A yêu cầu bản ghi của người dùng B theo ID nhận về 404 hoặc 403
  • Danh sách được phân trang; giá trị limit quá lớn bị giới hạn
  • Các yêu cầu tạo trùng lặp hoặc xung đột trả về 409, không phải 500
  • Vượt giới hạn tần suất trả về 429
  • Phản hồi lỗi không chứa stack trace, câu lệnh SQL hay khóa bí mật
  • CORS chỉ cho phép các origin bạn chủ đích

Các lỗi thường gặp

  • Kiểm tra đăng nhập nhưng không kiểm tra quyền sở hữu. Đây là lỗ hổng API phổ biến nhất: bất kỳ người dùng đã đăng nhập nào cũng có thể đọc mọi bản ghi chỉ bằng cách đổi ID.
  • Tin tưởng client. Giá, vai trò và ID người dùng trong thân yêu cầu đều có thể bị chỉnh sửa.
  • Trả về nguyên các dòng cơ sở dữ liệu. Mã băm mật khẩu và các trường nội bộ bị rò rỉ. Hãy chọn những gì mỗi phản hồi bao gồm.
  • Danh sách không giới hạn. Một yêu cầu lấy toàn bộ bản ghi có thể làm chậm cả ứng dụng.
  • 200 OK kèm thông báo lỗi bên trong. Client và hệ thống giám sát không thể biết là đã thất bại.
  • CORS cho phép tất cả trên một API dùng cookie.
  • Không có kiểm tra tình trạng hay nhật ký, nên bạn chỉ biết có sự cố khi người dùng báo lại.

Để rà soát rộng hơn trước khi ra mắt, xem danh sách kiểm tra bảo mật cho ứng dụng xây dựng bằng AI.

Xây dựng REST API trên Mythex

Bạn có thể yêu cầu Mythex tạo một API như một phần của ứng dụng hoặc như một dịch vụ riêng. Công thức tài liệu REST API backend có một prompt khởi đầu: nêu rõ framework và các đường dẫn, yêu cầu lỗi JSON rõ ràng, lưu khóa bí mật trong biến môi trường, và kèm một Dockerfile. Các backend container viết bằng Node, Python, C#, Java và các ngôn ngữ khác được xuất bản qua Dockerfile, và Mythex xử lý việc triển khai từ Publish (API backend). Một dự án có thể chạy đồng thời một website và một máy chủ API, và bạn có thể chuyển đổi giữa chúng trong bản xem trước. Lưu khóa dưới dạng bí mật của dự án; nếu API cần cơ sở dữ liệu, hãy yêu cầu trong chat. Với các tác vụ định kỳ quanh API, xem cách chạy tác vụ nền.

Câu hỏi thường gặp

REST API là gì?

REST API là cách để các chương trình làm việc với dữ liệu của ứng dụng bạn qua HTTP. Mỗi loại dữ liệu là một tài nguyên có URL riêng, chẳng hạn /orders, và các phương thức chuẩn tác động lên nó: GET để đọc, POST để tạo mới, PATCH hoặc PUT để cập nhật, và DELETE để xóa. Dữ liệu thường được gửi dưới dạng JSON.

Tôi nên xây dựng REST API bằng ngôn ngữ nào?

Hãy dùng ngôn ngữ mà bạn hoặc đội của bạn có thể bảo trì. Node.js với Express hoặc Fastify, Python với FastAPI, và các framework C# hay Java đều hoạt động tốt. Các quy tắc thiết kế cho đường dẫn, mã trạng thái, kiểm tra dữ liệu và xác thực quan trọng hơn ngôn ngữ.

Làm sao để bảo mật REST API?

Yêu cầu xác thực trên mọi đường dẫn không công khai, kiểm tra trên máy chủ rằng người gọi được phép truy cập từng bản ghi cụ thể, kiểm tra toàn bộ dữ liệu đầu vào, dùng HTTPS, giới hạn số lượt yêu cầu, và lưu các khóa bí mật trong biến môi trường. Không bao giờ tin các ID hay vai trò do phía client gửi lên.

Có cần một backend riêng cho REST API không?

Không nhất thiết. Các framework như Next.js có thể phục vụ API route cùng với các trang. Dịch vụ API riêng sẽ hợp lý khi nhiều client (web, di động, đối tác) cùng dùng, hoặc khi API cần ngôn ngữ hay khả năng mở rộng riêng.

Mythex · Pricing · Xây dựng mọi thứ với AI · Mẫu website và ứng dụng · So sánh Mythex · Thuật ngữ xây dựng ứng dụng bằng AI · Công cụ miễn phí để xây dựng ứng dụng bằng AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو 简体中文 繁體中文(香港) 繁體中文(台灣)