Tôi có nên trả lại trạng thái HTTP 400 (Yêu cầu xấu) nếu tham số đúng về mặt cú pháp, nhưng vi phạm quy tắc kinh doanh không?


56

Giả sử tôi có điểm cuối REST lấy số nguyên làm tham số:

/makeWaffles?numberOfWaffles=3

Trong trường hợp này, tôi muốn số đó dương vì tôi không thể tạo số bánh quế âm (và yêu cầu 0 bánh quế là một sự lãng phí thời gian). Vì vậy, tôi muốn từ chối mọi yêu cầu không chứa số nguyên dương. Tôi cũng muốn từ chối một yêu cầu vượt quá một số nguyên tối đa (bây giờ hãy nói rằng đó là MAX_INTEGER).

Trong trường hợp ai đó yêu cầu số lượng bánh quế không tích cực, tôi có nên trả lại trạng thái HTTP 400 (Yêu cầu xấu) không? Suy nghĩ ban đầu của tôi là có: nó không phải là một con số hợp lệ để tôi hoàn thành yêu cầu. Tuy nhiên, RFC không đề cập đến các quy tắc kinh doanh như một lý do để ném nó:

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).

Một quy tắc kinh doanh không thuộc bất kỳ một trong ba ví dụ. Nó đúng về mặt cú pháp, nó được đóng khung đúng cách và nó không lừa đảo định tuyến yêu cầu.

Vậy tôi có nên trả lại trạng thái HTTP 400 (Yêu cầu xấu) nếu tham số đúng về mặt cú pháp, nhưng vi phạm quy tắc kinh doanh không? Hoặc có một trạng thái thích hợp hơn để trở lại?



Câu trả lời:


38

Đây là một câu hỏi lớn và vẫn có liên quan cao với bối cảnh lịch sử (và các định nghĩa dường như mâu thuẫn) của mã trả về HTTP. Ngay cả trong số các câu trả lời cho câu hỏi này có những định nghĩa mâu thuẫn. Điều này có thể được làm rõ bằng cách di chuyển theo thời gian.

RFC 2616 (tháng 6 năm 1999)

10.4.1 400 Yêu cầu xấu

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.

Kể từ RFC này, mã trạng thái này chỉ áp dụng cụ thể cho các yêu cầu không hợp lệ về mặt cú pháp. Có một khoảng cách trong mã trạng thái để xác nhận ngữ nghĩa. Do đó, khi RFC 4918 xuất hiện, một mã mới đã ra đời.

RFC 4918 (tháng 6 năm 2007)

11.2. Thực thể không thể xử lý 422

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 đó. 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.

Thực thể không thể xử lý được tạo ra để lấp đầy khoảng trống xác thực ngữ nghĩa trong đặc tả ban đầu của mã trạng thái 4xx. Tuy nhiên, một RFC khác có liên quan đã xuất hiện vào năm 2014, khái quát 400 đến không còn cụ thể theo cú pháp .

RFC 7231 (tháng 6 năm 2014, đã lỗi thời RFC 2616)

6.5.1. 400 yêu cầu xấu

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).

Lưu ý rằng mô tả 422 nói rằng lý do 400 không phù hợp là vì 400 (kể từ RFC 2616) chỉ được trả về cho cú pháp yêu cầu xấu. Tuy nhiên, kể từ RFC 7231, định nghĩa lỗi cú pháp nghiêm ngặt không còn áp dụng cho 400 .

Quay trở lại câu hỏi: Trong khi 422 cụ thể hơn về mặt kỹ thuật, với bối cảnh này, tôi có thể thấy 400 hoặc 422 được sử dụng để xác thực ngữ nghĩa các tham số API. Tôi ngần ngại sử dụng 422 trong các API của riêng mình vì định nghĩa của 422 đã lỗi thời về mặt kỹ thuật tại thời điểm này (mặc dù tôi không biết nếu điều đó được công nhận chính thức ở bất cứ đâu). Bài viết được tham chiếu trong câu trả lời của Fran khuyến khích việc sử dụng 422 đã được viết vào năm 2012, hai năm trước khi RFC 7231 làm rõ HTTP 400. Chỉ cần đảm bảo tiêu chuẩn hóa cái này hay cái khác.


