286

Tôi đang cố gắng tìm ra mã trạng thái chính xác để trả về các kịch bản khác nhau với API "giống như REST" mà tôi đang làm việc. Giả sử tôi có một điểm cuối cho phép POST mua hàng ở định dạng JSON. Nó trông như thế này:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

Tôi nên trả lại những gì nếu khách hàng gửi cho tôi "sales_tax" (thay vì "thuế" dự kiến). Hiện tại, tôi đang trả lại 400. Nhưng, tôi đã bắt đầu tự đặt câu hỏi về điều này. Tôi có nên thực sự trở lại một 422? Ý tôi là, đó là JSON (được hỗ trợ) và JSON hợp lệ, nó chỉ không chứa tất cả các trường bắt buộc.

|
352

400 Yêu cầu Không hợp lệ dường như là mã trạng thái HTTP / 1.1 tốt nhất cho trường hợp sử dụng của bạn.

Tại thời điểm câu hỏi của bạn (và câu trả lời ban đầu của tôi), RFC 7231 không phải là một điều; tại thời điểm đó tôi đã phản đối 400 Bad RequestRFC 2616 đã nói (với sự nhấn mạnh của tôi):

Máy chủ không thể hiểu được yêu cầu do cú pháp không đúng .

và yêu cầu bạn mô tả là JSON hợp lệ về mặt cú pháp được bao bọc trong HTTP có hiệu lực về mặt cú pháp và do đó máy chủ không có vấn đề gì với cú pháp của yêu cầu.

Tuy nhiên, như Lee Saferite đã chỉ ra trong các bình luận , RFC 7231, đã lỗi thời RFC 2616, không bao gồm hạn chế đó :

Mã trạng thái 400 (Yêu cầu xấu) chỉ ra rằng máy chủ không thể hoặc sẽ không xử lý yêu cầu do lỗi được coi là lỗi máy khách (ví dụ: cú pháp yêu cầu không đúng định dạng, đóng khung thông báo yêu cầu không hợp lệ hoặc định tuyến yêu cầu lừa đảo).


Tuy nhiên, trước khi diễn đạt lại (hoặc nếu bạn muốn phân biệt về RFC 7231 chỉ là một tiêu chuẩn được đề xuất ngay bây giờ), 422 Unprocessable Entitydường như không phải là mã trạng thái HTTP không chính xác cho trường hợp sử dụng của bạn, bởi vì như giới thiệu về RFC 4918 nói:

Mặc dù các mã trạng thái được cung cấp bởi HTTP / 1.1 là đủ để mô tả hầu hết các điều kiện lỗi mà các phương thức WebDAV gặp phải, có một số lỗi không nằm gọn trong các danh mục hiện có. Đặc tả này xác định các mã trạng thái bổ sung được phát triển cho các phương thức WebDAV (Phần 11)

mô tả về422 nói:

Mã trạng thái 422 (Thực thể không thể xử lý) có nghĩa là máy chủ hiểu loại nội dung của thực thể yêu cầu (do đó mã trạng thái 415 (Loại phương tiện không được hỗ trợ) là không phù hợp) và cú pháp của thực thể yêu cầu là chính xác (do đó là 400 (Yêu cầu sai ) mã trạng thái không phù hợp) nhưng không thể xử lý các hướng dẫn có trong đó.

(Lưu ý tham chiếu đến cú pháp; Tôi nghi ngờ 7231 cũng bị lỗi thời 4918)

Điều này nghe chính xác giống như tình hình của bạn, nhưng chỉ trong trường hợp có bất kỳ nghi ngờ gì nữa, nó tiếp tục nói:

Ví dụ, điều kiện lỗi này có thể xảy ra nếu một thân yêu cầu XML chứa các hướng dẫn XML được định dạng đúng (nghĩa là đúng về mặt cú pháp), nhưng sai về mặt ngữ nghĩa, về mặt ngữ nghĩa.

(Thay thế "XML" bằng "JSON" và tôi nghĩ chúng ta có thể đồng ý rằng đó là tình huống của bạn)

