Lỗi API REST trả về các thực tiễn tốt [đã đóng]


623

Tôi đang tìm kiếm hướng dẫn về các thực tiễn tốt khi trả về lỗi từ API REST. Tôi đang làm việc trên một API mới vì vậy tôi có thể thực hiện bất kỳ hướng nào ngay bây giờ. Hiện tại loại nội dung của tôi là XML, nhưng tôi dự định hỗ trợ JSON trong tương lai.

Bây giờ tôi đang thêm một số trường hợp lỗi, ví dụ như một khách hàng cố gắng thêm tài nguyên mới nhưng đã vượt quá dung lượng lưu trữ của anh ta. Tôi đã xử lý một số trường hợp lỗi nhất định với mã trạng thái HTTP (401 để xác thực, 403 cho ủy quyền và 404 cho URI yêu cầu xấu đơn giản). Tôi đã xem qua các mã lỗi HTTP may mắn nhưng không có phạm vi 400-417 nào có vẻ đúng để báo cáo các lỗi cụ thể của ứng dụng. Vì vậy, lúc đầu, tôi đã cố gắng trả lại lỗi ứng dụng của mình với 200 OK và một tải trọng XML cụ thể (nghĩa là trả cho chúng tôi nhiều hơn và bạn sẽ nhận được dung lượng lưu trữ mà bạn cần!) Nhưng tôi đã dừng lại để suy nghĩ về nó và nó dường như có hiệu lực (/ nhún vai trong kinh hoàng). Bên cạnh đó, có cảm giác như tôi đang chia các phản hồi lỗi thành các trường hợp riêng biệt, vì một số là mã trạng thái http được điều khiển và một số khác là hướng nội dung.

Vậy các khuyến nghị của ngành là gì? Các thực tiễn tốt (vui lòng giải thích lý do tại sao!) Và cũng như vậy, từ máy khách POV, cách xử lý lỗi nào trong API REST giúp mã máy khách dễ dàng hơn?


7
Chỉ cần làm rõ: Tôi không quan tâm lắm đến việc trả lại mã trạng thái HTTP cụ thể nào, nhưng liệu đó có phải là cách thực hành REST tốt để kết hợp các lỗi tải trọng với mã trạng thái HTTP hay tốt hơn là chỉ dựa vào tải trọng.
Remus Rusanu

3
Sổ tay thiết kế API REST bao quát chủ đề này khá tốt.
Remus Rusanu

12
Câu hỏi không hỏi ý kiến, nhưng để được hướng dẫn / khuyến nghị và nên được mở lại và sử dụng làm tài liệu tham khảo. Câu hỏi đóng cửa năm 2016 là gì, được tạo ra vào năm 2009, có hơn 400 phiếu bầu và không có câu trả lời nào dựa trên ý kiến
Michael Freidgeim

4
Hầu hết không đề cập đến, nhưng sử dụng mã lỗi HTTP có thể dẫn đến các vấn đề liên quan đến nguyên nhân chính của vấn đề. HTTP là giao thức truyền tải và 404 phải chỉ ra rằng có vấn đề với mức độ truyền tải URLon (ví dụ: đường dẫn sai). Nếu ứng dụng không thể tìm thấy tập dữ liệu theo id của nó, thì đây là lỗi cấp độ ứng dụng (không phải lỗi cấp độ vận chuyển) và 404, như được đề xuất bởi người dùng mã trạng thái http yên tĩnh, có thể dẫn đến kết luận sai. Nói chung, tôi không thích sự kết hợp của lớp vận chuyển và ứng dụng trong việc sử dụng mã trạng thái.
SCI

Câu trả lời:


220

Vì vậy, lúc đầu, tôi đã cố gắng trả lại lỗi ứng dụng của mình với 200 OK và một tải trọng XML cụ thể (nghĩa là trả cho chúng tôi nhiều hơn và bạn sẽ nhận được dung lượng lưu trữ mà bạn cần!) Nhưng tôi đã dừng lại để suy nghĩ về nó và nó dường như có hiệu lực (/ nhún vai trong kinh hoàng).

Tôi sẽ không trả lại 200 trừ khi thực sự không có gì sai với yêu cầu. Từ RFC2616 , 200 có nghĩa là "yêu cầu đã thành công."

Nếu vượt quá dung lượng lưu trữ của khách hàng (vì bất kỳ lý do gì), tôi sẽ trả lại 403 (Bị cấm):

