Tóm tắt
API REST nên sử dụng mã trạng thái HTTP một cách chính xác: 200 cho GET thành công, 201 cho POST thành công khi tạo tài nguyên, 204 cho DELETE thành công, 400 cho lỗi phía máy khách, 401 cho lỗi xác thực, 404 cho không tìm thấy tài nguyên và 500 cho lỗi phía máy chủ. Modern PetstoreAPI triển khai tất cả các mã trạng thái HTTP tiêu chuẩn với ngữ nghĩa phù hợp và phản hồi lỗi theo RFC 9457.
Giới thiệu
API của bạn trả về 200 OK cho mọi thứ. Thành công? 200 OK. Lỗi xác thực? 200 OK với một thông báo lỗi trong phần thân phản hồi. Không tìm thấy tài nguyên? 200 OK với {"error": "not found"}. Lỗi xác thực? Bạn đoán đúng rồi—200 OK.
Điều này là sai. Mã trạng thái HTTP tồn tại vì một lý do. Chúng cho máy khách biết điều gì đã xảy ra mà không cần phân tích cú pháp phần thân phản hồi. Bộ nhớ đệm, proxy và các công cụ giám sát đều dựa vào mã trạng thái. Khi bạn trả về 200 cho các lỗi, bạn phá vỡ toàn bộ hệ sinh thái HTTP.
Swagger Petstore cũ đã mắc lỗi về mã trạng thái: trả về 200 cho các yêu cầu POST lẽ ra phải trả về 201, sử dụng 200 cho các thao tác DELETE lẽ ra phải trả về 204 và thiếu các mã lỗi quan trọng. Modern PetstoreAPI khắc phục điều này bằng cách triển khai ngữ nghĩa HTTP phù hợp trên tất cả các điểm cuối.
Trong hướng dẫn này, bạn sẽ tìm hiểu các mã trạng thái HTTP nào quan trọng đối với API REST, khi nào nên sử dụng từng mã và cách Modern PetstoreAPI triển khai chúng một cách chính xác.
Vấn đề về Mã trạng thái
Nhiều API coi mã trạng thái là một điều thứ yếu. Kết quả: ngữ nghĩa HTTP bị phá vỡ và máy khách bị bối rối.
Chống mẫu “200 OK cho mọi thứ”
// Thành công
GET /users/123
200 OK
{"id": 123, "name": "John"}
// Lỗi (nhưng vẫn là 200!)
GET /users/999
200 OK
{"error": "User not found"}
// Lỗi xác thực (vẫn là 200!)
POST /users
200 OK
{"error": "Email is required"}
Các vấn đề:
- Máy khách không thể phân biệt thành công với thất bại mà không phân tích cú pháp phần thân phản hồi
- Bộ nhớ đệm HTTP lưu trữ phản hồi lỗi
- Các công cụ giám sát báo cáo sai dương tính
- Logic thử lại không hoạt động chính xác
Tại sao điều này xảy ra
Các nhà phát triển trả về 200 vì:
- Họ không biết các mã trạng thái khác
- Họ nghĩ mã trạng thái là tùy chọn
- Họ muốn tránh “phá vỡ” máy khách
- Họ đang sao chép những ví dụ tồi (như Swagger Petstore cũ)
Các Mã trạng thái HTTP Thiết yếu cho API REST
Bạn không cần tất cả hơn 60 mã trạng thái HTTP. Hãy tập trung vào những mã thiết yếu này.
Tham khảo nhanh
Thành công (2xx):
- 200 OK - GET, PUT, PATCH thành công
- 201 Created - POST thành công khi tạo tài nguyên
- 204 No Content - DELETE, PUT thành công mà không có phần thân phản hồi
Lỗi phía máy khách (4xx):
- 400 Bad Request - Định dạng yêu cầu không hợp lệ hoặc lỗi xác thực
- 401 Unauthorized - Thiếu hoặc không hợp lệ thông tin xác thực
- 403 Forbidden - Đã xác thực nhưng không được ủy quyền
- 404 Not Found - Tài nguyên không tồn tại
- 409 Conflict - Xung đột tài nguyên (trùng lặp, không khớp phiên bản)
- 422 Unprocessable Entity - Định dạng hợp lệ nhưng lỗi ngữ nghĩa
- 429 Too Many Requests - Vượt quá giới hạn tốc độ
Lỗi phía máy chủ (5xx):
- 500 Internal Server Error - Lỗi máy chủ không mong muốn
- 502 Bad Gateway - Lỗi dịch vụ thượng nguồn
- 503 Service Unavailable - Không khả dụng tạm thời
- 504 Gateway Timeout - Thời gian chờ của cổng thượng nguồn
Mã Thành công (2xx)
Mã thành công cho biết yêu cầu đã thành công. Các mã khác nhau truyền tải các ý nghĩa khác nhau.
200 OK
Sử dụng cho: Các yêu cầu GET, PUT, PATCH thành công trả về dữ liệu.
GET /pets/123
200 OK
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT"
}
Không sử dụng cho: Yêu cầu POST tạo tài nguyên (sử dụng 201), yêu cầu DELETE (sử dụng 204).
201 Created
Sử dụng cho: Các yêu cầu POST thành công tạo một tài nguyên mới.
POST /pets
201 Created
Location: https://petstoreapi.com/pets/019b4132-70aa-764f-b315-e2803d882a24
{
"id": "019b4132-70aa-764f-b315-e2803d882a24",
"name": "Fluffy",
"species": "CAT"
}
Các điểm chính:
- Bao gồm tiêu đề
Locationvới URL tài nguyên mới - Trả về tài nguyên đã tạo trong phần thân phản hồi
- Máy khách biết rằng một tài nguyên đã được tạo, không chỉ được cập nhật
Modern PetstoreAPI trả về 201 cho tất cả các thao tác POST tạo tài nguyên.
204 No Content
Sử dụng cho: Các yêu cầu DELETE, PUT hoặc PATCH thành công mà không có phần thân phản hồi.
DELETE /pets/019b4132-70aa-764f-b315-e2803d882a24
204 No Content
Các điểm chính:
- Không có phần thân phản hồi (tiết kiệm băng thông)
- Cho biết thành công
- Thường dùng cho các thao tác DELETE
Mã lỗi phía máy khách (4xx)
Mã lỗi phía máy khách cho biết máy khách đã mắc lỗi. Yêu cầu không nên được thử lại mà không có sửa đổi.
400 Bad Request
Sử dụng cho: Các yêu cầu bị định dạng sai, JSON không hợp lệ, thiếu các trường bắt buộc.
POST /pets
400 Bad Request
Content-Type: application/problem+json
{
"type": "https://petstoreapi.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Request validation failed",
"invalid-params": [
{
"name": "name",
"reason": "Name is required"
}
]
}
Modern PetstoreAPI sử dụng định dạng RFC 9457 cho tất cả các phản hồi lỗi.
401 Unauthorized
Sử dụng cho: Thiếu hoặc không hợp lệ thông tin xác thực.
GET /pets
401 Unauthorized
WWW-Authenticate: Bearer realm="PetstoreAPI"
{
"type": "https://petstoreapi.com/errors/authentication-required",
"title": "Authentication Required",
"status": 401,
"detail": "Valid authentication credentials required"
}
Các điểm chính:
- Bao gồm tiêu đề
WWW-Authenticate - Máy khách nên yêu cầu thông tin xác thực hoặc làm mới token
- Đừng nhầm lẫn với 403 (ủy quyền)
403 Forbidden
Sử dụng cho: Người dùng đã xác thực nhưng thiếu quyền.
DELETE /pets/019b4132-70aa-764f-b315-e2803d882a24
403 Forbidden
{
"type": "https://petstoreapi.com/errors/insufficient-permissions",
"title": "Insufficient Permissions",
"status": 403,
"detail": "You don't have permission to delete this pet"
}
Khác biệt với 401:
- 401: “Bạn là ai?” (xác thực)
- 403: “Tôi biết bạn là ai, nhưng bạn không thể làm điều đó” (ủy quyền)
404 Not Found
Sử dụng cho: Tài nguyên không tồn tại.
GET /pets/nonexistent-id
404 Not Found
{
"type": "https://petstoreapi.com/errors/not-found",
"title": "Not Found",
"status": 404,
"detail": "Pet not found"
}
Không sử dụng cho: Lỗi ủy quyền (sử dụng 403), lỗi xác thực (sử dụng 400).
409 Conflict
Sử dụng cho: Xung đột tài nguyên như trùng lặp hoặc không khớp phiên bản.
POST /pets
409 Conflict
{
"type": "https://petstoreapi.com/errors/duplicate-resource",
"title": "Duplicate Resource",
"status": 409,
"detail": "A pet with this microchip ID already exists"
}
422 Unprocessable Entity
Sử dụng cho: Định dạng yêu cầu hợp lệ nhưng lỗi ngữ nghĩa.
POST /pets
422 Unprocessable Entity
{
"type": "https://petstoreapi.com/errors/business-rule-violation",
"title": "Business Rule Violation",
"status": 422,
"detail": "Cannot adopt more than 5 pets per household"
}
Khác biệt với 400:
- 400: Yêu cầu bị định dạng sai (JSON không hợp lệ, kiểu dữ liệu sai)
- 422: Yêu cầu định dạng đúng nhưng vi phạm quy tắc nghiệp vụ
429 Too Many Requests
Sử dụng cho: Vượt quá giới hạn tốc độ.
GET /pets
429 Too Many Requests
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 1678886400
{
"type": "https://petstoreapi.com/errors/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Rate limit of 100 requests per hour exceeded"
}
Modern PetstoreAPI sử dụng tiêu đề giới hạn tốc độ IETF.
Mã lỗi phía máy chủ (5xx)
Mã lỗi phía máy chủ cho biết máy chủ đã gặp lỗi. Máy khách có thể thử lại các yêu cầu này.
500 Internal Server Error
Sử dụng cho: Lỗi máy chủ không mong muốn.
GET /pets
500 Internal Server Error
{
"type": "https://petstoreapi.com/errors/internal-error",
"title": "Internal Server Error",
"status": 500,
"detail": "An unexpected error occurred"
}
Không bao gồm: Dấu vết ngăn xếp (stack traces), chi tiết nội bộ, lỗi cơ sở dữ liệu trong môi trường sản xuất.
503 Service Unavailable
Sử dụng cho: Không khả dụng tạm thời (bảo trì, quá tải).
GET /pets
503 Service Unavailable
Retry-After: 3600
{
"type": "https://petstoreapi.com/errors/service-unavailable",
"title": "Service Unavailable",
"status": 503,
"detail": "Service temporarily unavailable for maintenance"
}
Bao gồm tiêu đề Retry-After để cho máy khách biết khi nào có thể thử lại.
Cách Modern PetstoreAPI sử dụng mã trạng thái
Modern PetstoreAPI triển khai ngữ nghĩa HTTP phù hợp trên tất cả các điểm cuối.
Ví dụ: Quản lý thú cưng
// Liệt kê thú cưng
GET /pets
200 OK
// Tạo thú cưng
POST /pets
201 Created
Location: https://petstoreapi.com/pets/{id}
// Lấy thú cưng
GET /pets/{id}
200 OK (tìm thấy) hoặc 404 Not Found
// Cập nhật thú cưng
PUT /pets/{id}
200 OK (có phần thân) hoặc 204 No Content
// Xóa thú cưng
DELETE /pets/{id}
204 No Content (thành công) hoặc 404 Not Found
Phản hồi lỗi
Tất cả các lỗi đều sử dụng định dạng RFC 9457:
{
"type": "https://petstoreapi.com/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Request validation failed",
"instance": "/pets",
"invalid-params": [
{
"name": "name",
"reason": "Name must be between 1 and 100 characters"
}
]
}
Xem tài liệu xử lý lỗi của Modern PetstoreAPI để biết các ví dụ đầy đủ.
Kiểm tra Mã trạng thái với Apidog
Apidog giúp bạn kiểm tra hành vi mã trạng thái trong tất cả các trường hợp.
Xác định các Mã trạng thái mong muốn
paths:
/pets:
post:
responses:
'201':
description: Pet created (Thú cưng đã được tạo)
'400':
description: Validation error (Lỗi xác thực)
'401':
description: Authentication required (Yêu cầu xác thực)
'429':
description: Rate limit exceeded (Vượt quá giới hạn tốc độ)
Kiểm tra tất cả các trường hợp
Tạo các trường hợp kiểm thử cho:
- Các kịch bản thành công (200, 201, 204)
- Lỗi xác thực (400, 422)
- Xác thực/ủy quyền (401, 403)
- Không tìm thấy (404)
- Giới hạn tốc độ (429)
- Lỗi máy chủ (500, 503)
Kiểm tra tự động
// Kịch bản kiểm thử Apidog
pm.test("Returns 201 for successful creation (Trả về 201 cho việc tạo thành công)", () => {
pm.response.to.have.status(201);
pm.response.to.have.header("Location");
});
pm.test("Returns 400 for missing required fields (Trả về 400 khi thiếu các trường bắt buộc)", () => {
pm.response.to.have.status(400);
pm.expect(pm.response.json().type).to.include("validation-error");
});
Những sai lầm phổ biến cần tránh
Sai lầm 1: Sử dụng 200 cho POST
// Sai
POST /pets
200 OK
// Đúng
POST /pets
201 Created
Location: https://petstoreapi.com/pets/{id}
Sai lầm 2: Sử dụng 200 cho DELETE
// Sai
DELETE /pets/{id}
200 OK
{"message": "Deleted successfully"}
// Đúng
DELETE /pets/{id}
204 No Content
Sai lầm 3: Nhầm lẫn giữa 401 và 403
// Sai: Người dùng đã xác thực nhưng thiếu quyền
401 Unauthorized
// Đúng
403 Forbidden
Sai lầm 4: Sử dụng 500 cho Lỗi phía máy khách
// Sai: Lỗi xác thực trả về 500
POST /pets
500 Internal Server Error
// Đúng
POST /pets
400 Bad Request
Kết luận
Mã trạng thái HTTP không phải là tùy chọn. Chúng là một phần của đặc tả HTTP và cần thiết để xây dựng các API REST đúng đắn.
Sử dụng các mã trạng thái phù hợp:
- 200 cho việc đọc thành công
- 201 cho việc tạo thành công
- 204 cho việc xóa thành công
- 400 cho lỗi phía máy khách
- 401 cho xác thực
- 404 cho không tìm thấy tài nguyên
- 500 cho lỗi phía máy chủ
Modern PetstoreAPI minh họa việc sử dụng mã trạng thái chính xác trên tất cả các điểm cuối. Hãy nghiên cứu tài liệu API REST để xem cách triển khai phù hợp.
Kiểm tra mã trạng thái của bạn với Apidog để đảm bảo API của bạn tuân thủ các tiêu chuẩn HTTP.
Câu hỏi thường gặp
Tôi nên sử dụng 200 hay 204 cho DELETE thành công?
Sử dụng 204 No Content. Nó cho biết thành công mà không có phần thân phản hồi, giúp tiết kiệm băng thông. Chỉ sử dụng 200 nếu bạn cần trả về thông tin về tài nguyên đã xóa.
Sự khác biệt giữa 400 và 422 là gì?
400 có nghĩa là yêu cầu bị định dạng sai (JSON không hợp lệ, kiểu dữ liệu sai). 422 có nghĩa là yêu cầu định dạng đúng nhưng vi phạm quy tắc nghiệp vụ.
Khi nào tôi nên sử dụng 401 so với 403?
401 có nghĩa là “hãy xác thực chính bạn” (thiếu hoặc không hợp lệ thông tin xác thực). 403 có nghĩa là “bạn đã được xác thực nhưng không được ủy quyền” (thiếu quyền).
Tôi có nên trả về 404 hay 403 cho các tài nguyên mà người dùng không thể truy cập không?
Trả về 403 nếu tài nguyên tồn tại nhưng người dùng thiếu quyền. Trả về 404 nếu bạn muốn ẩn sự tồn tại của tài nguyên khỏi người dùng không được ủy quyền.
Làm cách nào để kiểm tra tất cả các kịch bản mã trạng thái?
Sử dụng Apidog để tạo các trường hợp kiểm thử cho các trường hợp thành công, lỗi xác thực, lỗi xác thực, không tìm thấy và lỗi máy chủ. Chạy các kiểm thử tự động trong CI/CD.
Mã trạng thái nào cho giới hạn tốc độ?
Sử dụng 429 Too Many Requests với các tiêu đề RateLimit-*. Bao gồm Retry-After để cho máy khách biết khi nào họ có thể thử lại.
Tôi có nên sử dụng 500 cho tất cả các lỗi máy chủ không?
Sử dụng 500 cho các lỗi không mong muốn. Sử dụng 502 cho lỗi dịch vụ thượng nguồn, 503 cho không khả dụng tạm thời và 504 cho thời gian chờ.
Modern PetstoreAPI xử lý lỗi như thế nào?
Tất cả các lỗi đều sử dụng định dạng RFC 9457 với các mã trạng thái phù hợp. Xem tài liệu xử lý lỗi để biết các ví dụ.