Bây giờ, một số người sẽ phản đối rằng RFC 4918 nói về "Phần mở rộng HTTP cho tác giả và phiên bản phân tán trên web (WebDAV)" và bạn (có lẽ) không làm gì liên quan đến WebDAV vì vậy không nên sử dụng những thứ từ nó.

Đưa ra lựa chọn giữa việc sử dụng mã lỗi trong tiêu chuẩn ban đầu rõ ràng không bao gồm tình huống và một từ một phần mở rộng mô tả chính xác tình huống, tôi sẽ chọn cái sau.

Hơn nữa, RFC 4918 Mục 21.4 đề cập đến Sổ đăng ký mã trạng thái giao thức truyền siêu văn bản (HTTP) IANA , nơi có thể tìm thấy 422.

Tôi đề nghị rằng việc khách hàng hoặc máy chủ HTTP sử dụng bất kỳ mã trạng thái nào từ sổ đăng ký đó là hoàn toàn hợp lý, miễn là họ làm như vậy một cách chính xác.


Nhưng kể từ HTTP / 1.1, RFC 7231 có lực kéo, vì vậy chỉ cần sử dụng 400 Bad Request!

|
  • 1

    Pin.net sử dụng 422 để xác thực như lỗi nếu bạn gửi dữ liệu sai hoặc thiếu ngay cả với cấu trúc JSON hợp lệ. Nhưng nó cũng gửi 400 nếu việc xử lý số thẻ tín dụng không thành công, đó là không có đủ tiền trong thẻ, hoặc có một sự gian lận đáng ngờ ... vv Hơi lạ một chút, nhưng mô tả của 400 hoặc 422 don Không phù hợp với tình hình thẻ tín dụng. Hoặc có thể tất cả đều thuộc "lỗi xác nhận".

    – Tạ Di Nhiên 09:30:39 01/01/2014
  • 1

    Câu trả lời của bạn (422) có ý nghĩa với tôi. Đây cũng là những gì Rails ( respons_with ) sử dụng khi tài nguyên không thể được xử lý do lỗi xác thực.

    – Ngô Thi Xuân 16:31:05 01/04/2014
  • 1

    Lưu ý việc sử dụng 422 trong thông số không phải WebDAV tại đây: tools.ietf.org/html/rfc5789#section-2.2

    – Hoàng Hữu Khoa 02:22:16 25/11/2014
  • 1

    Cũng giống như một bản cập nhật, RFC 7231 có một mô tả khác cho mã phản hồi 400 thay đổi ngữ nghĩa.

    – Hồ Hoa Thiên 18:40:48 01/07/2015
  • 1

    Tôi xin lỗi - Tôi đã cập nhật câu trả lời này để phản ánh sự thay đổi trong RFC và mất đi một số sự rõ ràng; Tôi sẽ cố gắng tái cấu trúc. Nó gần như chắc chắn an toàn khi sử dụng 422, nhưng ngày nay bạn nên sử dụng 400.

    – Tạ Khánh Linh 14:30:36 31/03/2016
32

Để phản ánh tình trạng của năm 2015:

Về mặt hành vi, cả hai mã phản hồi 400 và 422 sẽ được khách hàng và các bên trung gian đối xử giống nhau, vì vậy nó thực sự không tạo ra sự khác biệt cụ thể mà bạn sử dụng.

Tuy nhiên, tôi hy vọng sẽ thấy 400 hiện đang được sử dụng rộng rãi hơn và hơn nữa các giải thích mà thông số HTTPbis cung cấp làm cho nó phù hợp hơn với hai mã trạng thái:

  • Thông số kỹ thuật HTTPbis làm rõ ý định 400 không chỉ dành cho các lỗi cú pháp. Cụm từ rộng hơn "chỉ ra rằng máy chủ không thể hoặc sẽ không xử lý yêu cầu do lỗi được coi là lỗi máy khách" hiện được sử dụng.
  • 422 Đặc biệt là một phần mở rộng WebDAV và không được tham chiếu trong RFC 2616 hoặc trong đặc tả HTTPbis mới hơn .

Đối với ngữ cảnh, HTTPbis là bản sửa đổi của thông số HTTP / 1.1 cố gắng làm rõ các khu vực không rõ ràng hoặc không nhất quán. Khi nó đã đạt đến trạng thái được phê duyệt, nó sẽ thay thế RFC2616.

