2013-03-24 68 views
9

Các phương pháp hay nhất để trả lại mã trạng thái HTTP trong RESTful API là gì? Tôi đang sử dụng Laravel 4 cho khung công tác PHP của tôi.Thực tiễn tốt nhất cho các lỗi trong RESTful API

Trong trường hợp của một lỗi, tôi nên sử dụng

return Response::json('User Exists', 401); 

hoặc

bao gồm cờ cho success

return Response::json([ 
    'success' => false, 
    'data' => 'User Exists'], 
    401 
); 

hoặc

sử dụng 200 thay vì 4xx, dựa vào success để xác định xem có phải là một lỗi

return Response::json([ 
    'success' => false, 
    'data' => 'User Exists'], 
    200 
); 

Và trong trường hợp thành công và không có nhu cầu trả lại bất kỳ dữ liệu, bạn vẫn trở lại bất cứ điều gì?

PHP API Mã

public function getCheckUniqueEmail() { 
    // Check if Email already exist in table 'users' 
    $uniqueEmail = checkIfEmailExists(); 

    // Return JSON Response 
    if($uniqueEmail) { 
     // Validation fail (user exists) 
     return Response::json('User Exists', 401); 
    } else { 
     // Validation success 
     // - Return anything? 
    } 
} 

Trả lời

12

Khi bạn nhìn vào list of available HTTP status codes, bạn sẽ tại một số điểm nhận ra rằng có rất nhiều trong số họ, nhưng sử dụng một mình họ có thể không thực sự giải thích một lỗi bằng cách riêng của mình.

Vì vậy, để trả lời câu hỏi của bạn, có hai phần. Một là: API của bạn có thể truyền đạt các lý do lỗi như thế nào và thêm thông tin hữu ích mà người dùng API (mà trong hầu hết các trường hợp là một nhà phát triển khác) có thể đọc và hành động. Bạn nên thêm càng nhiều thông tin càng tốt, cả hai máy có thể đọc được và có thể đọc được.

Phần khác: Mã trạng thái HTTP có thể giúp phân biệt một số trạng thái lỗi (và thành công) nhất định như thế nào?

Phần sau này thực sự khó hơn một điều có thể. Có những trường hợp hiển nhiên khi 404 được sử dụng để nói "không tìm thấy". Và 500 cho bất kỳ lỗi nào là phía máy chủ.

Tôi sẽ không sử dụng trạng thái 401, trừ khi tôi thực sự muốn cho phép hoạt động thành công nếu có thông tin đăng nhập xác thực HTTP. 401 thường kích hoạt một hộp thoại trong trình duyệt, điều đó rất tệ.

Trong trường hợp nguồn cấp dữ liệu là duy nhất và đã tồn tại, trạng thái "409 Xung đột" có vẻ phù hợp. Và nếu tạo người dùng thành công, trạng thái "201 Tạo" cũng giống như một ý tưởng hay.

Lưu ý rằng có nhiều mã trạng thái hơn, một số mã liên quan đến phần mở rộng của giao thức HTTP (như DAV), một số hoàn toàn không chuẩn hóa (như trạng thái "420 Cải thiện sự bình tĩnh của bạn" từ API Twitter). Có một cái nhìn tại http://en.wikipedia.org/wiki/List_of_HTTP_status_codes để xem những gì đã được sử dụng cho đến nay, và quyết định xem bạn muốn sử dụng một cái gì đó thích hợp cho các trường hợp lỗi của bạn.

Từ kinh nghiệm của tôi, rất dễ dàng để chỉ cần chọn một mã trạng thái và sử dụng nó, nhưng thật khó để làm như vậy một cách nhất quán và phù hợp với các tiêu chuẩn hiện có.

Tôi sẽ không dừng ở đây chỉ vì những người khác có thể khiếu nại. :) Làm các giao diện RESTful đúng là một nhiệm vụ khó khăn trong chính nó, nhưng càng có nhiều giao diện, thì càng có nhiều kinh nghiệm được thu thập.

Edit:

Về phiên bản: Nó được coi là xấu thực hành để đặt một thẻ phiên bản vào URL, như vậy: example.com/api/v1/stuff Nó sẽ làm việc, nhưng nó không phải là tốt đẹp.