42

Tôi đã đọc câu trả lời đầu tiên và không thực sự đồng ý với nó bởi vì, ít nhất trong bài đọc của tôi, một yêu cầu tồi (400) có nghĩa là, "Tôi thậm chí không thể xử lý yêu cầu của bạn vì có gì đó sai về cơ bản." Và tôi đã tìm thấy bài đăng này làm cho trường hợp trả lại một 422.

từ IETF

422 Thực thể không thể xử lý (WebDAV; RFC 4918) Yêu cầu được định dạng tốt nhưng không thể thực hiện được do lỗi ngữ nghĩa

Đây có vẻ như là một phản hồi phù hợp hơn vì yêu cầu của bạn được hình thành rõ ràng, nhưng không vượt qua các quy tắc xác thực của bạn.


5
Ive nghe nó được mô tả là "400 có nghĩa là cú pháp xấu, 422 có nghĩa là ngữ nghĩa xấu."
cbojar

33
Tất cả các mã x00 là "bắt tất cả" mã chung. Một 400 là không phù hợp , chỉ là ít cụ thể .
Jack

1
Câu trả lời tốt, nhưng ansewer được cung cấp bởi @GoFree có ý nghĩa hơn đối với tôi.
Ewerton

2
Có một trường hợp thực sự mạnh mẽ để trả lại mã mà mọi người đều biết. Tuyệt đối mọi người sẽ cần phải tìm kiếm 422, và tôi cá rằng hầu hết mọi người vẫn sẽ không biết phải làm gì với nó.
sylvanaar

8

Có, đầu vào không tuân theo hợp đồng ngụ ý của điểm cuối là "một cái gì đó được coi là lỗi của máy khách" và sẽ trả về 400.

Các ngoại lệ cho điều này là nếu quy tắc kinh doanh có liên quan đến bảo mật (thì 401 Unauthorizedhoặc 403 Forbiddensẽ tốt hơn). Ngoài ra, nếu gửi 400 sẽ rò rỉ thông tin về sự tồn tại của một cái gì đó, và sau đó 404 Not Foundcó thể phù hợp hơn.


8

Không, bạn không nên. Mã HTTP có nghĩa là cho lớp HTTP của ứng dụng của bạn. Quy tắc kinh doanh là lớp hoàn toàn khác nhau và là ứng dụng cụ thể, vì vậy bạn cần đưa ra "giao thức" của riêng mình.

Hãy tưởng tượng ngày tận thế xảy ra và bạn phải chuyển từ giao thức HTTP sang sử dụng Pigeons. Chim bồ câu không có bất kỳ mã trả lại nào, vì vậy bạn sẽ cần thay đổi lớp doanh nghiệp của mình để phù hợp với điều đó. Nhưng doanh nghiệp của bạn chưa thực sự thay đổi theo bất kỳ cách nào nên bạn không cần thay đổi lớp doanh nghiệp. Nó cho thấy một sự kết hợp chặt chẽ giữa hai lớp (vận chuyển và kinh doanh).

Quay lại câu hỏi: Điều bạn nên làm là trả lại "200 OK" với phần thân mô tả những gì đã xảy ra với yêu cầu. Các đặc điểm kỹ thuật nói rõ ràng như vậy:

https://www.w3.org/Prot Protocol / rfc2616 / rfc2616-sec10.html # sec10.2.1 .

200 OK

Yêu cầu đã thành công. Các thông tin trở lại với câu trả lời phụ thuộc vào phương pháp được sử dụng trong các yêu cầu , ví dụ

POST một thực thể mô tả hoặc chứa kết quả của hành động;