|
  • 1

    Không phải 403 Cấm cũng có thể được sử dụng cho bối cảnh này sao? Trích dẫn: Mã trạng thái 403 (Bị cấm) chỉ ra rằng máy chủ hiểu yêu cầu nhưng từ chối ủy quyền ... Nếu thông tin xác thực được cung cấp trong yêu cầu, máy chủ cho rằng chúng không đủ để cấp quyền truy cập .... Tuy nhiên, yêu cầu có thể bị cấm vì lý do không liên quan đến thông tin đăng nhập. Vì vậy, có vẻ như 403 có thể được sử dụng để từ chối các yêu cầu bên ngoài xác thực.

    – Tạ Di Nhiên 22:19:49 24/08/2015
  • 1

    @garbagecollector lưu ý rằng "bị từ chối vì lý do bên ngoài thông tin đăng nhập "! = "bị từ chối vì lý do bên ngoài xác thực ." Có rất nhiều cách để xác thực một ai đó mà không cần sử dụng thông tin đăng nhập, cụ thể.

    – Ngô Thi Xuân 17:52:33 23/05/2017
  • 1

    @garbagecollector không, thông tin đăng nhập có nghĩa là xác thực ("bạn là ai"), sẽ là 401 khi thất bại. Ủy quyền ("bạn có thể làm gì") sẽ là 403 khi thất bại. Giải thích đầy đủ ở đây: stackoverflow.com/a/6937030/137948 Không áp dụng cho tình huống "trường bị thiếu" của OP vì lỗi sẽ giống nhau cho dù người dùng đã thử nó. Tôi đồng ý 400 là câu trả lời đúng.

    – Hoàng Hữu Khoa 15:19:20 08/08/2017
29

400 Yêu cầu xấu là mã trạng thái HTTP thích hợp cho trường hợp sử dụng của bạn. Mã được xác định bởi HTTP / 0.9-1.1 RFC.

Máy chủ không thể hiểu được yêu cầu do cú pháp không đúng. Khách hàng KHÔNG NÊN lặp lại yêu cầu mà không sửa đổi.

http://tools.ietf.org/html/rfc2616#section-10.4.1

Thực thể không thể xử lý được xác định bởi RFC 4918 - WebDav. Lưu ý rằng có một chút khác biệt so với 400, xem văn bản được trích dẫn dưới đây.

Điều kiện lỗi này có thể xảy ra nếu một thân yêu cầu XML chứa các hướng dẫn XML được định dạng đúng (nghĩa là đúng về mặt cú pháp), nhưng sai về mặt ngữ nghĩa, về mặt ngữ nghĩa.

Để giữ giao diện thống nhất, bạn chỉ nên sử dụng 422 trong trường hợp phản hồi XML và bạn cũng nên hỗ trợ tất cả các mã trạng thái được xác định bởi tiện ích mở rộng Webdav, không chỉ là 422.

http://tools.ietf.org/html/rfc4918#page-78

Xem thêm bài viết của Mark Nottingham về mã trạng thái:

thật sai lầm khi cố gắng ánh xạ từng phần trong ứng dụng của bạn sâu vào các mã trạng thái HTTP; trong hầu hết các trường hợp, mức độ chi tiết mà bạn muốn hướng tới là thô hơn nhiều. Khi nghi ngờ, bạn có thể sử dụng các mã trạng thái chung 200 OK, 400 Yêu cầu Không hợp lệ và 500 Lỗi Dịch vụ Nội bộ khi không phù hợp hơn .

Cách nghĩ về mã trạng thái HTTP