Nhưng điều đầu tiên là: Làm thế nào để khách hàng của bạn chỉ định loại đại diện mà anh ta muốn nhận được, tức là làm thế nào anh ta có thể quyết định nhận JSON hoặc XML? Trả lời: Với tiêu đề Accept. Anh ấy có thể gửi Accept: application/json cho JSON và Accept: application/xml cho XML. Anh ta thậm chí có thể chấp nhận nhiều loại, và nó là cho máy chủ để quyết định sau đó những gì để trở về.

Trừ khi máy chủ được thiết kế để trả lời với nhiều hơn một đại diện của tài nguyên (JSON hoặc XML, được khách hàng chọn), thực sự không có nhiều sự lựa chọn cho khách hàng. Nhưng nó vẫn là một điều tốt để có khách hàng gửi ít nhất "ứng dụng/json" như là sự lựa chọn duy nhất của mình và sau đó trả về một tiêu đề Content-type: application/json để đáp ứng. Bằng cách này, cả hai bên làm cho mình rõ ràng về những gì họ mong đợi phía bên kia để xem nội dung như thế nào.

Bây giờ cho các phiên bản. Nếu bạn đặt phiên bản vào URL, bạn có thể tạo các tài nguyên khác nhau (v1 và v2) một cách hiệu quả, nhưng thực tế bạn chỉ có một tài nguyên (= URL) với các phương thức khác nhau để truy cập nó. Việc tạo một phiên bản API mới phải diễn ra khi có thay đổi đột ngột trong các tham số của yêu cầu và/hoặc biểu diễn trong phản hồi không tương thích với phiên bản hiện tại.

Vì vậy, khi bạn tạo một API sử dụng JSON, bạn không xử lý JSON chung. Bạn đối phó với một cấu trúc JSON cụ thể mà bằng cách nào đó là duy nhất đối với API của bạn. Bạn có thể và có thể chỉ ra điều này trong máy chủ Content-type được gửi bởi máy chủ. Phần mở rộng "nhà cung cấp" có sẵn cho điều này: Content-type: application/vnd.IAMVENDOR.MYAPI+json sẽ cho mọi người biết rằng cấu trúc dữ liệu cơ bản là ứng dụng/json, nhưng đó là công ty của bạn và API của bạn thực sự cho cấu trúc nào mong đợi. Và đó chính xác là nơi phiên bản cho yêu cầu API phù hợp với: application/vnd.IAMVENDOR.MYAPI-v1+json.

Vì vậy, thay vì đặt phiên bản trong URL, bạn mong đợi khách hàng gửi tiêu đề Accept: application/vnd.IAMVENDOR.MYAPI-v1+json và bạn cũng trả lời với Content-type: application/vnd.IAMVENDOR.MYAPI-v1+json. Điều này thực sự không thay đổi gì đối với phiên bản đầu tiên, nhưng hãy xem mọi thứ phát triển như thế nào khi phiên bản 2 phát huy tác dụng.

Phương pháp tiếp cận URL sẽ tạo một tập hợp tài nguyên mới hoàn toàn không có liên quan. Khách hàng sẽ tự hỏi nếu example.com/api/v2/stuff là tài nguyên giống như example.com/api/v1/stuff. Khách hàng có thể đã tạo một số tài nguyên với API phiên bản 1 và anh đã lưu trữ URL cho công cụ này. Làm thế nào là ông phải nâng cấp tất cả các nguồn lực này để v2? Các tài nguyên thực sự không thay đổi, chúng giống nhau, điều duy nhất thay đổi là chúng trông khác trong v2.

Có, máy chủ có thể thông báo cho khách hàng bằng cách gửi chuyển hướng đến URL v2. Nhưng chuyển hướng không báo hiệu rằng khách hàng cũng phải nâng cấp phần ứng dụng khách của API.

Khi sử dụng tiêu đề chấp nhận với phiên bản, URL của tài nguyên giống nhau cho tất cả các phiên bản. Khách hàng quyết định yêu cầu tài nguyên với phiên bản 1 hoặc 2 và máy chủ có thể rất tốt và vẫn trả lời phiên bản 1 yêu cầu với phản hồi phiên bản 1, nhưng tất cả phiên bản 2 đều yêu cầu phản hồi phiên bản mới và sáng bóng 2.

Nếu máy chủ không thể trả lời yêu cầu phiên bản 1, anh ta có thể thông báo cho khách hàng bằng cách gửi trạng thái HTTP "406 Not Acceptable" (Tài nguyên được yêu cầu chỉ có thể tạo nội dung không được chấp nhận theo tiêu đề Chấp nhận được gửi trong yêu cầu.)