Máy chủ hiểu yêu cầu, nhưng từ chối thực hiện nó. Ủy quyền sẽ không giúp đỡ và yêu cầu KHÔNG NÊN lặp lại. Nếu phương thức yêu cầu không phải là CHÍNH và máy chủ muốn công khai lý do tại sao yêu cầu chưa được thực hiện, thì NÊN mô tả lý do từ chối trong thực thể. Nếu máy chủ không muốn cung cấp thông tin này cho khách hàng, mã trạng thái 404 (Không tìm thấy) có thể được sử dụng thay thế.

Điều này cho khách hàng biết rằng yêu cầu đã ổn, nhưng nó đã thất bại (điều mà 200 không thực hiện được). Điều này cũng cung cấp cho bạn cơ hội để giải thích vấn đề (và giải pháp của nó) trong cơ thể phản hồi.

Những điều kiện lỗi cụ thể khác bạn đã có trong tâm trí?


6
Tôi nên bao gồm thông báo lỗi chi tiết của tôi trong cơ thể, tức là. một cặp mã / chuỗi XML? Làm thế nào là khách hàng đối phó tốt nhất với điều này? Chẳng hạn, tôi biết các khách hàng dựa trên C # WebRequest sẽ ném 'Yêu cầu xấu' hoặc 'Bị cấm' và không cung cấp cho cơ quan phản hồi.
Remus Rusanu

18
Phần thân của 403 "nên" chứa các chi tiết về lỗi. Liệu một khách hàng có sẵn sàng sử dụng thông tin hay không là một câu chuyện khác. Nó có ý nghĩa nhất đối với định dạng này giống với định dạng cho tất cả các tải trọng khác (ví dụ: XML, JSON).
Giàu Apodaca

1
... Và nếu các chi tiết không được trả lại trong 403, thì "có thể" sử dụng 404 "(mặc dù nghe có vẻ không phải là lựa chọn tốt nhất đối với tôi).
Giàu Apodaca

6
Tùy chọn 404 dành cho sự kiện 403 có thể tiết lộ chi tiết về ứng dụng mà bạn không muốn người dùng trái phép biết về - ví dụ: nếu người dùng không phải quản trị viên truy cập URL chỉ dành cho quản trị viên, bạn có thể không muốn người dùng đó để biết rằng đó là một URL hợp lệ cho quản trị viên, v.v. Trong trường hợp này, 403 là hoàn toàn phù hợp.
Greg Campbell

16
Tôi cảm thấy đây là một câu trả lời khá hữu ích. Tôi đã nghĩ rằng khía cạnh quan trọng hơn liên quan đến việc liệu các trạng thái chỉ nên được sử dụng hay liệu thông tin lỗi sẽ được trả lại trong tải trọng, hoặc cả hai, v.v ... Và sau đó CÁCH nên thêm thông tin vào tải trọng. Trạng thái cụ thể được sử dụng chỉ nhằm vào một khía cạnh cụ thể của câu hỏi.
Manachi

584

Một tài nguyên tuyệt vời để chọn mã lỗi HTTP chính xác cho API của bạn: http://www.codetinkerer.com/2015/12/04/ch rủi-an-http-status-code.html

Một đoạn trích từ bài báo:

Bắt đầu từ đâu:

nhập mô tả hình ảnh ở đây

2XX / 3XX:

nhập mô tả hình ảnh ở đây

4XX:

nhập mô tả hình ảnh ở đây

5XX:

nhập mô tả hình ảnh ở đây


1
422 Đặc biệt là một phần mở rộng WebDAV. Tôi nghĩ rằng không nên ở đây.
Mario

@Mario Đó là thành ngữ trong API của Ruby on Rails để trả về 422 theo các điều kiện được chỉ định ở đây. Rất nhiều điều tốt theo cách tiếp cận này. Bạn sẽ thay thế việc sử dụng 422 để làm gì?
Kelsey Hannan

400 cũ thường xuyên
Andbdrew

Cảm ơn bạn. Điều gì có nghĩa là "Bạn đang giận dữ từ bỏ Internet?"?
RoutesMaps.com 24/12/18


87

Lựa chọn chính là bạn có muốn coi mã trạng thái HTTP là một phần của API REST hay không.