|
  • 1

    Mã 422 là một phần của sổ đăng ký IANA iana.org/assignments/http-status-codes/http-status-codes.xhtml vì vậy bất kỳ IMHO nào cũng không có ý nghĩa. Trong mọi trường hợp, API REST của Facebook và Twitter phát minh lại mã riêng và không sử dụng các tiêu chuẩn RFC / IANA. Vì vậy, bạn có thể làm.

    – Hồ Nhã Anh 08:08:25 04/07/2014
  • 1

    Phần 11 nêu cụ thể chúng được thêm vào toàn bộ thông số kỹ thuật và không chỉ trong thông số WebDav:The following status codes are added to those defined in HTTP/1.1 [RFC2616].

    – Tạ Hồng Như 10:27:14 28/07/2014
  • 1

    Chỉ vì mã được mô tả là một phần của thông số WebDAV không có nghĩa là nó dành riêng cho WebDAV! Mã trạng thái được coi là chung chung.

    – Thanh Huyền 14:22:22 31/07/2014
13

Không có câu trả lời đúng, vì nó phụ thuộc vào định nghĩa của "cú pháp" là gì đối với yêu cầu của bạn. Điều quan trọng nhất là bạn:

  1. Sử dụng (các) mã phản hồi nhất quán
  2. Bao gồm càng nhiều thông tin bổ sung trong phần phản hồi càng tốt để giúp nhà phát triển sử dụng API của bạn tìm hiểu điều gì đang xảy ra. =

Trước khi mọi người nhảy lên tôi vì nói rằng không có câu trả lời đúng hay sai ở đây, hãy để tôi giải thích một chút về cách tôi đi đến kết luận.

Trong ví dụ cụ thể này, câu hỏi của OP là về một yêu cầu JSON chứa khóa khác với dự kiến. Bây giờ, tên khóa nhận được rất giống nhau, từ quan điểm ngôn ngữ tự nhiên, đến khóa dự kiến, nhưng nó, hoàn toàn khác, và do đó không (thường) được máy nhận ra là tương đương.

Như tôi đã nói ở trên, yếu tố quyết định là cú pháp có nghĩa là gì . Nếu yêu cầu được gửi với Loại nội dung application/json, thì có, yêu cầu đó có hiệu lực về mặt cú pháp vì đó là cú pháp JSON hợp lệ, nhưng không hợp lệ về mặt ngữ nghĩa , vì nó không phù hợp với những gì mong đợi. (giả sử một định nghĩa chặt chẽ về những gì làm cho yêu cầu trong câu hỏi có giá trị về mặt ngữ nghĩa hay không).

Mặt khác, nếu yêu cầu được gửi với Loại Nội dung tùy chỉnh cụ thể hơn như application/vnd.mycorp.mydatatype+jsonvậy, có lẽ, chỉ định chính xác các trường được mong đợi, thì tôi sẽ nói rằng yêu cầu có thể dễ dàng bị vô hiệu hóa về mặt cú pháp, do đó phản hồi 400.

Trong trường hợp được đề cập, vì khóa bị sai, không phải giá trị , đã xảy ra lỗi cú pháp nếu có thông số kỹ thuật cho các khóa hợp lệ là gì. Nếu không có thông số kỹ thuật cho các khóa hợp lệ hoặc lỗi xảy ra với một giá trị , thì đó sẽ là một lỗi ngữ nghĩa .

|
  • 1

    Câu trả lời rất bị đánh giá thấp - cảm ơn vì lời giải thích tốt.

    – Hồ Nhã Anh 14:14:08 03/06/2016
  • 1

    Chính xác là suy nghĩ của tôi về vấn đề này! Tôi đến từ nền tảng XML SOAP và khái niệm lược đồ đã đi vào máu và các tài liệu JSON của tôi thay vì không công bố lược đồ của họ. Đối với tôi đó là liệu máy chủ có "hiểu" yêu cầu hay không. Nếu máy chủ không biết "sales_tax" là gì thì đó chỉ là 400: "Tôi không biết bạn đã gửi gì cho tôi nhưng chắc chắn không phải là điều tôi muốn."

    – Tạ Hồng Như 16:38:26 06/07/2017
8

Nghiên cứu điển hình: API GitHub

https://developer.github.com/v3/#client-errors

Có lẽ sao chép từ các API nổi tiếng là một ý tưởng khôn ngoan:

Có ba loại lỗi máy khách có thể xảy ra đối với các lệnh gọi API nhận nội dung yêu cầu:

Gửi JSON không hợp lệ sẽ dẫn đến phản hồi 400 Yêu cầu Không hợp lệ.

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

