Mã trạng thái HTTP: dùng đúng 200, 201, 400, 401, 403, 404, 422, 500

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Mã trạng thái là cách đầu tiên và ngắn nhất để server nói với client chuyện gì đã xảy ra. Dùng đúng mã giúp ứng dụng khách xử lý chính xác, công cụ giám sát hiển thị có nghĩa, và đồng đội đọc log dễ hơn. Dùng sai (nhất là trả 200 cho mọi thứ) là nguồn gây rối quen thuộc.

Năm nhóm mã

  • 1xx: thông tin, hiếm khi bạn phải xử lý trực tiếp.
  • 2xx: thành công.
  • 3xx: chuyển hướng.
  • 4xx: lỗi do phía client (yêu cầu sai, chưa xác thực, không có quyền...).
  • 5xx: lỗi do phía server.

Chỉ riêng việc phân biệt 4xx (lỗi của người gọi) và 5xx (lỗi của chúng ta) đã giúp rất nhiều khi điều tra sự cố và đặt cảnh báo.

Nhóm 2xx thường dùng

  • 200 OK: yêu cầu thành công, có nội dung trả về.
  • 201 Created: tạo thành công tài nguyên mới; nên kèm header Location trỏ tới tài nguyên đó.
  • 202 Accepted: đã nhận yêu cầu nhưng xử lý nền, chưa xong.
  • 204 No Content: thành công và không có nội dung, thường dùng cho xóa hoặc cập nhật không trả dữ liệu.

Nhóm 3xx: chuyển hướng

301 chuyển hướng vĩnh viễn (tốt cho SEO khi đổi địa chỉ), 302 và 307 chuyển hướng tạm thời, 304 Not Modified báo nội dung chưa đổi để trình duyệt dùng bản cache. Với API thuần túy, bạn hiếm khi dùng ngoài 304.

Nhóm 4xx: lỗi của client

  • 400 Bad Request: yêu cầu sai cú pháp hoặc không hiểu được, như JSON hỏng.
  • 401 Unauthorized: chưa xác thực hoặc token không hợp lệ. Dù tên nói "unauthorized", ý nghĩa thực tế là "bạn là ai?".
  • 403 Forbidden: đã biết bạn là ai nhưng bạn không có quyền.
  • 404 Not Found: không tìm thấy tài nguyên.
  • 405 Method Not Allowed: đường dẫn có nhưng không hỗ trợ phương thức này.
  • 409 Conflict: xung đột trạng thái, ví dụ tạo bản ghi trùng giá trị duy nhất.
  • 422 Unprocessable Content: cú pháp đúng nhưng dữ liệu không hợp lệ về nghiệp vụ; nhiều framework dùng cho lỗi validation.
  • 429 Too Many Requests: vượt giới hạn tần suất, nên kèm header Retry-After.

Cặp 401 và 403 hay bị nhầm nhất. Cách nhớ: 401 là chưa đăng nhập, 403 là đã đăng nhập nhưng không được phép. Một điểm tinh tế về bảo mật: để tránh lộ việc một tài nguyên có tồn tại, đôi khi người ta trả 404 thay vì 403 cho tài nguyên không thuộc về người gọi.

Nhóm 5xx: lỗi của server

  • 500 Internal Server Error: lỗi không lường trước trong code.
  • 502 Bad Gateway: máy chủ trung gian (như proxy) nhận phản hồi lỗi từ máy chủ phía sau.
  • 503 Service Unavailable: dịch vụ tạm thời không sẵn sàng, như đang bảo trì hoặc quá tải.
  • 504 Gateway Timeout: máy chủ phía sau trả lời quá chậm.

Với 5xx, đừng trả chi tiết nội bộ cho người dùng. Hãy ghi log đầy đủ và trả thông điệp chung kèm một mã tham chiếu để tra cứu.

Ví dụ trong code

// Expressapp.post('/users', async (req, res) => {  if (!req.body.email) {    return res.status(422).json({ error: 'Thiếu email' });  }  const exists = await users.findByEmail(req.body.email);  if (exists) {    return res.status(409).json({ error: 'Email đã được dùng' });  }  const user = await users.create(req.body);  res.status(201).location('/users/' + user.id).json(user);});

Gợi ý kiểm tra nhanh

  1. Thành công mà có nội dung: 200. Tạo mới: 201. Không có nội dung: 204.
  2. Client gửi sai: 4xx, chọn mã cụ thể nhất có thể.
  3. Lỗi bất ngờ của ta: 500, và phải có log.
  4. Đừng bao giờ trả 200 kèm nội dung "success: false" nếu có thể dùng mã đúng.

Gắn mã trạng thái với thông điệp hữu ích

Mã trạng thái chỉ là nửa câu chuyện; nửa còn lại là nội dung giải thích. Một phản hồi 422 chỉ nói "dữ liệu không hợp lệ" thì chưa đủ, hãy kèm danh sách trường sai và lý do bằng ngôn ngữ người dùng hiểu được. Một phản hồi 500 thì ngược lại: đừng giải thích chi tiết, chỉ kèm một mã tham chiếu như request_id để người dùng báo lại và bạn tra được log. Cân bằng giữa hữu ích cho người gọi và an toàn cho hệ thống là kỹ năng nhỏ nhưng quan trọng của người viết API.

Cũng đừng quên cấu hình proxy và trình cân bằng tải: nhiều lỗi 502, 503, 504 không đến từ code của bạn mà từ tầng hạ tầng phía trước. Khi đọc log, hãy phân biệt xem mã đó do ứng dụng trả hay do nginx hoặc dịch vụ cloud sinh ra, để tìm đúng nơi cần sửa.

Kết luận

Bạn không cần thuộc hết hàng chục mã, chỉ cần nắm khoảng mười mã ở trên và dùng chúng nhất quán. Đây là một trong những cải thiện rẻ nhất mà tác động lớn nhất đến chất lượng API của bạn.

Nếu muốn luyện tập cùng bài tập thực tế, hãy ghé các khóa học tại codebem.com khi bạn sẵn sàng.

author_photo
Nguyễn Đình Cường

0 comment