Cả hai cách đều hoạt động tốt. Tôi đồng ý rằng, nói đúng ra, một trong những ý tưởng của REST là bạn nên sử dụng mã Trạng thái HTTP như một phần của API của mình (trả lại 200 hoặc 201 cho một hoạt động thành công và 4xx hoặc 5xx tùy thuộc vào các trường hợp lỗi khác nhau.) Tuy nhiên , không có cảnh sát REST. Bạn có thể làm những gì bạn muốn. Tôi đã thấy các API không phải REST quá lớn được gọi là "RESTful".

Tại thời điểm này (tháng 8 năm 2015) tôi khuyên bạn nên sử dụng mã Trạng thái HTTP như một phần của API. Bây giờ dễ dàng hơn để xem mã trả về khi sử dụng các khung công tác so với trước đây. Đặc biệt, giờ đây dễ dàng hơn để thấy trường hợp trả lại không phải 200 và cơ thể của các phản hồi không 200 so với trước đây.

Mã trạng thái HTTP là một phần của api của bạn

  1. Bạn sẽ cần cẩn thận chọn mã 4xx phù hợp với điều kiện lỗi của mình. Bạn có thể bao gồm phần còn lại, xml hoặc tin nhắn văn bản dưới dạng tải trọng bao gồm mã phụ và nhận xét mô tả.

  2. Các máy khách sẽ cần sử dụng khung phần mềm cho phép chúng lấy mã trạng thái cấp HTTP. Thường làm có thể, không phải lúc nào cũng thẳng thắn.

  3. Các máy khách sẽ phải phân biệt giữa các mã trạng thái HTTP chỉ ra lỗi giao tiếp và mã trạng thái của riêng bạn cho biết sự cố ở cấp ứng dụng.

Mã trạng thái HTTP KHÔNG phải là một phần của api của bạn

  1. Mã trạng thái HTTP sẽ luôn là 200 nếu ứng dụng của bạn nhận được yêu cầu và sau đó được trả lời (cả trường hợp thành công và lỗi)

  2. TẤT CẢ các câu trả lời của bạn nên bao gồm thông tin "phong bì" hoặc "tiêu đề". Điển hình như:

    phong bì_ver: 1.0
    trạng thái: # sử dụng bất kỳ mã nào bạn thích. Dự trữ mã để thành công.
    tin nhắn: "ok" # Một chuỗi con người phản ánh mã. Hữu ích cho việc gỡ lỗi.
    data: ... # Dữ liệu của phản hồi, nếu có.
  3. Phương pháp này có thể dễ dàng hơn cho khách hàng vì trạng thái cho phản hồi luôn ở cùng một vị trí (không cần mã phụ), không giới hạn mã, không cần tìm nạp mã trạng thái cấp HTTP.

Đây là một bài đăng với ý tưởng tương tự: http://yuiblog.com/blog/2008/10/15/datitable-260-part-one/

Các vấn đề chính:

  1. Hãy chắc chắn bao gồm số phiên bản để sau này bạn có thể thay đổi ngữ nghĩa của api nếu cần.

  2. Tài liệu ...


8
Ty. Lựa chọn 2 có vẻ như SOAP trong quần áo nghỉ ngơi ...
Remus Rusanu

138
Không, đào hầm mọi thứ qua 200 không hề yên tĩnh chút nào. Nó ngăn các bên trung gian hiểu kết quả của một hoạt động, nó sẽ giết bất kỳ hình thức lưu trữ nào, nó che giấu ngữ nghĩa của hoạt động và áp đặt việc hiểu nội dung của thông báo để xử lý lỗi, vi phạm ràng buộc các thông báo độc lập.
SerialSeb

13
Trả lại chi tiết lỗi với 200 có thể không phải là RESTful, nhưng dù sao đây cũng là một câu trả lời hữu ích (nếu bạn bỏ qua nhận xét "Cả hai cách đều yên tĩnh") Điểm lớn hơn có thể là API RESTful có thể không phải là lựa chọn tốt nhất cho OP.
MB.

3
Dường như có một sự hiểu biết chung rằng bạn có thể làm bất cứ điều gì bạn muốn với giao thức HTTP và vẫn là "RESTy", điều đó là sai. Sử dụng giao thức cho những gì nó được viết, đó là một trong những ý tưởng cốt lõi của REST. Vì vậy, mã trạng thái phải là một phần của giao thức của bạn.
Ariel M.

Điểm của mã trạng thái là cung cấp một ngôn ngữ hiểu biết chung giữa các ngôn ngữ lập trình, khung và phương pháp tiếp cận đa dạng. Ý nghĩa mã trạng thái gần với phổ quát: cơ thể tùy chỉnh của bạn - vốn đã tăng thêm độ phức tạp thông qua cú pháp tùy chỉnh mà khách hàng API của bạn phải học - thì không.
Kelsey Hannan