Gửi sai loại giá trị JSON sẽ dẫn đến phản hồi 400 Yêu cầu Không hợp lệ.

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

Gửi các trường không hợp lệ sẽ dẫn đến phản hồi Thực thể không thể xử lý 422.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}
|
5

Giải thích về thực thể không thể xử lý được cập nhật: ngày 6 tháng 3 năm 2017

422 thực thể không thể xử lý là gì?

Mã trạng thái 422 xảy ra khi một yêu cầu được hình thành tốt, tuy nhiên, do lỗi ngữ nghĩa, nó không thể được xử lý. Trạng thái HTTP này được giới thiệu trong RFC 4918 và đặc biệt hướng đến các tiện ích mở rộng HTTP cho Tác giả và Phiên bản phân tán Web (WebDAV).

Có một số tranh cãi ngoài kia về việc liệu các nhà phát triển có nên trả lại lỗi 400 so với 422 cho khách hàng hay không (nhiều hơn về sự khác biệt giữa cả hai trạng thái bên dưới). Tuy nhiên, trong hầu hết các trường hợp, người ta đồng ý rằng trạng thái 422 chỉ nên được trả về nếu bạn hỗ trợ các khả năng của WebDAV.

Một định nghĩa từng từ của mã trạng thái 422 được lấy từ phần 11.2 trong RFC 4918 có thể được đọc dưới đây.

Mã trạng thái 422 (Thực thể không thể xử lý) có nghĩa là máy chủ hiểu loại nội dung của thực thể yêu cầu (do đó mã trạng thái 415 (Loại phương tiện không được hỗ trợ) là không phù hợp) và cú pháp của thực thể yêu cầu là chính xác (do đó là 400 (Yêu cầu sai ) mã trạng thái không phù hợp) nhưng không thể xử lý các hướng dẫn có trong đó.

Định nghĩa tiếp tục nói:

Ví dụ, điều kiện lỗi này có thể xảy ra nếu một thân yêu cầu XML chứa các hướng dẫn XML được định dạng đúng (nghĩa là đúng về mặt cú pháp), nhưng sai về mặt ngữ nghĩa, về mặt ngữ nghĩa.

Mã trạng thái 400 so với 422

Lỗi yêu cầu xấu sử dụng mã trạng thái 400 và phải được trả lại cho máy khách nếu cú ​​pháp yêu cầu không đúng, chứa khung tin nhắn yêu cầu không hợp lệ hoặc định tuyến yêu cầu lừa đảo. Mã trạng thái này có vẻ khá giống với trạng thái thực thể không thể xử lý 422, tuy nhiên, một thông tin nhỏ phân biệt chúng là thực tế rằng cú pháp của một thực thể yêu cầu đối với lỗi 422 là chính xác trong khi cú pháp của yêu cầu tạo ra 400 lỗi không chính xác.

Việc sử dụng trạng thái 422 chỉ nên dành riêng cho các trường hợp sử dụng rất cụ thể. Trong hầu hết các trường hợp khác xảy ra lỗi máy khách do cú pháp không đúng, nên sử dụng trạng thái Yêu cầu xấu 400.

https://www.keycdn.com/support/422-un Processable-entity /

|
2

Thứ nhất đây là một câu hỏi rất hay.

400 Yêu cầu Không hợp lệ - Khi thiếu thông tin quan trọng trong yêu cầu

ví dụ: Tiêu đề ủy quyền hoặc tiêu đề loại nội dung. Mà hoàn toàn được yêu cầu bởi máy chủ để hiểu yêu cầu. Điều này có thể khác nhau từ máy chủ đến máy chủ.

422 Thực thể không thể xử lý - Khi cơ thể yêu cầu không thể được phân tích cú pháp.

Điều này ít nghiêm trọng hơn 400. Yêu cầu đã đến máy chủ. Các máy chủ đã thừa nhận yêu cầu đã có cấu trúc cơ bản ngay. Nhưng thông tin trong phần yêu cầu không thể được phân tích hoặc hiểu.

ví dụ: Content-Type: application/xmlkhi cơ thể yêu cầu là JSON.

Đây là một bài viết liệt kê mã trạng thái và việc sử dụng nó trong API REST. https://metamug.com/article/status-codes-for-rest-api.php