Khách hàng có thể gửi tiêu đề chấp nhận với cả hai phiên bản, cho phép máy chủ phản hồi bằng phiên bản anh thích nhất, tức là khách hàng thông minh có thể triển khai phiên bản 1 và 2 và hiện gửi cả tiêu đề chấp nhận và chờ để máy chủ nâng cấp từ phiên bản 1 lên 2. Máy chủ sẽ trả lời mọi câu trả lời cho dù đó là phiên bản 1 hay 2 và khách hàng có thể hành động tương ứng - anh ta không cần biết chính xác ngày nâng cấp phiên bản máy chủ.

Để tổng hợp: Đối với API rất cơ bản có giới hạn, có thể nội bộ, sử dụng ngay cả khi có phiên bản có thể quá mức cần thiết. Nhưng bạn không bao giờ biết nếu điều này sẽ đúng một năm kể từ bây giờ. Nó luôn luôn là một ý tưởng rất tốt để bao gồm một số phiên bản vào một API. Và điểm tốt nhất cho điều này là bên trong loại mime mà API của bạn sắp sử dụng. Việc kiểm tra phiên bản hiện có sẽ là không đáng kể, nhưng bạn có tùy chọn nâng cấp minh bạch sau này mà không gây nhầm lẫn cho các máy khách hiện có.

+0

Api an toàn chỉ dành cho ajax/backbonejs/jquery của trang web của riêng tôi để sử dụng. Trong trường hợp này, tôi chỉ nên dính vào cùng một mã lỗi (nói 400)? Hoặc trả về 200 cho mỗi phản hồi AJAX và kiểm tra biến 'success' để xem lỗi có xảy ra không. – Nyxynyx

+1

Không, cho biết thực tế" thành công/lỗi "cơ bản thông qua mã lỗi là một ý tưởng rất hay. Các phản hồi lỗi được xử lý khác nhau bởi các máy khách HTTP, ví dụ: họ không nên được lưu trữ vv Chỉ ra cùng một bên trong tải trọng dữ liệu cũng là một điều tốt. API của riêng tôi hoặc có "dữ liệu" về thành công hoặc "lỗi" về lỗi. Điều này về cơ bản giống như có "success = true/false" và nó hoạt động đối với tôi. Nhưng hãy biết rằng trạng thái "400 yêu cầu không hợp lệ" không phải là trạng thái lỗi chung của máy khách mà bạn nghĩ. Không có điều như vậy, bạn phải xác định trạng thái lỗi. – Sven

+2

Câu trả lời hay, Sven! Tuy nhiên, bạn nói:> Về phiên bản: Việc xem một phiên bản > thẻ vào URL tôi không đồng ý. Đây là [hướng dẫn] (http://apigee.com/about/api-best-practices/restful-api-design-second-edition) từ Apigee, người kết luận rằng * * là * thực sự là phương pháp hay nhất để sử dụng số phiên bản trong URL. Họ cũng làm rõ mã trạng thái trả lại. – unicopter

2

Tôi sẽ không sử dụng 200 trạng thái cho mọi thứ. Điều đó sẽ gây nhầm lẫn.

Jquery cho phép bạn xử lý các mã phản hồi khác nhau, có sẵn các phương pháp để sử dụng chúng trong ứng dụng của bạn và khi ứng dụng của bạn phát triển, bạn cũng có thể cung cấp API cho người khác sử dụng.

Edit: Ngoài ra tôi khuyên bạn nên xem điều này nói về Laravel và phát triển API:

http://kuzemchak.net/blog/entry/laracon-slides-and-video

+0

Liên kết video hữu ích, nhưng người nói thực hiện một số điều xấu khi triển khai API RESTful như có số phiên bản trong URL. Đó là những gì "Chấp nhận" tiêu đề được cho. – Sven

+0

@Sven bạn có thể vui lòng giải thích chi tiết hơn về cách sử dụng không? Tôi tò mò =) – msurguy

+0

Đã cập nhật câu trả lời của tôi. – Sven

1

Có một số danh sách các HTTP Status Code tại Illuminate\Http\Response mà mở rộng đến Symfony\Component\HttpFoundation\Response. Bạn có thể sử dụng nó trong lớp học của bạn.

Ví dụ:

use Illuminate\Http\Response as LaravelResponse; 
... 
return Response::json('User Exists', LaravelResponse::HTTP_CONFLICT); 

Nó nhiều hơn nữa có thể đọc được.

Các vấn đề liên quan