40

Hãy nhớ rằng có nhiều mã trạng thái hơn các mã được xác định trong HTTP / 1.1 RFC, sổ đăng ký IANA có tại http://www.iana.org/assignments/http-status-codes . Đối với trường hợp bạn đề cập mã trạng thái 507 nghe có vẻ đúng.


3
Hmm, trong khi nhìn thoáng qua "507 Dung lượng không đủ" có vẻ phù hợp, tôi sẽ không thích sử dụng nó vì nó được dùng như một tiện ích mở rộng WebDAV (khá cụ thể) chứ không phải là "bạn hết dung lượng" ngoại lệ. Tuy nhiên, tôi cho rằng bạn có thể sử dụng nó.
Tối đa

1
Không, nó hoàn toàn không dành riêng cho WebDAV. Có một lý do tại sao có một sổ đăng ký mã trạng thái HTTP.
Julian Reschke

26
Tôi không đồng ý với 507mục đích này. Giải thích của tôi 507là máy chủ hết dung lượng, không phải tài khoản hết dung lượng.
Patrick

12
Tôi đồng ý với Patrick. 5xxlỗi là lỗi để làm với máy chủ.
Sean

10
418: "Tôi là một ấm trà" ngụ ý rằng không gian lưu trữ quá ít (như một ấm trà là ít) chứ không phải lớn và do đó là hết không gian.
Steve Konves

22

Như những người khác đã chỉ ra, có một thực thể phản hồi trong mã lỗi là hoàn toàn được phép.

Hãy nhớ rằng lỗi 5xx là phía máy chủ, hay còn gọi là máy khách không thể thay đổi bất cứ điều gì thành yêu cầu của nó để thực hiện yêu cầu. Nếu vượt quá hạn ngạch của khách hàng, đó chắc chắn không phải là lỗi máy chủ, vì vậy nên tránh 5xx.


Tôi sẽ không đồng ý. Hạn ngạch vượt quá sẽ là lỗi máy chủ (5xx) vì: Yêu cầu của khách hàng là hợp lệ và sẽ bị hủy bỏ nếu theo hạn ngạch, quy định trong 400 bộ sưu tập.
mikek3332002

4
Nhưng máy chủ đã không làm gì sai.
Charlie Schliesser

19

Có hai loại lỗi. Lỗi ứng dụng và lỗi HTTP. Các lỗi HTTP chỉ là để cho trình xử lý AJAX của bạn biết rằng mọi thứ đã ổn và không nên được sử dụng cho bất kỳ điều gì khác.

5xx Lỗi máy chủ

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

2xx thành công

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

Tuy nhiên, cách bạn thiết kế lỗi ứng dụng thực sự phụ thuộc vào bạn. Stack Overflow ví dụ gửi ra một đối tượng với response, datamessagetài sản. Phản hồi tôi tin có chứa truehoặc falseđể cho biết liệu thao tác có thành công hay không (thường là cho các thao tác ghi). Dữ liệu chứa tải trọng (thường dành cho các hoạt động đọc) và thông báo chứa bất kỳ siêu dữ liệu bổ sung hoặc thông báo hữu ích nào (chẳng hạn như thông báo lỗi khi responsefalse).


2
400 cũng hữu ích để chỉ ra một vấn đề trong ứng dụng khách.
heo

19