|
  • 1

    422 có nghĩa là cú pháp hợp lệ, nhưng nội dung thì không. Gửi JSON trong đó XML được mong đợi có nghĩa là cú pháp sai, vì vậy 400 là phản hồi chính xác trong trường hợp này.

    – Hồ Nhã Anh 10:18:59 07/11/2018
  • 1

    Chính xác như Dirk đã nói 422 có nghĩa là yêu cầu hợp lệ về mặt cú pháp (có thể được phân tích và hiểu) nhưng không hợp lệ về mặt ngữ nghĩa

    – Tạ Hồng Như 02:37:02 12/12/2018
1

Trường hợp của bạn: HTTP 400 là mã trạng thái phù hợp cho trường hợp của bạn từ phối cảnh REST vì nó không đúng về mặt cú pháp để gửi sales_taxthay vì tax, mặc dù đó là một JSON hợp lệ. Điều này thường được thi hành bởi hầu hết các khung công tác phía máy chủ khi ánh xạ JSON tới các đối tượng. Tuy nhiên, có một số triển khai REST bỏ qua mới keytrong đối tượng JSON. Trong trường hợp đó, một content-typeđặc tả tùy chỉnh để chỉ chấp nhận các trường hợp lệ có thể được thi hành bởi phía máy chủ.

Kịch bản lý tưởng cho 422:

Trong một thế giới lý tưởng, 422 được ưu tiên và thường được chấp nhận để gửi dưới dạng phản hồi nếu máy chủ hiểu loại nội dung của thực thể yêu cầu và cú pháp của thực thể yêu cầu là chính xác nhưng không thể xử lý dữ liệu vì lỗi ngữ nghĩa của nó.

Các tình huống của 400 trên 422:

Hãy nhớ rằng, mã phản hồi 422 là mã trạng thái HTTP (WebDAV) mở rộng. Vẫn còn một số ứng dụng khách / thư viện giao diện người dùng HTTP chưa được chuẩn bị để xử lý 422. Đối với họ, đơn giản như "HTTP 422 là sai, vì đó không phải là HTTP" . Từ góc độ dịch vụ, 400 không khá cụ thể.

Trong kiến ​​trúc doanh nghiệp, các dịch vụ được triển khai chủ yếu trên các lớp dịch vụ như SOA, IDM, v.v. Chúng thường phục vụ nhiều máy khách khác nhau, từ máy khách gốc rất cũ đến máy khách HTTP mới nhất. Nếu một trong các máy khách không xử lý HTTP 422, các tùy chọn là yêu cầu khách hàng nâng cấp hoặc thay đổi mã phản hồi của bạn thành HTTP 400 cho mọi người. Theo kinh nghiệm của tôi, điều này rất hiếm trong những ngày này nhưng vẫn có khả năng. Vì vậy, một nghiên cứu cẩn thận về kiến ​​trúc của bạn luôn được yêu cầu trước khi quyết định mã phản hồi HTTP.

Để xử lý tình huống như vậy, các lớp dịch vụ thường sử dụng versioninghoặc cài đặt configurationcờ cho các máy khách tuân thủ HTTP nghiêm ngặt để gửi 400 và gửi 422 cho phần còn lại của chúng. Bằng cách đó, họ cung cấp hỗ trợ tương thích ngược cho người tiêu dùng hiện tại nhưng đồng thời cung cấp khả năng cho các khách hàng mới sử dụng HTTP 422.


Bản cập nhật mới nhất cho RFC7321 cho biết:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

Điều này xác nhận rằng các máy chủ có thể gửi HTTP 400 cho yêu cầu không hợp lệ. 400 không chỉ đề cập đến lỗi cú pháp nữa , tuy nhiên, 422 vẫn là một phản hồi chính hãng miễn là khách hàng có thể xử lý nó.

|

Câu trả lời của bạn (> 20 ký tự)

Bằng cách click "Đăng trả lời", bạn đồng ý với Điều khoản dịch vụ, Chính sách bảo mật and Chính sách cookie của chúng tôi.

Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ hoặc hỏi câu hỏi của bạn.