Yêu cầu HTTP của bạn đã thành công chưa? Có, máy chủ web biết phải làm gì với yêu cầu đó (ví dụ: chuyển nó cho phần máy chủ của ứng dụng của bạn). Sau đó, máy chủ web chuyển yêu cầu này đến phần máy chủ trong ứng dụng của bạn, dữ liệu đã được POST, xử lý chúng (xác thực chúng trong trường hợp của bạn) và trả về một câu trả lời bình thường (trong phần phản hồi HTTP) cho phần máy khách của ứng dụng của bạn . Câu trả lời này từ phần máy chủ của ứng dụng có thể là "Tuyệt vời, dữ liệu bạn gửi cho tôi là hợp lệ" hoặc "Tôi xin lỗi, dữ liệu bạn gửi không hợp lệ". Và tùy thuộc vào ứng dụng khách của bạn để hiểu câu trả lời có nghĩa là gì.

PS: "400 Yêu cầu xấu" có nghĩa là máy chủ web không hiểu bạn muốn gì từ nó. Điều đó có nghĩa là một phần máy chủ của ứng dụng của bạn thậm chí không nhận được yêu cầu. Hoặc ít nhất đó là ý nghĩa của nó :-)

EDIT : Tôi mới nhận ra rằng bạn đang thực hiện yêu cầu GET, không phải POST. Đây là một ý tưởng tồi vì GET không nên thay đổi trạng thái của ứng dụng. GET được cho là chỉ đơn giản là lấy dữ liệu từ máy chủ. Nhưng trong yêu cầu của bạn, bạn thực sự đang thay đổi trạng thái của ứng dụng, vì vậy bạn thực sự nên sử dụng POST.


1
Có, trả lại 404 trong trường hợp đó là tốt. Tôi không nói rằng máy chủ phải luôn gửi 200 OK với lời giải thích trong cơ thể.
GoFree

Giải thích tốt hơn tôi thấy cho đến nay. Tôi có cùng một câu hỏi và dường như tất cả các từ nghĩ khác với tôi và bạn @GoFree
Ewerton

@GoFree Đây là một câu trả lời thực sự tốt để suy nghĩ lại về Thiết kế API. Nhưng không phải vậy, chúng ta sử dụng HTTP và mã phản hồi của nó như là một phần nổi bật của lớp quy tắc kinh doanh khi chúng ta sử dụng API REST?
Thomas Lauria

1
@Thomas Lauria Tôi chưa thấy triển khai API RESTFUL đúng cách. Tuy nhiên, API REST là một từ thông dụng ngày nay vì vậy mọi công ty phải sử dụng nó (từ này, không phải công nghệ) mà không thực sự hiểu khái niệm đằng sau nó. Vì vậy, có, nó đang được sử dụng sai cách ở khắp mọi nơi. Những gì lập trình viên thường tạo không phải là API REST, mà là API HTTP hoặc API QUÁ HTTP. Trên thực tế, một trong số ít các triển khai RESTFUL tốt là chính HTTP :)
GoFree

1
Sử dụng 200-OK đặc biệt hợp lý nếu ứng dụng bao gồm trường "lỗi" trong phần phản hồi để mô tả mọi lỗi cấp doanh nghiệp như giá trị đầu vào quá cao hoặc quá thấp hoặc thiếu, hết sản phẩm, v.v.
Roland

-3

Không chắc chắn rằng tất cả sẽ đồng ý, nhưng chúng tôi đang sử dụng 409 - Xung đột. Nhiều trạng thái của 409 là xung đột với trạng thái hệ thống, nhưng chúng tôi chấp nhận cách giải thích rằng xung đột của các giá trị dữ liệu nằm ngoài phạm vi được chấp nhận là có thể khắc phục được bởi người yêu cầu và việc sử dụng 409. chấp nhận được. được hình thành chính xác nhưng không thể được xử lý theo yêu cầu. Tôi phản đối tuy nhiên nếu bạn không muốn thực hiện một loạt các câu trả lời, chỉ cần đưa ra 400 vẫn được chấp nhận.


5
409 có nghĩa là "trạng thái bạn đang cố gắng đặt điều này mâu thuẫn với trạng thái mà một khách hàng khác đang cố gắng đưa nó vào", đó là để chặn việc ghi đồng thời (ví dụ: sử dụng ETags)
Jack
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.