Tôi biết điều này là rất muộn cho bữa tiệc, nhưng bây giờ, vào năm 2013, chúng tôi có một vài loại phương tiện để xử lý lỗi theo kiểu phân tán (RESTful) phổ biến. Xem "vnd.error", application / vnd.error + json ( https://github.com/blongden/vnd.error ) và "Chi tiết vấn đề cho API HTTP", ứng dụng / vấn đề + json ( https: // tools. ietf.org/html/draft-nottingham-http-pro Hiệu-05 ).


2
Cảm ơn các liên kết. dự thảo-nottingham-http-vấn đề hiện là một tiêu chuẩn được đề xuất: datatracker.ietf.org/doc/rfc7807
seanf

9

Đã đồng ý. Triết lý cơ bản của REST là sử dụng cơ sở hạ tầng web. Mã trạng thái HTTP là khung nhắn tin cho phép các bên liên lạc với nhau mà không làm tăng tải trọng HTTP. Chúng đã được thiết lập các mã phổ quát truyền đạt trạng thái phản hồi và do đó, để thực sự RESTful, các ứng dụng phải sử dụng khung này để truyền đạt trạng thái phản hồi.

Gửi phản hồi lỗi trong phong bì HTTP 200 là sai lệch và buộc khách hàng (người tiêu dùng api) phân tích thông điệp, rất có thể theo cách không chuẩn hoặc độc quyền. Điều này cũng không hiệu quả - bạn sẽ buộc khách hàng của mình phân tích tải trọng HTTP mỗi lần để hiểu trạng thái phản hồi "thực". Điều này làm tăng xử lý, thêm độ trễ và tạo môi trường cho khách hàng mắc lỗi.


3
Cho dù bạn có phản hồi thành công hay phản hồi thất bại, rất có thể bạn sẽ phân tích cú pháp phản hồi. Nếu đó là một lỗi, bạn muốn phân tích nó để đưa ra thông báo lỗi. Các phản hồi lỗi thường nhỏ và nhanh chóng phân tích cú pháp. Tôi không nghĩ rằng chúng ta nên quan tâm đến việc cố gắng tối ưu hóa để tránh phân tích phản hồi lỗi. Bạn có thể vứt bỏ phản hồi lỗi mà không phân tích cú pháp không? Theo tôi thì không khôn ngoan.
AgilePro

3
Nếu bạn nhận được 200 OK, bạn cũng có thể chọn không phân tích cú pháp, tùy thuộc vào quy tắc kinh doanh của bạn. Vấn đề không phải là liệu chúng ta có phân tích nó mọi lúc hay không. Vấn đề là ý định - ý định của 200 OK là gì? Bạn đang làm hỏng ý định bằng cách gửi thông báo lỗi được gói trong 200 OK.
Kingz

1
"ý định của 200 OK là gì?" - chỉ ra sự thành công của lớp vận chuyển. Yêu cầu đã được nhận và trả lời thành công, chỉ có một vấn đề cụ thể của ứng dụng không liên quan gì đến HTTP. +++ Đặt cách khác: Gửi 404 trong thế giới REST có nghĩa là không tìm thấy thứ gì đó , có thể URL bị sai hoặc tài nguyên được xử lý hoặc bất kỳ thứ gì khác không được tìm thấy. Nếu không phân tích thông điệp, bạn không thể. IMHO REST chỉ là các lớp conflating.
maaartinus

Liên kết là chuẩn mực. Nó cung cấp cho bạn một cú pháp để giải quyết vấn đề phù hợp với lý luận của bạn và giải phóng bạn để tập trung vào lớp doanh nghiệp. Đồng ý về tình trạng vận chuyển sau này - đó là mục đích ở nơi đầu tiên - REST không được phát minh / đề xuất đồng thời với HTTP - nó xuất hiện sau đó và chỉ đơn giản là quyết định sử dụng cơ sở hạ tầng hiện có để đại diện cho STATE và THAY ĐỔI của họ.
Kingz


5

Hãy bám vào ngữ nghĩa của giao thức. Sử dụng 2xx cho các phản hồi thành công và 4xx, 5xx cho các phản hồi lỗi - có thể là ngoại lệ kinh doanh của bạn hoặc khác. Đã sử dụng 2xx cho bất kỳ phản hồi nào là trường hợp sử dụng dự định trong giao thức, họ sẽ không có mã trạng thái khác ở vị trí đầu tiên.


3

Đừng quên các lỗi 5xx cũng như các lỗi ứng dụng.

Trong trường hợp này thì khoảng 409 (Xung đột)? Điều này giả định rằng người dùng có thể khắc phục sự cố bằng cách xóa các tài nguyên được lưu trữ.

Nếu không, 507 (không hoàn toàn tiêu chuẩn) cũng có thể hoạt động. Tôi sẽ không sử dụng 200 trừ khi bạn sử dụng 200 cho các lỗi nói chung.


-2

Nếu vượt quá hạn ngạch máy khách, đó là lỗi máy chủ, hãy tránh 5xx trong trường hợp này.


3
Tại sao tránh các lỗi loạt 5xx khi chúng là lỗi máy chủ?
mikek3332002

7
'vượt quá hạn ngạch khách hàng' không phải là lỗi máy chủ, đó là hạn chế của máy khách và phải dưới 4xx.
MyGGaN
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.